using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PlotLine.Data;
using PlotLine.Models;
using PlotLine.Services;
using PlotLine.ViewModels;

namespace PlotLine.Controllers;

[Authorize(Policy = "AdminOnly")]
[Route("Development")]
public sealed class DevelopmentController(
    IWebHostEnvironment environment,
    ICurrentUserService currentUser,
    IIllustrationLibraryService illustrationLibrary,
    IStoryMemoryService storyMemory,
    IStoryMemoryRepository storyMemoryRepository,
    IStoryIntelligenceVisualisationSnapshotService snapshots) : Controller
{
    [HttpGet("StoryIntelligenceExperience")]
    public async Task<IActionResult> StoryIntelligenceExperience([FromQuery] string? mode, [FromQuery] int? importSessionId, [FromQuery] int? runId)
    {
        if (!environment.IsDevelopment())
        {
            return NotFound();
        }

        var requestedMode = string.IsNullOrWhiteSpace(mode) ? "real" : mode.Trim();
        var simulationRequested = string.Equals(requestedMode, "simulation", StringComparison.OrdinalIgnoreCase);
        var replayRequested = string.Equals(requestedMode, "replay", StringComparison.OrdinalIgnoreCase);

        if (!simulationRequested && importSessionId.HasValue && currentUser.UserId is int userId)
        {
            var realModel = replayRequested
                ? await snapshots.BuildReplaySnapshotAsync(importSessionId.Value, userId)
                : await snapshots.BuildImportSessionSnapshotAsync(importSessionId.Value, userId);
            if (realModel is null)
            {
                return View(ErrorModel(
                    requestedMode,
                    importSessionId,
                    $"Import Session {importSessionId.Value:N0} could not be found for the current user, or it has no persisted chapter analysis runs yet."));
            }

            return View(realModel);
        }

        if (!simulationRequested && runId.HasValue && currentUser.UserId is int legacyUserId)
        {
            var realModel = await snapshots.BuildSnapshotAsync(runId.Value, legacyUserId);
            if (realModel is null)
            {
                return View(ErrorModel(
                    requestedMode,
                    null,
                    $"Run {runId.Value:N0} could not be found for the current user. Live visualisation URLs should use importSessionId for book imports."));
            }

            return View(realModel);
        }

        if (simulationRequested)
        {
            var model = StoryIntelligenceExperiencePrototypeData.Build();
            await illustrationLibrary.ApplyApprovedIllustrationsAsync(model);
            return View(model);
        }

        if (currentUser.UserId is int selectorUserId)
        {
            var sessions = await snapshots.ListImportSessionOptionsAsync(selectorUserId);
            return View(new StoryIntelligenceExperiencePrototypeViewModel
            {
                Mode = "selector",
                AvailableRuns = sessions,
                ProjectName = "Development",
                BookTitle = "Story Intelligence",
                SnapshotMessage = sessions.Count == 0
                    ? "No persisted Story Intelligence import sessions were found for the current user. Start a real import, then refresh this page."
                    : "Choose a Story Intelligence import session, or explicitly open simulation mode.",
                Diagnostics = new StoryIntelligenceExperienceSnapshotDiagnostics
                {
                    RequestedMode = requestedMode,
                    RequestedImportSessionId = importSessionId,
                    SnapshotSource = "Real"
                }
            });
        }

        return View(ErrorModel(requestedMode, importSessionId, "No development user is signed in."));
    }

    [HttpPost("StoryIntelligenceExperience/Rebuild")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> RebuildStoryIntelligenceExperience(
        [FromForm] int importSessionId,
        [FromForm] string? rebuildScope,
        [FromForm] bool dryRun = false,
        [FromForm] bool queueDemand = false,
        [FromForm] int? maxDemandToQueue = null,
        [FromForm] string? appearancePreference = null)
    {
        if (!environment.IsDevelopment())
        {
            return NotFound();
        }

        if (importSessionId <= 0 || currentUser.UserId is not int userId)
        {
            return BadRequest("A valid importSessionId is required.");
        }

        var rebuild = await storyMemory.RebuildImportSessionAsync(
            importSessionId,
            userId,
            new StoryMemoryRebuildOptions
            {
                DryRun = dryRun,
                RebuildAll = !string.Equals(rebuildScope, "incremental", StringComparison.OrdinalIgnoreCase),
                QueueDemand = queueDemand,
                MaxDemandToQueue = maxDemandToQueue,
                AppearancePreference = string.IsNullOrWhiteSpace(appearancePreference)
                    ? StoryMemoryAppearancePreferences.Balanced
                    : appearancePreference.Trim()
            },
            HttpContext.RequestAborted);
        if (rebuild.DryRun)
        {
            TempData["StoryIntelligenceReplayMessage"] = $"Dry run complete. {rebuild.SceneResultsRead:N0} stored scene result(s), {rebuild.SceneResultsProcessed:N0} parseable. No database changes, AI calls, or image credits.";
        }
        else
        {
            TempData["StoryIntelligenceReplayMessage"] = $"Durable Story Memory rebuilt. {rebuild.SceneResultsProcessed:N0} scene result(s) processed, {rebuild.AssignmentsCreatedOrValidated:N0} assignment(s), {rebuild.DemandsCreated:N0} demand record(s), {rebuild.AiCalls:N0} AI calls.";
        }

        return RedirectToAction(nameof(StoryIntelligenceExperience), new { importSessionId, mode = "replay" });
    }

    [HttpGet("StoryMemoryDiagnostics")]
    public async Task<IActionResult> StoryMemoryDiagnostics([FromQuery] int importSessionId)
    {
        if (!environment.IsDevelopment())
        {
            return NotFound();
        }

        if (importSessionId <= 0)
        {
            return BadRequest("A valid importSessionId is required.");
        }

        var diagnostics = await storyMemoryRepository.GetDiagnosticsAsync(importSessionId);
        return Json(diagnostics);
    }

    [HttpGet("StoryIntelligenceIllustrationDiagnostics")]
    public async Task<IActionResult> StoryIntelligenceIllustrationDiagnostics([FromQuery] int importSessionId)
    {
        if (!environment.IsDevelopment())
        {
            return NotFound();
        }

        if (importSessionId <= 0 || currentUser.UserId is not int userId)
        {
            return BadRequest("A valid importSessionId is required.");
        }

        var model = await snapshots.BuildImportSessionSnapshotAsync(importSessionId, userId);
        if (model is null)
        {
            return NotFound($"Import Session {importSessionId:N0} could not be found for the current user, or it has no persisted chapter analysis runs yet.");
        }

        return View(model);
    }

    private static StoryIntelligenceExperiencePrototypeViewModel ErrorModel(string requestedMode, int? importSessionId, string message)
        => new()
        {
            Mode = "error",
            ProjectName = "Development",
            BookTitle = "Story Intelligence",
            SnapshotMessage = message,
            Diagnostics = new StoryIntelligenceExperienceSnapshotDiagnostics
            {
                RequestedMode = requestedMode,
                RequestedImportSessionId = importSessionId,
                SnapshotSource = "Real",
                Warning = message
            }
        };
}
