using System.Data;
using System.Text.Json;
using Dapper;
using PlotLine.Models;

namespace PlotLine.Data;

public interface IOnboardingBuildRepository
{
    Task<OnboardingManuscriptBuildResult?> BuildAsync(int userId, OnboardingManuscriptBuildRequest request);
}

public sealed class OnboardingBuildRepository(ISqlConnectionFactory connectionFactory) : IOnboardingBuildRepository
{
    public async Task<OnboardingManuscriptBuildResult?> 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<OnboardingManuscriptBuildResult>();
        if (header is null)
        {
            return null;
        }

        var chapters = (await result.ReadAsync<OnboardingBuildChapterMap>()).ToList();
        var scenes = (await result.ReadAsync<OnboardingBuildSceneMap>()).ToList();
        var characters = (await result.ReadAsync<OnboardingBuildCharacterMap>()).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<OnboardingBuildChapterRequest> Chapters { get; init; } = [];
    public IReadOnlyList<OnboardingBuildSceneRequest> Scenes { get; init; } = [];
    public IReadOnlyList<OnboardingBuildCharacterRequest> 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; }
}
