@page "/inventur/scannen"
@attribute [Authorize]
@using WerksverkaufScanner.Data
@using WerksverkaufScanner.Services
@using Microsoft.AspNetCore.Components.Web
@inject StammdatenCache Cache
@inject InventurService Inventur
@inject IJSRuntime JS

<h3>Inventur – Scannen / Eingeben</h3>

@if (needsSetup)
{
    <div class="alert alert-warning d-flex align-items-center" role="alert">
        <div>
            Es fehlen lokale Einstellungen (Filial-ID oder Inventur-ID). Bitte zuerst den QR-Code
            auf der Seite <a href="/inventur/vorbereiten" class="alert-link">Inventur vorbereiten</a> scannen.
        </div>
    </div>
}
else
{
    <!-- 1) Barcode ODER Artikelnummer -->
    <input @ref="barcodeRef" id="barcode"
           class="form-control form-control-lg mb-2"
           placeholder="Barcode scannen oder Artikelnummer eingeben"
           @bind="scanText" @bind:event="oninput"
           @onkeydown="OnScanKey" />

    @if (varianten is { Count: > 1 })
    {
        <div class="mb-3">
            <div class="mb-1">Varianten gefunden – bitte auswählen:</div>
            <div class="d-flex flex-wrap gap-2">
                @foreach (var art in varianten)
                {
                    var isActive = ReferenceEquals(gefunden, art);
                    <button type="button"
                            class="btn btn-lg"
                            style="@GetButtonStyle(art, isActive)"
                            @onclick="@(() => VarianteAuswaehlen(art))">
                        @GetVarianteLabel(art)
                    </button>
                }
            </div>
        </div>
    }

    @if (gefunden is not null)
    {
        <div class="alert alert-info py-2 mb-2">
            <strong>@gefunden.Bezeichnung</strong>
            <span class="text-muted">
                · @gefunden.ArtikelNummer
                · Variante @gefunden.Variante
                @if (!string.IsNullOrWhiteSpace(gefunden.Farbe))
                {
                    <text> · @gefunden.Farbe</text>
                }
                @if (!string.IsNullOrWhiteSpace(gefunden.Text))
                {
                    <text> · @gefunden.Text</text>
                }
            </span>
        </div>

        <!-- 2) Menge -->
        <input @ref="mengeRef" id="menge"
               class="form-control form-control-lg mb-2"
               placeholder="Menge (natürliche Zahl) …"
               @bind="mengeText" @bind:event="oninput"
               @onkeydown="OnMengeKey"
               inputmode="numeric" pattern="[0-9]*" />
    }
}

@if (!string.IsNullOrEmpty(status))
{
    <div class="mt-2 @(ok ? "text-success" : "text-danger")">@status</div>
}

