@model StoryIntelligenceProgressViewModel
@{
    ViewData["Title"] = "Reading your manuscript";
    var runIds = string.Join(",", Model.Chapters.Select(chapter => chapter.RunID));
    var progressPercent = ProgressPercent(Model);
    var currentChapter = CurrentChapter(Model);
}

<section class="onboarding-shell" aria-labelledby="story-progress-title">
    <div class="onboarding-panel onboarding-review-panel story-live-progress"
         data-story-intelligence-onboarding
         data-story-intelligence-batch-id="@Model.BatchID"
         data-story-intelligence-run-ids="@runIds"
         data-story-max-progress-percent="@progressPercent"
         data-story-intelligence-has-active-runs="@Model.HasActiveRuns.ToString().ToLowerInvariant()">
        <partial name="_StoryIntelligencePipelineHeader" model="@(new StoryIntelligencePipelineHeaderViewModel { CurrentStage = "Analyse Manuscript" })" />
        <div class="onboarding-copy story-live-hero">
            <p class="eyebrow">Analyse manuscript</p>
            <h1 id="story-progress-title">Reading your manuscript</h1>
            <p>PlotDirector is analysing your chapters and preparing scenes for review. You can safely leave this page and return later.</p>
        </div>

        @if (TempData["OnboardingStoryIntelligenceError"] is string error)
        {
            <div class="alert alert-danger">@error</div>
        }
        @if (TempData["OnboardingStoryIntelligenceMessage"] is string message)
        {
            <div class="alert alert-success">@message</div>
        }

        <section class="alert alert-info">
            PlotDirector will keep analysing your manuscript. You can close Word, close this browser tab, and return later. We’ll show this import on your Projects page while it is running.
        </section>

        <section class="story-live-progress-card" aria-label="Import progress">
            <div class="story-live-progress-heading">
                <div>
                    <p class="eyebrow mb-1">Import progress</p>
                    <strong data-story-overall-percent>@progressPercent%</strong>
                </div>
                <span data-story-current-stage>@FriendlyStage(currentChapter?.CurrentStage, currentChapter?.Status)</span>
            </div>
            <div class="progress" role="progressbar" aria-label="Story Intelligence progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="@progressPercent">
                <div class="progress-bar" data-story-overall-progress-bar style="width:@progressPercent%"></div>
            </div>
            <div class="story-live-stats">
                <div>
                    <span>Chapters read</span>
                    <strong class="story-stat-value" data-story-chapters-read-value>@Model.CompletedChapterCount of @Model.ChapterCount</strong>
                </div>
                <div>
                    <span>Scenes read</span>
                    <strong class="story-stat-value" data-story-scenes-read-value>@Model.TotalCompletedScenes so far</strong>
                </div>
                <div>
                    <span>Needs review</span>
                    <strong class="story-stat-value" data-story-failures>@(Model.FailedChapterCount + Model.TotalFailedScenes)</strong>
                </div>
                <div>
                    <span>Elapsed</span>
                    <strong class="story-stat-value" data-story-elapsed>@Elapsed(Model)</strong>
                </div>
                <div>
                    <span>Estimated remaining</span>
                    <strong class="story-stat-value" data-story-remaining>@EstimateRemaining(Model)</strong>
                </div>
            </div>
        </section>

        <section class="story-live-current" aria-label="Current activity">
            <div>
                <p class="eyebrow">Current chapter</p>
                <h2 data-story-current-chapter>@(currentChapter?.ChapterTitle ?? "Waiting")</h2>
                <p data-story-current-message>@FriendlyMessage(currentChapter)</p>
            </div>
            <div class="story-current-scene-panel">
                <p class="eyebrow">Current scene</p>
                <strong data-story-current-scene>@CurrentScene(Model)</strong>
                <div class="story-chapter-progress">
                    <span data-story-chapter-progress-text>@ChapterProgressText(currentChapter)</span>
                    <div class="progress" role="progressbar" aria-label="Current chapter progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="@ChapterProgressPercent(currentChapter)">
                        <div class="progress-bar" data-story-chapter-progress-bar style="width:@ChapterProgressPercent(currentChapter)%"></div>
                    </div>
                </div>
            </div>
        </section>

        <section class="story-live-feed-grid" aria-label="Live manuscript feed">
            <div>
                <h2>Latest from your manuscript</h2>
                @if (!string.IsNullOrWhiteSpace(currentChapter?.LatestSceneSummary))
                {
                    <p class="lead story-latest-summary" data-story-latest-summary>@currentChapter.LatestSceneSummary</p>
                    <p class="text-muted" data-story-latest-empty hidden>Scene summaries will appear here as PlotDirector reads.</p>
                }
                else
                {
                    <p class="lead story-latest-summary" data-story-latest-summary hidden></p>
                    <p class="text-muted" data-story-latest-empty>Scene summaries will appear here as PlotDirector reads.</p>
                }
            </div>
            <div class="story-live-discoveries">
                <h2>Recent discoveries</h2>
                <p class="text-muted story-discovery-placeholder" data-story-discovery-empty>Possible characters, locations and story clues will appear here as PlotDirector reads.</p>
                <ul data-story-discovery-feed></ul>
            </div>
        </section>

        <div class="story-run-state" aria-hidden="true" hidden>
            @foreach (var chapter in Model.Chapters.OrderBy(chapter => chapter.ChapterNumber))
            {
                <div data-story-run-id="@chapter.RunID"
                     data-story-chapter-title="@chapter.ChapterTitle"
                     data-story-raw-status="@chapter.Status"
                     data-story-source-word-count="@(chapter.SourceWordCount ?? 0)"
                     data-story-duration-ms="@(chapter.TotalDurationMs ?? 0)">
                    <span data-story-run-status>@FriendlyStatus(chapter.Status)</span>
                    <span data-story-run-completed>@((chapter.CompletedScenes ?? 0).ToString("N0"))</span>
                    <span data-story-run-total>@((chapter.TotalDetectedScenes ?? 0).ToString("N0"))</span>
                    <span data-story-run-failed>@((chapter.FailedScenes ?? 0).ToString("N0"))</span>
                    <span data-story-run-message>@FriendlyMessage(chapter)</span>
                    <span data-story-run-error>@(chapter.ErrorMessage ?? string.Empty)</span>
                    <span data-story-run-latest-summary>@(chapter.LatestSceneSummary ?? string.Empty)</span>
                </div>
            }
        </div>

        <div class="onboarding-actions">
            @if (Model.BatchID.HasValue)
            {
                <form asp-action="CancelStoryIntelligence" method="post">
                    <input type="hidden" name="batchId" value="@Model.BatchID" />
                    <button class="btn btn-outline-secondary" type="submit" disabled="@(!Model.HasActiveRuns)">Cancel analysis</button>
                </form>
                @if (Model.HasActiveRuns)
                {
                    <a class="btn btn-outline-primary" asp-controller="Projects" asp-action="Index">Continue in background</a>
                }
                @if (!Model.HasActiveRuns && Model.Chapters.Any(chapter => chapter.IsRunComplete || chapter.IsFailed || chapter.HasCompletedCommit))
                {
                    <a class="btn btn-primary"
                       data-story-review-link
                       asp-action="StoryIntelligenceReview"
                       asp-route-batchId="@Model.BatchID">Review scenes</a>
                }
            }
        </div>
    </div>
