@using System.Collections.Generic
@using System.Linq
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using RolemasterDb.App.Features
@implements IAsyncDisposable
@inject IJSRuntime JSRuntime

<div class="critical-editor-backdrop"
     @onpointerdown="HandleBackdropPointerDown"
     @onpointerup="HandleBackdropPointerUp"
     @onpointercancel="HandleBackdropPointerCancel">
    <div class="critical-editor-dialog critical-curation-dialog"
         @onpointerdown="HandleDialogPointerDown"
         @onpointerup="HandleDialogPointerUp"
         @onpointercancel="HandleDialogPointerCancel"
         @onpointerdown:stopPropagation="true"
        @onpointerup:stopPropagation="true"
        @onpointercancel:stopPropagation="true">
        <header class="critical-editor-header">
            <div>
                <h3 class="panel-title">Curate Result Card</h3>
                @if (Model is not null)
                {
                    <p class="muted critical-editor-meta">
                        <strong>@Model.TableName</strong>
                        <span> · Column <strong>@BuildColumnDisplayText(Model)</strong></span>
                        <span> · Roll band <strong>@Model.RollBand</strong></span>
                    </p>
                }
            </div>
            <button type="button" class="btn btn-link critical-editor-close" @onclick="OnClose">Close</button>
        </header>

        @if (IsLoading)
        {
            <div class="critical-editor-body">
                <p class="muted">Loading curation preview...</p>
            </div>
        }
        else if (Model is null)
        {
            <div class="critical-editor-body">
                @if (!string.IsNullOrWhiteSpace(GetVisibleErrorMessage()))
                {
                    <p class="error-text critical-editor-error">@GetVisibleErrorMessage()</p>
                }
                else
                {
                    <p class="muted">No curation preview is available.</p>
                }
            </div>
        }
        else
        {
            <div class="critical-editor-body critical-curation-body @(IsQuickParseMode ? "is-quick-parse" : null)">
                @if (!string.IsNullOrWhiteSpace(ErrorMessage))
                {
                    <p class="error-text critical-editor-error">@ErrorMessage</p>
                }

                <div class="critical-curation-grid">
                    <div class="critical-editor-card critical-curation-preview-card @(IsQuickParseMode ? "is-quick-parse" : null)">
                        @if (IsQuickParseMode)
                        {
                            <CriticalCellQuickParseEditor
                                @ref="quickParseEditor"
                                Model="Model"
                                IsDisabled="@(IsSaving || IsReparsing)"
                                TextAreaCssClass="input-shell critical-editor-textarea critical-curation-quick-parse-textarea"
                                OnReparse="OnReparse" />
                        }
                        else
                        {
                            <button
                                type="button"
                                class="critical-curation-preview-button"
                                @onclick="OnEnterQuickParse"
                                disabled="@(IsSaving || IsReparsing)">
                                <CompactCriticalCell
                                    Description="@Model.DescriptionText"
                                    Effects="@CriticalCellPresentation.BuildPreviewEffects(Model)"
                                    Branches="@CriticalCellPresentation.BuildPreviewBranches(Model)" />
                            </button>
                        }
                    </div>

                    <div class="critical-editor-card critical-curation-source-card">
                        @if (!string.IsNullOrWhiteSpace(Model.SourceImageUrl))
                        {
                            <img
                                class="critical-curation-source-image"
                                src="@Model.SourceImageUrl"
                                alt="@CriticalCellPresentation.BuildSourceImageAltText(Model)" />
                        }
                        else
                        {
                            <div class="critical-curation-source-empty">
                                <p class="muted">No source image is available for this cell yet.</p>
                            </div>
                        }
                    </div>
                </div>

                @if (!IsQuickParseMode)
                {
                    @if (GetUsedLegendEntries(Model, LegendEntries) is { Count: > 0 } usedLegendEntries)
                    {
                        <div class="critical-curation-legend">
                            @foreach (var entry in usedLegendEntries)
                            {
                                <div class="critical-curation-legend-item" title="@entry.Tooltip">
                                    <span class="legend-symbol">@entry.Symbol</span>
                                    <strong>@entry.Label</strong>
                                </div>
                            }
                        </div>
                    }
                }
            </div>

            <footer class="critical-editor-footer">
                @if (IsQuickParseMode)
                {
                    <button type="button" class="btn btn-link" @onclick="OnCancelQuickParse" disabled="@(IsSaving || IsReparsing)">Cancel</button>
                    <button
                        type="button"
                        class="btn-ritual"
                        @onclick="HandleReparseClickAsync"
                        @onclick:stopPropagation="true"
                        @onclick:preventDefault="true"
                        disabled="@(IsSaving || IsReparsing)">
                        @(IsReparsing ? "Parsing..." : "Parse")
                    </button>
                }
                else
                {
                    <button type="button" class="btn btn-link" @onclick="OnEdit" disabled="@(IsSaving || IsReparsing)">Edit</button>
                    <button type="button" class="btn-ritual" @onclick="OnMarkCurated" disabled="@(IsSaving || IsReparsing)">
                        @(IsSaving ? "Saving..." : "Mark as Curated")
                    </button>
                }
            </footer>
        }
    </div>
