using System.Data; using System.Text.Json; using Dapper; using PlotLine.Models; namespace PlotLine.Data; public interface IOnboardingBuildRepository { Task BuildAsync(int userId, OnboardingManuscriptBuildRequest request); } public sealed class OnboardingBuildRepository(ISqlConnectionFactory connectionFactory) : IOnboardingBuildRepository { public async Task BuildAsync(int userId, OnboardingManuscriptBuildRequest request) { using var connection = connectionFactory.CreateConnection(); using var result = await connection.QueryMultipleAsync( "dbo.Onboarding_ManuscriptBuild_Create", new { UserID = userId, request.PreviewID, request.ProjectID, request.BookID, request.DocumentGuid, BindingVersion = 1, ChaptersJson = JsonSerializer.Serialize(request.Chapters), ScenesJson = JsonSerializer.Serialize(request.Scenes), CharactersJson = JsonSerializer.Serialize(request.Characters) }, commandType: CommandType.StoredProcedure); var header = await result.ReadSingleOrDefaultAsync(); if (header is null) { return null; } var chapters = (await result.ReadAsync()).ToList(); var scenes = (await result.ReadAsync()).ToList(); var characters = (await result.ReadAsync()).ToList(); return new OnboardingManuscriptBuildResult { BuildID = header.BuildID, PreviewID = header.PreviewID, ProjectID = header.ProjectID, BookID = header.BookID, ManuscriptDocumentID = header.ManuscriptDocumentID, Status = header.Status, MarkerStatus = header.MarkerStatus, ChaptersCreated = header.ChaptersCreated, ScenesCreated = header.ScenesCreated, CharactersCreated = header.CharactersCreated, CharactersReused = header.CharactersReused, SceneAppearancesCreated = header.SceneAppearancesCreated, AlreadyBuilt = header.AlreadyBuilt, Message = header.Message, ChapterMappings = chapters, SceneMappings = scenes, CharacterMappings = characters }; } } public sealed class OnboardingManuscriptBuildRequest { public Guid PreviewID { get; init; } public int ProjectID { get; init; } public int BookID { get; init; } public Guid DocumentGuid { get; init; } public IReadOnlyList Chapters { get; init; } = []; public IReadOnlyList Scenes { get; init; } = []; public IReadOnlyList Characters { get; init; } = []; } public sealed class OnboardingBuildChapterRequest { public string TemporaryChapterKey { get; init; } = string.Empty; public string Title { get; init; } = string.Empty; public int SortOrder { get; init; } public int WordCount { get; init; } } public sealed class OnboardingBuildSceneRequest { public string TemporarySceneKey { get; init; } = string.Empty; public string TemporaryChapterKey { get; init; } = string.Empty; public string Title { get; init; } = string.Empty; public int SortOrder { get; init; } public int WordCount { get; init; } } public sealed class OnboardingBuildCharacterRequest { public string TemporaryCharacterKey { get; init; } = string.Empty; public string Name { get; init; } = string.Empty; public int? ExistingCharacterID { get; init; } }