using PlotLine.Data;
using PlotLine.Models;

namespace PlotLine.Services;

public interface IStoryIntelligencePipelineStateService
{
    Task<StoryIntelligenceBookPipelineState?> GetForBookAsync(int bookId, int userId);
    Task<IReadOnlyList<StoryIntelligenceBookPipelineState>> ListForUserAsync(int userId);
    Task<StoryIntelligenceBookPipelineState?> EnsureForBookAsync(int bookId, int userId);
    Task RecordChapterAnalysisQueuedAsync(int projectId, int bookId, int runId);
    Task RecordSceneImportAsync(int projectId, int bookId, int runId);
    Task RecordCharacterImportAsync(int projectId, int bookId);
    Task RecordLocationImportAsync(int projectId, int bookId);
    Task RecordAssetImportAsync(int projectId, int bookId);
    Task RecordRelationshipImportAsync(int projectId, int bookId);
    Task RecordKnowledgeImportAsync(int projectId, int bookId);
    Task<IReadOnlyList<StoryIntelligenceCommittedRunSummary>> ListCommittedRunsByBookAsync(int bookId, int userId);
}

public sealed class StoryIntelligencePipelineStateService(
    IStoryIntelligencePipelineRepository pipelines,
    ILogger<StoryIntelligencePipelineStateService> logger) : IStoryIntelligencePipelineStateService
{
    public async Task<StoryIntelligenceBookPipelineState?> GetForBookAsync(int bookId, int userId)
        => await pipelines.GetByBookForUserAsync(bookId, userId)
            ?? await EnsureForBookAsync(bookId, userId);

    public Task<IReadOnlyList<StoryIntelligenceBookPipelineState>> ListForUserAsync(int userId)
        => pipelines.ListForUserAsync(userId);

    public async Task<StoryIntelligenceBookPipelineState?> EnsureForBookAsync(int bookId, int userId)
    {
        var existing = await pipelines.GetByBookForUserAsync(bookId, userId);
        if (existing is not null)
        {
            return existing;
        }

        var committedRuns = await pipelines.ListCommittedRunsByBookAsync(bookId, userId);
        if (committedRuns.Count == 0)
        {
            return null;
        }

        var latestRun = committedRuns.OrderByDescending(run => run.StoryIntelligenceRunID).First();
        var created = await pipelines.UpsertAsync(new StoryIntelligenceBookPipelineSaveRequest
        {
            ProjectID = latestRun.ProjectID,
            BookID = latestRun.BookID,
            CurrentStage = StoryIntelligencePipelineStages.CharacterReview,
            LastCompletedStage = StoryIntelligencePipelineStages.SceneImport,
            CurrentReviewStage = StoryIntelligencePipelineStages.CharacterReview,
            Status = StoryIntelligencePipelineStatuses.NeedsReview,
            CompletedUtc = null,
            LastRunID = latestRun.StoryIntelligenceRunID
        });

        logger.LogInformation(
            "Created Story Intelligence pipeline state for existing imported book {BookID}. ProjectID={ProjectID} CurrentStage={CurrentStage}",
            bookId,
            created.ProjectID,
            created.CurrentStage);
        return created;
    }

    public async Task RecordSceneImportAsync(int projectId, int bookId, int runId)
    {
        await pipelines.UpsertAsync(new StoryIntelligenceBookPipelineSaveRequest
        {
            ProjectID = projectId,
            BookID = bookId,
            CurrentStage = StoryIntelligencePipelineStages.CharacterReview,
            LastCompletedStage = StoryIntelligencePipelineStages.SceneImport,
            CurrentReviewStage = StoryIntelligencePipelineStages.CharacterReview,
            Status = StoryIntelligencePipelineStatuses.NeedsReview,
            CompletedUtc = null,
            LastRunID = runId
        });
    }

    public async Task RecordChapterAnalysisQueuedAsync(int projectId, int bookId, int runId)
    {
        await pipelines.UpsertAsync(new StoryIntelligenceBookPipelineSaveRequest
        {
            ProjectID = projectId,
            BookID = bookId,
            CurrentStage = StoryIntelligencePipelineStages.Chapters,
            LastCompletedStage = null,
            CurrentReviewStage = null,
            Status = StoryIntelligencePipelineStatuses.InProgress,
            CompletedUtc = null,
            LastRunID = runId
        });
    }

    public async Task RecordCharacterImportAsync(int projectId, int bookId)
    {
        await pipelines.UpsertAsync(new StoryIntelligenceBookPipelineSaveRequest
        {
            ProjectID = projectId,
            BookID = bookId,
            CurrentStage = StoryIntelligencePipelineStages.LocationReview,
            LastCompletedStage = StoryIntelligencePipelineStages.CharacterImport,
            CurrentReviewStage = StoryIntelligencePipelineStages.LocationReview,
            Status = StoryIntelligencePipelineStatuses.NeedsReview,
            CompletedUtc = null,
            LastRunID = null
        });
    }

    public async Task RecordLocationImportAsync(int projectId, int bookId)
    {
        await pipelines.UpsertAsync(new StoryIntelligenceBookPipelineSaveRequest
        {
            ProjectID = projectId,
            BookID = bookId,
            CurrentStage = StoryIntelligencePipelineStages.AssetReview,
            LastCompletedStage = StoryIntelligencePipelineStages.LocationImport,
            CurrentReviewStage = StoryIntelligencePipelineStages.AssetReview,
            Status = StoryIntelligencePipelineStatuses.NeedsReview,
            CompletedUtc = null,
            LastRunID = null
        });
    }

    public async Task RecordAssetImportAsync(int projectId, int bookId)
    {
        await pipelines.UpsertAsync(new StoryIntelligenceBookPipelineSaveRequest
        {
            ProjectID = projectId,
            BookID = bookId,
            CurrentStage = StoryIntelligencePipelineStages.RelationshipReview,
            LastCompletedStage = StoryIntelligencePipelineStages.AssetImport,
            CurrentReviewStage = StoryIntelligencePipelineStages.RelationshipReview,
            Status = StoryIntelligencePipelineStatuses.NeedsReview,
            CompletedUtc = null,
            LastRunID = null
        });
    }

    public async Task RecordRelationshipImportAsync(int projectId, int bookId)
    {
        await pipelines.UpsertAsync(new StoryIntelligenceBookPipelineSaveRequest
        {
            ProjectID = projectId,
            BookID = bookId,
            CurrentStage = StoryIntelligencePipelineStages.KnowledgeReview,
            LastCompletedStage = StoryIntelligencePipelineStages.RelationshipImport,
            CurrentReviewStage = StoryIntelligencePipelineStages.KnowledgeReview,
            Status = StoryIntelligencePipelineStatuses.NeedsReview,
            CompletedUtc = null,
            LastRunID = null
        });
    }

    public async Task RecordKnowledgeImportAsync(int projectId, int bookId)
    {
        await pipelines.UpsertAsync(new StoryIntelligenceBookPipelineSaveRequest
        {
            ProjectID = projectId,
            BookID = bookId,
            CurrentStage = StoryIntelligencePipelineStages.Complete,
            LastCompletedStage = StoryIntelligencePipelineStages.KnowledgeImport,
            CurrentReviewStage = null,
            Status = StoryIntelligencePipelineStatuses.Complete,
            CompletedUtc = DateTime.UtcNow,
            LastRunID = null
        });
    }

    public Task<IReadOnlyList<StoryIntelligenceCommittedRunSummary>> ListCommittedRunsByBookAsync(int bookId, int userId)
        => pipelines.ListCommittedRunsByBookAsync(bookId, userId);
}
