using System.Text.Json; namespace PlotLine.Models; public static class CharacterEnrichmentStatuses { public const string Queued = "Queued"; public const string Running = "Running"; public const string Completed = "Completed"; public const string Failed = "Failed"; public const string Superseded = "Superseded"; } public sealed class CharacterEnrichmentRun { public int CharacterEnrichmentRunID { get; set; } public int ProjectID { get; set; } public int BookID { get; set; } public int UserID { get; set; } public int? CharacterID { get; set; } public int? StoryIntelligenceBookPipelineID { get; set; } public string CharacterResolutionVersion { get; set; } = string.Empty; public string Status { get; set; } = CharacterEnrichmentStatuses.Queued; public int TotalCharacters { get; set; } public int ProcessedCharacters { get; set; } public string? CurrentStage { get; set; } public string? CurrentMessage { get; set; } public DateTime QueuedUtc { get; set; } public DateTime? StartedUtc { get; set; } public DateTime? CompletedUtc { get; set; } public DateTime? FailedUtc { get; set; } public int AttemptCount { get; set; } public string? Model { get; set; } public int? InputTokens { get; set; } public int? OutputTokens { get; set; } public int? TotalTokens { get; set; } public long? DurationMs { get; set; } public string? ErrorMessage { get; set; } public string? ErrorDetail { get; set; } public DateTime UpdatedUtc { get; set; } public bool WasCoalesced { get; set; } } public sealed class CharacterEnrichmentQueueRequest { public int ProjectID { get; init; } public int BookID { get; init; } public int UserID { get; init; } public int? StoryIntelligenceBookPipelineID { get; init; } public string CharacterResolutionVersion { get; init; } = string.Empty; } public sealed class CharacterEnrichmentCharacterQueueRequest { public int CharacterID { get; init; } public int UserID { get; init; } public int? BookID { get; init; } } public sealed class CharacterEnrichmentCharacterStatus { public int CharacterID { get; init; } public int? BookID { get; init; } public int? CharacterEnrichmentRunID { get; init; } public string Status { get; init; } = "Not analysed"; public string? CurrentStage { get; init; } public string? CurrentMessage { get; init; } public DateTime? LastAnalysedUtc { get; init; } public string? ErrorMessage { get; init; } public string? Summary { get; init; } public string? DateOfBirth { get; init; } public string? AgeAtStartOfSeries { get; init; } public string? Sex { get; init; } public string? Height { get; init; } public string? EyeColour { get; init; } public DateTime UpdatedUtc { get; init; } = DateTime.UtcNow; public bool IsActive => Status is CharacterEnrichmentStatuses.Queued or CharacterEnrichmentStatuses.Running; public bool IsCompleted => Status == CharacterEnrichmentStatuses.Completed; } public sealed class CharacterEnrichmentProgressUpdate { public int CharacterEnrichmentRunID { get; init; } public int TotalCharacters { get; init; } public int ProcessedCharacters { get; init; } public string CurrentStage { get; init; } = string.Empty; public string CurrentMessage { get; init; } = string.Empty; } public sealed class CharacterEnrichmentCompletionRequest { public int CharacterEnrichmentRunID { get; init; } public string Model { get; init; } = string.Empty; public int? InputTokens { get; init; } public int? OutputTokens { get; init; } public int? TotalTokens { get; init; } public long? DurationMs { get; init; } } public sealed class CharacterEnrichmentContext { public int ProjectID { get; init; } public int BookID { get; init; } public string BookTitle { get; init; } = string.Empty; public string? StoryEra { get; init; } public DateTime? SeriesStartDate { get; init; } public IReadOnlyList Characters { get; init; } = []; } public sealed class CharacterEnrichmentCharacterContext { public int CharacterID { get; init; } public string CharacterName { get; init; } = string.Empty; public DateTime? BirthDate { get; init; } public int? AgeAtSeriesStart { get; init; } public string? Height { get; init; } public string? EyeColour { get; init; } public string? DefaultDescription { get; init; } public IReadOnlyList Aliases { get; init; } = []; public IReadOnlyList Scenes { get; init; } = []; } public sealed class CharacterEnrichmentSceneContext { public int SceneID { get; init; } public int ChapterID { get; init; } public decimal ChapterNumber { get; init; } public string ChapterTitle { get; init; } = string.Empty; public decimal SceneNumber { get; init; } public string SceneTitle { get; init; } = string.Empty; public string SourceText { get; init; } = string.Empty; } public sealed class CharacterEnrichmentResult { public string SchemaVersion { get; init; } = "1"; public IReadOnlyList Characters { get; init; } = []; public static CharacterEnrichmentResult FromJson(string json) => JsonSerializer.Deserialize( json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) ?? new(); } public sealed class CharacterEnrichmentCharacterResult { public int CharacterID { get; init; } public string Summary { get; init; } = string.Empty; public decimal Confidence { get; init; } public CharacterEnrichmentFactResult DateOfBirth { get; init; } = new(); public CharacterEnrichmentFactResult AgeAtStartOfSeries { get; init; } = new(); public CharacterEnrichmentFactResult Sex { get; init; } = new(); public CharacterEnrichmentFactResult Height { get; init; } = new(); public CharacterEnrichmentFactResult EyeColour { get; init; } = new(); public IReadOnlyList EvidenceSceneIDs { get; init; } = []; } public sealed class CharacterEnrichmentFactResult { public string? Value { get; init; } public decimal Confidence { get; init; } public string? Evidence { get; init; } public int? SceneID { get; init; } } public sealed class CharacterEnrichmentProgressEvent { public int CharacterEnrichmentRunID { get; init; } public int UserID { get; init; } public int ProjectID { get; init; } public int BookID { get; init; } public int? CharacterID { get; init; } public string Status { get; init; } = string.Empty; public int TotalCharacters { get; init; } public int ProcessedCharacters { get; init; } public string CurrentStage { get; init; } = string.Empty; public string CurrentMessage { get; init; } = string.Empty; public string? ErrorMessage { get; init; } public DateTime UpdatedUtc { get; init; } = DateTime.UtcNow; public bool IsActive => Status is CharacterEnrichmentStatuses.Queued or CharacterEnrichmentStatuses.Running; public bool IsCompleted => Status == CharacterEnrichmentStatuses.Completed; }