</section>

@section Scripts {
    <script src="~/js/story-intelligence-progress.js" asp-append-version="true"></script>
}

@functions {
    private static string FriendlyStatus(string? status)
        => status switch
        {
            StoryIntelligenceRunStatuses.Pending => "Waiting",
            StoryIntelligenceRunStatuses.Running => "Reading",
            StoryIntelligenceRunStatuses.Completed => "Ready to create",
            StoryIntelligenceRunStatuses.CompletedWithWarnings => "Ready",
            StoryIntelligenceRunStatuses.Failed => "Needs review",
            StoryIntelligenceRunStatuses.Cancelled => "Cancelled",
            _ => "Waiting"
        };

    private static string FriendlyStage(string? stage, string? status)
    {
        if (status is StoryIntelligenceRunStatuses.Completed or StoryIntelligenceRunStatuses.CompletedWithWarnings)
        {
            return "Ready to review";
        }

        if (status is StoryIntelligenceRunStatuses.Failed)
        {
            return "Needs review";
        }

        if (status is StoryIntelligenceRunStatuses.Cancelled)
        {
            return "Cancelled";
        }

        return stage switch
        {
            "Queued" => "Waiting",
            StoryIntelligenceFailureStages.ChapterStructure => "Finding scenes",
            StoryIntelligenceFailureStages.SceneIntelligence => "Reading scenes",
            StoryIntelligenceFailureStages.SceneSplit => "Preparing review",
            StoryIntelligenceFailureStages.Validation => "Preparing review",
            StoryIntelligenceFailureStages.Persistence => "Preparing review",
            _ => "Reading"
        };
    }

    private static string FriendlyMessage(StoryIntelligenceOnboardingChapterViewModel? chapter)
    {
        if (chapter is null)
        {
            return "Waiting for analysis to begin.";
        }

        if (chapter.Status == StoryIntelligenceRunStatuses.Cancelled)
        {
            return "Analysis was cancelled. Any completed chapters remain available for review.";
        }

        if (chapter.Status == StoryIntelligenceRunStatuses.Failed)
        {
            return "This chapter needs review before scenes can be created.";
        }

        return chapter.CurrentStage switch
        {
            "Queued" => "Waiting to read this chapter.",
            StoryIntelligenceFailureStages.ChapterStructure => "Finding scenes in this chapter.",
            StoryIntelligenceFailureStages.SceneSplit => "Preparing the detected scenes.",
            StoryIntelligenceFailureStages.SceneIntelligence => "Reading the detected scenes.",
            StoryIntelligenceFailureStages.Validation => "Checking the results.",
            _ => chapter.IsRunComplete
                ? "This chapter is ready to review."
                : "Waiting for analysis to begin."
        };
    }

    private static StoryIntelligenceOnboardingChapterViewModel? CurrentChapter(StoryIntelligenceProgressViewModel model)
        => model.Chapters.FirstOrDefault(chapter => chapter.IsActive)
            ?? model.Chapters.LastOrDefault(chapter => chapter.IsRunComplete)
            ?? model.Chapters.FirstOrDefault();

    private static int ProgressPercent(StoryIntelligenceProgressViewModel model)
    {
        if (model.ChapterCount == 0)
        {
            return 0;
        }

        var chapterProgress = model.Chapters.Sum(ChapterProgress);
        return Math.Clamp((int)Math.Floor(chapterProgress * 100m / model.ChapterCount), 0, 100);
    }

    private static decimal ChapterProgress(StoryIntelligenceOnboardingChapterViewModel chapter)
    {
        if (chapter.HasCompletedCommit || chapter.IsRunComplete || chapter.IsFailed)
        {
            return 1m;
        }

        if (chapter.Status == StoryIntelligenceRunStatuses.Pending)
        {
            return 0m;
        }

        if ((chapter.TotalDetectedScenes ?? 0) > 0)
        {
            var sceneProgress = Math.Clamp((chapter.CompletedScenes ?? 0) / Math.Max(1m, chapter.TotalDetectedScenes ?? 1), 0m, 1m);
            return Math.Clamp(0.25m + (sceneProgress * 0.7m), 0m, 0.95m);
        }

        return 0.15m;
    }

    private static string Elapsed(StoryIntelligenceProgressViewModel model)
    {
        var elapsedMs = model.Chapters.Max(chapter => chapter.TotalDurationMs ?? 0);
        var elapsed = TimeSpan.FromMilliseconds(Math.Max(0, elapsedMs));
        return elapsed.TotalMinutes >= 1
            ? $"{Math.Max(1, (int)Math.Round(elapsed.TotalMinutes)):N0} min"
            : $"{Math.Max(0, (int)Math.Round(elapsed.TotalSeconds)):N0} sec";
    }

    private static string EstimateRemaining(StoryIntelligenceProgressViewModel model)
    {
        if (!model.HasActiveRuns)
        {
            return "Ready to review";
        }

        var completed = model.Chapters
            .Where(chapter => chapter.IsRunComplete && (chapter.SourceWordCount ?? 0) > 0 && (chapter.TotalDurationMs ?? 0) > 0)
            .ToList();
        if (completed.Count == 0)
        {
            return "Estimating...";
        }

        var completedWords = completed.Sum(chapter => chapter.SourceWordCount ?? 0);
        var completedSeconds = completed.Sum(chapter => chapter.TotalDurationMs ?? 0) / 1000m;
        var remainingWords = model.Chapters
            .Where(chapter => !chapter.IsRunComplete && !chapter.IsFailed)
            .Sum(chapter => chapter.SourceWordCount ?? 0);
        if (completedWords <= 0 || completedSeconds <= 0 || remainingWords <= 0)
        {
            return "Estimating...";
        }

        var secondsPerWord = completedSeconds / completedWords;
        var bufferedSeconds = secondsPerWord * remainingWords * 1.35m;
        return FriendlyRemaining(bufferedSeconds);
    }

    private static string FriendlyRemaining(decimal seconds)
    {
        var minutes = (int)Math.Ceiling(seconds / 60m);
        if (minutes <= 0)
        {
            return "Estimating...";
        }

        if (minutes <= 20)
        {
            return "About 20-30 minutes";
        }

        if (minutes <= 45)
        {
            return "About 45-60 minutes";
        }

        if (minutes <= 120)
        {
            return "About 1-2 hours";
        }

        return "More than 2 hours";
    }

    private static string CurrentScene(StoryIntelligenceProgressViewModel model)
    {
        var chapter = CurrentChapter(model);
        return chapter?.CompletedScenes is > 0
            ? chapter.CompletedScenes.Value.ToString("N0")
            : "Waiting";
    }

    private static string ChapterProgressText(StoryIntelligenceOnboardingChapterViewModel? chapter)
    {
        if ((chapter?.TotalDetectedScenes ?? 0) <= 0)
        {
            return "Finding scenes...";
        }

        var completed = Math.Clamp(chapter?.CompletedScenes ?? 0, 0, chapter?.TotalDetectedScenes ?? 0);
        return $"Scene {completed:N0} of {chapter?.TotalDetectedScenes:N0}";
    }

    private static int ChapterProgressPercent(StoryIntelligenceOnboardingChapterViewModel? chapter)
    {
        var total = chapter?.TotalDetectedScenes ?? 0;
        if (total <= 0)
        {
            return 0;
        }

        var completed = Math.Clamp(chapter?.CompletedScenes ?? 0, 0, total);
        return Math.Clamp((int)Math.Floor(completed * 100m / total), 0, 100);
    }
}
