using System.Text.Json.Serialization; namespace PlotLine.Models; public sealed class PlotLineImportPackage { public string? PackageVersion { get; set; } public string? Source { get; set; } public ImportProjectDto Project { get; set; } = new(); public List Characters { get; set; } = []; public List Locations { get; set; } = []; public List PlotLines { get; set; } = []; public List StoryAssets { get; set; } = []; public List Books { get; set; } = []; [JsonExtensionData] public Dictionary? ExtensionData { get; set; } } public sealed class ImportProjectDto { public string Title { get; set; } = string.Empty; public string? Description { get; set; } public string? Notes { get; set; } } public sealed class ImportBookDto { public string Title { get; set; } = string.Empty; public string? Subtitle { get; set; } public int SeriesOrder { get; set; } public bool DependsOnPreviousBook { get; set; } public string? Description { get; set; } public string? Notes { get; set; } public List Chapters { get; set; } = []; } public sealed class ImportCharacterDto { public string Name { get; set; } = string.Empty; public string? DisplayName { get; set; } public string? ShortName { get; set; } public string? Role { get; set; } public int? Importance { get; set; } public string? Description { get; set; } public string? Notes { get; set; } } public sealed class ImportLocationDto { public string Name { get; set; } = string.Empty; public string? DisplayName { get; set; } public string? Type { get; set; } public string? ParentLocationName { get; set; } public string? Description { get; set; } public string? Notes { get; set; } } public sealed class ImportPlotLineDto { public string Name { get; set; } = string.Empty; public string? DisplayName { get; set; } public string? Type { get; set; } public int? Importance { get; set; } public string? Description { get; set; } public string? Notes { get; set; } public List Threads { get; set; } = []; } public sealed class ImportPlotThreadDto { public string Name { get; set; } = string.Empty; public string? DisplayName { get; set; } public string? Type { get; set; } public string? Status { get; set; } public int? Importance { get; set; } public string? Description { get; set; } public string? Notes { get; set; } public List Events { get; set; } = []; } public sealed class ImportThreadEventDto { public string? SceneRef { get; set; } public int? BookOrder { get; set; } public int? ChapterOrder { get; set; } public int? SceneOrder { get; set; } public string? Title { get; set; } public string? EventType { get; set; } public string? Summary { get; set; } public string? Impact { get; set; } public int? Importance { get; set; } public string? Notes { get; set; } } public sealed class ImportStoryAssetDto { public string Name { get; set; } = string.Empty; public string? DisplayName { get; set; } public string? Type { get; set; } public int? Importance { get; set; } public string? Description { get; set; } public string? Notes { get; set; } public string? InitialOwnerCharacterName { get; set; } public string? InitialLocationName { get; set; } public List States { get; set; } = []; public List Events { get; set; } = []; } public sealed class ImportAssetStateDto { public string? SceneRef { get; set; } public int? BookOrder { get; set; } public int? ChapterOrder { get; set; } public int? SceneOrder { get; set; } public string? StateName { get; set; } public string? Description { get; set; } public string? Notes { get; set; } } public sealed class ImportAssetEventDto { public string? SceneRef { get; set; } public int? BookOrder { get; set; } public int? ChapterOrder { get; set; } public int? SceneOrder { get; set; } public string? EventType { get; set; } public string? Title { get; set; } public string? Summary { get; set; } public string? CharacterName { get; set; } public string? LocationName { get; set; } public string? Notes { get; set; } } public sealed class ImportChapterDto { public decimal ChapterNumber { get; set; } public string Title { get; set; } = string.Empty; public int Order { get; set; } public string? Summary { get; set; } public string? Notes { get; set; } public List Scenes { get; set; } = []; } public sealed class ImportSceneDto { public decimal SceneNumber { get; set; } public string Title { get; set; } = string.Empty; public int Order { get; set; } public string? Summary { get; set; } public string? PovCharacterName { get; set; } public string? LocationName { get; set; } public string? DateTimeText { get; set; } public string? PurposeText { get; set; } public string? OutcomeText { get; set; } public string? Notes { get; set; } public List SceneCharacters { get; set; } = []; } public sealed class ImportSceneCharacterDto { public string CharacterName { get; set; } = string.Empty; public string? RoleInScene { get; set; } public int? Importance { get; set; } public string? Notes { get; set; } } public sealed class ImportValidationResult { public bool IsValid => Errors.Count == 0; public List Errors { get; } = []; public List Warnings { get; } = []; } public sealed class ImportPreview { public PlotLineImportPackage? Package { get; init; } public ImportValidationResult Validation { get; init; } = new(); public bool HasDuplicateProjectTitle { get; init; } public string? DuplicateImportProjectTitle { get; init; } public IReadOnlyList BookPreviews { get; init; } = []; public IReadOnlyList UnmatchedPovNames { get; init; } = []; public IReadOnlyList UnmatchedLocationNames { get; init; } = []; public IReadOnlyList UnmatchedSceneCharacterNames { get; init; } = []; public IReadOnlyList UnresolvedThreadEventReferences { get; init; } = []; public IReadOnlyList UnresolvedAssetReferences { get; init; } = []; public IReadOnlyList UnmatchedAssetOwnerNames { get; init; } = []; public IReadOnlyList UnmatchedAssetLocationNames { get; init; } = []; public int BookCount => Package?.Books.Count ?? 0; public int CharacterCount => Package?.Characters.Count ?? 0; public int LocationCount => Package?.Locations.Count ?? 0; public int PlotLineCount => Package?.PlotLines.Count ?? 0; public int PlotThreadCount => Package?.PlotLines.Sum(plotLine => plotLine.Threads.Count) ?? 0; public int ThreadEventCount => Package?.PlotLines.Sum(plotLine => plotLine.Threads.Sum(thread => thread.Events.Count)) ?? 0; public int ResolvedThreadEventCount => Math.Max(0, ThreadEventCount - UnresolvedThreadEventReferences.Count); public int StoryAssetCount => Package?.StoryAssets.Count ?? 0; public int AssetStateCount => Package?.StoryAssets.Sum(asset => asset.States.Count) ?? 0; public int AssetEventCount => Package?.StoryAssets.Sum(asset => asset.Events.Count) ?? 0; public int ResolvedAssetStateCount => Math.Max(0, AssetStateCount - UnresolvedAssetReferences.Count(x => x.Contains("state", StringComparison.OrdinalIgnoreCase))); public int ResolvedAssetEventCount => Math.Max(0, AssetEventCount - UnresolvedAssetReferences.Count(x => x.Contains("event", StringComparison.OrdinalIgnoreCase))); public int ChapterCount => Package?.Books.Sum(book => book.Chapters.Count) ?? 0; public int SceneCount => Package?.Books.Sum(book => book.Chapters.Sum(chapter => chapter.Scenes.Count)) ?? 0; public int SceneCharacterAppearanceCount => Package?.Books.Sum(book => book.Chapters.Sum(chapter => chapter.Scenes.Sum(scene => scene.SceneCharacters.Count + AutoPovAppearanceCount(scene)))) ?? 0; private static int AutoPovAppearanceCount(ImportSceneDto scene) => !string.IsNullOrWhiteSpace(scene.PovCharacterName) && scene.SceneCharacters.All(x => !string.Equals(x.CharacterName?.Trim(), scene.PovCharacterName.Trim(), StringComparison.OrdinalIgnoreCase)) ? 1 : 0; } public sealed class ImportBookPreview { public ImportBookDto Book { get; init; } = new(); public int ChapterCount => Book.Chapters.Count; public int SceneCount => Book.Chapters.Sum(chapter => chapter.Scenes.Count); public IReadOnlyList ChapterPreviews { get; init; } = []; } public sealed class ImportChapterPreview { public ImportChapterDto Chapter { get; init; } = new(); public int SceneCount => Chapter.Scenes.Count; } public sealed class ImportResult { public bool Succeeded { get; init; } public int? ProjectID { get; init; } public string ProjectName { get; init; } = string.Empty; public int BooksCreated { get; init; } public int ChaptersCreated { get; init; } public int ScenesCreated { get; init; } public int CharactersCreated { get; init; } public int LocationsCreated { get; init; } public int SceneCharacterAppearancesCreated { get; init; } public int PlotLinesCreated { get; init; } public int PlotThreadsCreated { get; init; } public int ThreadEventsCreated { get; init; } public int StoryAssetsCreated { get; init; } public int AssetStatesCreated { get; init; } public int AssetEventsCreated { get; init; } public int AssetCustodyEventsCreated { get; init; } public IReadOnlyList SkippedOptionalFields { get; init; } = []; public IReadOnlyList UnresolvedWarnings { get; init; } = []; public string? TechnicalDetail { get; init; } public string Message { get; init; } = string.Empty; }