namespace PlotLine.Models; public static class StoryIntelligenceJobStatuses { public const string Pending = "Pending"; public const string Preparing = "Preparing"; public const string ReadingScenes = "ReadingScenes"; public const string AnalysingCharacters = "AnalysingCharacters"; public const string AnalysingRelationships = "AnalysingRelationships"; public const string AnalysingLocations = "AnalysingLocations"; public const string AnalysingAssets = "AnalysingAssets"; public const string AnalysingTimeline = "AnalysingTimeline"; public const string Finalising = "Finalising"; public const string Completed = "Completed"; public const string Cancelled = "Cancelled"; public const string Failed = "Failed"; } public sealed class StoryIntelligenceJob { public Guid JobID { get; init; } public int ConsentID { get; init; } public int UserID { get; init; } public int ProjectID { get; init; } public int BookID { get; init; } public string Status { get; init; } = StoryIntelligenceJobStatuses.Pending; public DateTime CreatedUtc { get; init; } public DateTime? StartedUtc { get; init; } public DateTime? CompletedUtc { get; init; } public DateTime? CancelledUtc { get; init; } public int ProgressPercent { get; init; } public string CurrentStage { get; init; } = StoryIntelligenceJobStatuses.Pending; public string CurrentMessage { get; init; } = "Story Intelligence is queued."; public string? EstimatedRemaining { get; init; } public string? ErrorMessage { get; init; } public DateTime UpdatedUtc { get; init; } public bool IsActive => Status is StoryIntelligenceJobStatuses.Pending or StoryIntelligenceJobStatuses.Preparing or StoryIntelligenceJobStatuses.ReadingScenes or StoryIntelligenceJobStatuses.AnalysingCharacters or StoryIntelligenceJobStatuses.AnalysingRelationships or StoryIntelligenceJobStatuses.AnalysingLocations or StoryIntelligenceJobStatuses.AnalysingAssets or StoryIntelligenceJobStatuses.AnalysingTimeline or StoryIntelligenceJobStatuses.Finalising; public bool IsCompleted => string.Equals(Status, StoryIntelligenceJobStatuses.Completed, StringComparison.Ordinal); public bool IsCancelled => string.Equals(Status, StoryIntelligenceJobStatuses.Cancelled, StringComparison.Ordinal); } public sealed class StoryIntelligenceJobProgress { public Guid JobID { get; init; } public int UserID { get; init; } public int ProjectID { get; init; } public int BookID { get; init; } public string Status { get; init; } = StoryIntelligenceJobStatuses.Pending; public string CurrentStage { get; init; } = StoryIntelligenceJobStatuses.Pending; public string CurrentMessage { get; init; } = "Story Intelligence is queued."; public int ProgressPercent { get; init; } public string? EstimatedRemaining { get; init; } public string ElapsedTime { get; init; } = "0 min"; public string? ErrorMessage { get; init; } public DateTime UpdatedUtc { get; init; } public bool IsActive { get; init; } public bool IsCompleted { get; init; } } public sealed class StoryIntelligenceOptions { public string ApiKey { get; init; } = string.Empty; public string Model { get; init; } = string.Empty; public decimal Temperature { get; init; } = 0.2m; public int MaxOutputTokens { get; init; } = 4000; public int TimeoutSeconds { get; init; } = 120; } public sealed class StoryIntelligenceRun { public Guid RunId { get; init; } = Guid.NewGuid(); public int ProjectId { get; init; } public int BookId { get; init; } public DateTime StartedUtc { get; init; } = DateTime.UtcNow; public DateTime? CompletedUtc { get; init; } public string Status { get; init; } = "Pending"; public string PromptVersion { get; init; } = string.Empty; public string Model { get; init; } = string.Empty; public int? InputTokens { get; init; } public int? OutputTokens { get; init; } public decimal? EstimatedCost { get; init; } public bool Cancelled { get; init; } public string? ErrorMessage { get; init; } } public sealed class StoryIntelligenceClientResult { public string RawResponseText { get; init; } = string.Empty; public string Model { get; init; } = string.Empty; public TimeSpan Duration { get; init; } public int RetryCount { get; init; } public int? InputTokens { get; init; } public int? OutputTokens { get; init; } public decimal? EstimatedCost { get; init; } }