using System.Text; using Core.Entities; using Core.Models; using Core.Parsers; using Microsoft.Extensions.Configuration; namespace Core.Services; /// /// Service implementation for parsing event occurrence text data. /// Wraps EventOccurrenceParser to support text input and error collection. /// public class EventOccurrenceParserService : IEventOccurrenceParserService { private readonly LocationParsingConfiguration? _locationConfig; public EventOccurrenceParserService(IConfiguration? configuration = null) { // Load location parsing configuration from IConfiguration if provided if (configuration != null) { _locationConfig = configuration.GetSection("LocationParsingSettings").Get() ?? LocationParsingConfiguration.Default; } else { _locationConfig = LocationParsingConfiguration.Default; } } /// public EventOccurrenceParseResult ParseFromText(string text, ICollection events) { var result = new EventOccurrenceParseResult(); if (string.IsNullOrWhiteSpace(text)) { result.Errors.Add("Input text is empty or whitespace."); return result; } try { // Create a temporary file from the text content var tempFile = Path.GetTempFileName(); try { File.WriteAllText(tempFile, text, Encoding.UTF8); var fileInfo = new FileInfo(tempFile); // Use the existing EventOccurrenceParser with location configuration var parser = new EventOccurrenceParser(fileInfo, events, _locationConfig); var parserResult = parser.Parse(); // Copy occurrences from parser result var parsedOccurrences = parserResult.Occurrences; // Convert parsed occurrences to result format, handling special event types foreach (var kvp in parsedOccurrences) { var eventDefinition = kvp.Key; var occurrences = kvp.Value; // Check if this is a special event type (not stored in database) if (eventDefinition == EventDefinition.GeneralSchedule || eventDefinition == EventDefinition.MeetTheCandidates || eventDefinition == EventDefinition.ChapterOfficerMeeting || eventDefinition == EventDefinition.VotingDelegateMeeting || eventDefinition == EventDefinition.SocialGathering) { // For special events, set EventDefinitionId to null and set SpecialEventType foreach (var occurrence in occurrences) { occurrence.EventDefinitionId = null; occurrence.SpecialEventType = eventDefinition switch { var ed when ed == EventDefinition.GeneralSchedule => "GeneralSchedule", var ed when ed == EventDefinition.MeetTheCandidates => "MeetTheCandidates", var ed when ed == EventDefinition.ChapterOfficerMeeting => "ChapterOfficerMeeting", var ed when ed == EventDefinition.VotingDelegateMeeting => "VotingDelegateMeeting", var ed when ed == EventDefinition.SocialGathering => "SocialGathering", _ => throw new InvalidOperationException($"Unknown special event type: {eventDefinition.Name}") }; } // Add to result with the special EventDefinition as key result.Occurrences[eventDefinition] = occurrences; } else { // For regular events, set EventDefinitionId and ensure SpecialEventType is null foreach (var occurrence in occurrences) { occurrence.EventDefinitionId = eventDefinition.Id; occurrence.SpecialEventType = null; } result.Occurrences[eventDefinition] = occurrences; } } // Copy parsing issues from parser result result.Issues.AddRange(parserResult.Issues); } finally { // Clean up temporary file try { if (File.Exists(tempFile)) { File.Delete(tempFile); } } catch { // Ignore cleanup errors } } } catch (Exception ex) { result.Errors.Add($"Error parsing text: {ex.Message}"); if (ex.InnerException != null) { result.Errors.Add($"Inner exception: {ex.InnerException.Message}"); } } return result; } }