@code {
    // --- Konfig aus localStorage ---
    private bool needsSetup;               // true = FilialId/InventurId fehlen/ungültig
    private string? filialId;              // bereinigt (ohne Anführungszeichen)
    private int? inventurId;
    private string? currentUser;

    // Eingaben/Status
    private string? scanText;
    private string? mengeText;
    private Artikel? gefunden;
    private List<Artikel>? varianten;
    private string? status;
    private bool ok;

    // Fokussteuerung
    private ElementReference barcodeRef, mengeRef;
    private bool focusBarcode = true;
    private bool focusMenge;

    protected override async Task OnInitializedAsync()
    {
        if (Cache.GetArtikel().Count == 0)
            await Cache.RefreshAsync();
    }

    // JS-Interop nur after first render (sonst Prerender-Fehler)
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await LoadConfigAsync();

            // Erst fokussieren, wenn Setup ok
            if (!needsSetup && focusBarcode)
            {
                focusBarcode = false;
                await barcodeRef.FocusAsync();
            }

            StateHasChanged(); // UI nach Konfig-Check aktualisieren
            return;
        }

        if (!needsSetup && focusMenge)
        {
            focusMenge = false;
            await mengeRef.FocusAsync();
        }
    }

    private async Task LoadConfigAsync()
    {
        try
        {
            var f = await JS.InvokeAsync<string?>("localStorage.getItem", "scannerpilot.filialId");
            var i = await JS.InvokeAsync<string?>("localStorage.getItem", "scannerpilot.inventurId");
            var u = await JS.InvokeAsync<string?>("localStorage.getItem", "scannerpilot.user");

            filialId = f?.Trim('"');
            currentUser = u?.Trim('"');

            if (!string.IsNullOrWhiteSpace(i) && int.TryParse(i.Trim('"'), out var inv))
                inventurId = inv;
            else
                inventurId = null;

            // needsSetup = true, wenn irgendwas fehlt/ungültig
            needsSetup = string.IsNullOrWhiteSpace(filialId) || inventurId is null;
        }
        catch
        {
            needsSetup = true;
            filialId = null;
            inventurId = null;
            currentUser = null;
        }
    }

    private async Task OnScanKey(KeyboardEventArgs e)
    {
        if (e.Key == "Enter" && !needsSetup)
            await SucheArtikelAsync();
    }

    private async Task SucheArtikelAsync()
    {
        status = null;
        ok = false;
        gefunden = null;
        varianten = null;

        var input = scanText?.Trim();
        scanText = string.Empty;

        if (string.IsNullOrWhiteSpace(input))
        {
            focusBarcode = true;
            StateHasChanged();
            return;
        }

        if (Cache.GetArtikel().Count == 0)
            await Cache.RefreshAsync();

        var alle = Cache.GetArtikel();

        var matches = alle
            .Where(a =>
                string.Equals(a.Barcode, input, StringComparison.OrdinalIgnoreCase) ||
                string.Equals(a.ArtikelNummer, input, StringComparison.OrdinalIgnoreCase))
            .OrderBy(a => a.Variante)
            .ThenBy(a => a.ArtikelVariantenId)
            .ToList();

        if (matches.Count == 0)
        {
            status = $"Kein Artikel gefunden für „{input}“.";
            focusBarcode = true;
        }
        else if (matches.Count == 1)
        {
            gefunden = matches[0];
            varianten = null;
            status = $"„{gefunden.Bezeichnung}“ – Variante {GetVarianteLabel(gefunden)} ausgewählt. Bitte Menge eingeben.";
            focusMenge = true;
        }
        else
        {
            varianten = matches;
            status = $"{matches.Count} Varianten gefunden – bitte auswählen.";
            focusMenge = false;
        }

        StateHasChanged();
    }

    private void VarianteAuswaehlen(Artikel art)
    {
        gefunden = art;
        status = $"Variante {GetVarianteLabel(art)} ausgewählt. Bitte Menge eingeben.";
        focusMenge = true;
        StateHasChanged();
    }

    private async Task OnMengeKey(KeyboardEventArgs e)
    {
        if (e.Key == "Enter")
            await SpeichernAsync();
    }

    private async Task SpeichernAsync()
    {
        status = null;
        ok = false;

        if (needsSetup)
        {
            status = "Bitte zuerst die Inventur vorbereiten (QR-Code scannen).";
            return;
        }

        if (gefunden is null)
        {
            status = "Bitte zuerst Barcode scannen und eine Variante auswählen.";
            focusBarcode = true;
            StateHasChanged();
            return;
        }

        // Menge: nur natürliche Zahl (>0)
        if (!int.TryParse(mengeText, out var menge) || menge <= 0)
        {
            status = "Ungültige Menge. Bitte eine natürliche Zahl (1,2,3, …) eingeben.";
            focusMenge = true;
            StateHasChanged();
            return;
        }

        try
        {
            // Sicherheitsnetz – noch einmal kurz prüfen (kann durch Tabwechsel gelöscht sein)
            if (filialId is null || inventurId is null)
                await LoadConfigAsync();

            if (string.IsNullOrWhiteSpace(filialId))
                throw new InvalidOperationException("Filial-ID fehlt.");
            if (inventurId is null)
                throw new InvalidOperationException("Inventur-ID fehlt oder ungültig.");

            var rows = await Inventur.SaveAsync(
                filialId,
                inventurId.Value,
                gefunden.ArtikelId,
                gefunden.ArtikelVariantenId,
                gefunden.Variante,
                menge,
                currentUser ?? string.Empty   // optional Benutzer mitschicken
            );

            ok = rows > 0;
            status = ok
                ? $"Gespeichert: {gefunden.ArtikelNummer} – Variante {gefunden.Variante} ({GetVarianteLabel(gefunden)}) · Menge {menge} (Filiale {filialId})."
                : "Nichts gespeichert.";

            mengeText = null;
            gefunden = null;
            varianten = null;
            focusBarcode = true;
        }
        catch (Exception ex)
        {
            ok = false;
            status = "Fehler beim Speichern: " + ex.Message;
            focusMenge = true;
        }

        StateHasChanged();
    }

    // ---------- Hilfsfunktionen für Button-Darstellung ----------

    private string GetVarianteLabel(Artikel art)
    {
        if (!string.IsNullOrWhiteSpace(art.Text))
            return art.Text;

        if (!string.IsNullOrWhiteSpace(art.Farbe))
            return art.Farbe;

        return $"Variante {art.Variante}";
    }

    private string GetButtonStyle(Artikel art, bool isActive)
    {
        var bg = GetCssColorFromFarbe(art.Farbe);
        var border = isActive ? "3px solid black" : "1px solid #666";
        var color = NeedsDarkText(art.Farbe) ? "black" : "white";

        return $"background-color:{bg};color:{color};border:{border};min-width:6rem;";
    }

    private string GetCssColorFromFarbe(string? farbe)
    {
        if (string.IsNullOrWhiteSpace(farbe))
            return "#e0e0e0";

        switch (farbe.Trim().ToLowerInvariant())
        {
            case "rot": return "#dc3545";
            case "blau": return "#007bff";
            case "gruen":
            case "grün": return "#28a745";
            case "gelb": return "#ffc107";
            case "orange": return "#fd7e14";
            case "lila": return "#6f42c1";
            default: return "#e0e0e0"; // neutral
        }
    }

    private bool NeedsDarkText(string? farbe)
    {
        if (string.IsNullOrWhiteSpace(farbe))
            return true;

        var f = farbe.Trim().ToLowerInvariant();
        return f is "gelb" or "orange";
    }
}