</div>

@code {
    [Parameter, EditorRequired]
    public CriticalCellEditorModel? Model { get; set; }

    [Parameter]
    public bool IsLoading { get; set; }

    [Parameter]
    public bool IsSaving { get; set; }

    [Parameter]
    public bool IsReparsing { get; set; }

    [Parameter]
    public bool IsQuickParseMode { get; set; }

    [Parameter]
    public string? ErrorMessage { get; set; }

    [Parameter]
    public string? QuickParseErrorMessage { get; set; }

    [Parameter]
    public IReadOnlyList<CriticalTableLegendEntry>? LegendEntries { get; set; }

    [Parameter, EditorRequired]
    public EventCallback OnClose { get; set; }

    [Parameter, EditorRequired]
    public EventCallback OnMarkCurated { get; set; }

    [Parameter, EditorRequired]
    public EventCallback OnEdit { get; set; }

    [Parameter, EditorRequired]
    public EventCallback OnEnterQuickParse { get; set; }

    [Parameter, EditorRequired]
    public EventCallback OnCancelQuickParse { get; set; }

    [Parameter, EditorRequired]
    public EventCallback OnReparse { get; set; }

    private IJSObjectReference? jsModule;
    private bool isBackdropPointerDown;
    private CriticalCellQuickParseEditor? quickParseEditor;
    private bool shouldFocusQuickParseEditor;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            jsModule = await JSRuntime.InvokeAsync<IJSObjectReference>(
                "import",
                "./Components/Shared/CriticalCellEditorDialog.razor.js");

            await jsModule.InvokeVoidAsync("lockBackgroundScroll");
        }

        if (shouldFocusQuickParseEditor && quickParseEditor is not null)
        {
            shouldFocusQuickParseEditor = false;
            await quickParseEditor.FocusAsync();
        }
    }

    public async ValueTask DisposeAsync()
    {
        if (jsModule is null)
        {
            return;
        }

        try
        {
            await jsModule.InvokeVoidAsync("unlockBackgroundScroll");
            await jsModule.DisposeAsync();
        }
        catch (JSDisconnectedException)
        {
        }
    }

    private void HandleBackdropPointerDown()
    {
        isBackdropPointerDown = true;
    }

    private async Task HandleBackdropPointerUp()
    {
        if (!isBackdropPointerDown)
        {
            return;
        }

        isBackdropPointerDown = false;
        await OnClose.InvokeAsync();
    }

    private void HandleBackdropPointerCancel()
    {
        isBackdropPointerDown = false;
    }

    private void HandleDialogPointerDown()
    {
        isBackdropPointerDown = false;
    }

    private void HandleDialogPointerUp()
    {
        isBackdropPointerDown = false;
    }

    private void HandleDialogPointerCancel()
    {
        isBackdropPointerDown = false;
    }

    private static string BuildColumnDisplayText(CriticalCellEditorModel model) =>
        string.IsNullOrWhiteSpace(model.GroupLabel)
            ? model.ColumnLabel
            : $"{model.GroupLabel} / {model.ColumnLabel}";

    private static IReadOnlyList<CriticalTableLegendEntry> GetUsedLegendEntries(
        CriticalCellEditorModel model,
        IReadOnlyList<CriticalTableLegendEntry>? legendEntries)
    {
        if (legendEntries is null || legendEntries.Count == 0)
        {
            return [];
        }

        var usedEffectCodes = model.Effects
            .Select(effect => effect.EffectCode)
            .Concat(model.Branches.SelectMany(branch => branch.Effects.Select(effect => effect.EffectCode)))
            .Where(effectCode => !string.IsNullOrWhiteSpace(effectCode))
            .ToHashSet(StringComparer.OrdinalIgnoreCase);

        return legendEntries
            .Where(entry => usedEffectCodes.Contains(entry.EffectCode))
            .ToList();
    }

    private async Task HandleReparseClickAsync(MouseEventArgs _)
    {
        if (quickParseEditor is not null)
        {
            await quickParseEditor.ReparseAsync();
            return;
        }

        await OnReparse.InvokeAsync();
    }

    private string? GetVisibleErrorMessage() =>
        IsQuickParseMode && !string.IsNullOrWhiteSpace(QuickParseErrorMessage)
            ? QuickParseErrorMessage
            : ErrorMessage;

    protected override void OnParametersSet()
    {
        if (IsQuickParseMode && quickParseEditor is null)
        {
            shouldFocusQuickParseEditor = true;
        }
    }
}
