@page "/stammdaten/preisaenderung"
@attribute [Authorize]

@using System.Globalization

@using WerksverkaufScanner.Data
@using WerksverkaufScanner.Services
@using Microsoft.AspNetCore.Components.Web

@using Microsoft.EntityFrameworkCore

@inject IDbContextFactory<ScannerDb> DbFactory
@inject PreisAenderungSqlService Preise
@inject IJSRuntime JS

<h2>Preisänderung</h2>

<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?.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="@(isActive ? "border:2px solid #007bff;background:#e9f7ff;" : "")"
                        @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>

    <!-- Preis-Eingabe -->
    <div class="input-group input-group-lg mb-2">
        <span class="input-group-text">€</span>
        <input @ref="priceRef" id="preis"
               class="form-control text-end"
               inputmode="numeric" pattern="[0-9]*"
               placeholder="z. B. 599 → 5,99"
               @bind="priceText" @bind:event="oninput" @bind:after="OnPriceChanged"
               @onkeydown="OnPriceKey" />
        <span class="input-group-text text-muted">z. B. 599 → 5,99</span>
    </div>

    <button class="btn btn-primary"
            disabled="@(!priceCents.HasValue)"
            @onclick="SpeichernAsync">
        Speichern
    </button>
}

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

@code {
    private string? scanText;
    private ArtikelFilialPreise? gefunden;
    private List<ArtikelFilialPreise>? varianten;

    private string? priceText;
    private int? priceCents;
    private string? status;
    private bool ok;

    private ElementReference barcodeRef, priceRef;
    private bool focusBarcode = true;
    private bool focusPrice;

    private int? filialId; // Aktuelle Filiale

    protected override async Task OnInitializedAsync()
    {
        // Filial-ID holen (async, weil localStorage)
        var filialIdStr = await JS.InvokeAsync<string?>("localStorage.getItem", "scannerpilot.filialId");
        if (!string.IsNullOrWhiteSpace(filialIdStr) && int.TryParse(filialIdStr.Trim('"'), out var id))
            filialId = id;
        else
        {
            status = "Keine Filiale ausgewählt – bitte zuerst konfigurieren!";
            return;
        }
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (focusBarcode)
        {
            focusBarcode = false;
            await barcodeRef.FocusAsync();
        }

        if (focusPrice)
        {
            focusPrice = false;
            await priceRef.FocusAsync();
        }
    }

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

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

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

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

        if (filialId == null)
        {
            status = "Keine Filiale ausgewählt!";
            return;
        }

        // Aus Datenbank laden!
        await using var db = await DbFactory.CreateDbContextAsync();
        var matches = await db.Set<ArtikelFilialPreise>()
            .Where(a => a.Barcode == input || a.ArtikelNummer == input)
            .Where(a => a.FilialId == filialId)
            .OrderBy(a => a.Variante)
            .ToListAsync();

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

        StateHasChanged();
    }

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

    private void OnPriceChanged()
    {
        var raw = priceText ?? string.Empty;
        var digits = new string(raw.Where(char.IsDigit).ToArray());

        if (string.IsNullOrEmpty(digits))
        {
            priceCents = null;
            priceText = string.Empty;
            return;
        }

        // führende Nullen tolerieren
        if (digits.Length > 1)
            digits = digits.TrimStart('0').PadLeft(1, '0');

        if (!int.TryParse(digits, out var cents))
        {
            priceCents = null;
            return;
        }

        priceCents = cents;
        var de = CultureInfo.GetCultureInfo("de-DE");
        priceText = (cents / 100m).ToString("N2", de);
    }

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

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

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

        if (!priceCents.HasValue || priceCents.Value <= 0)
        {
            status = "Bitte einen gültigen Preis eingeben.";
            focusPrice = true;
            StateHasChanged();
            return;
        }

        try
        {
            var filialIdStr = filialId?.ToString() ?? throw new InvalidOperationException("Filial-ID fehlt.");
            var user = await JS.InvokeAsync<string>("localStorage.getItem", "scannerpilot.user");
            if (string.IsNullOrWhiteSpace(user))
                throw new InvalidOperationException("Benutzername fehlt.");

            var rows = await Preise.SaveAsync(
                filialIdStr,
                gefunden.ArtikelId,
                gefunden.ArtikelVariantenId,
                gefunden.Variante,
                priceCents!.Value,
                user.Trim('"')
            );

            ok = rows > 0;
            status = ok
                ? $"Preis gespeichert: {gefunden.ArtikelNummer} – Variante {GetVarianteLabel(gefunden)} · {FormatEuro(priceCents!.Value)}."
                : "Nichts gespeichert.";

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

        StateHasChanged();
    }

    private string GetVarianteLabel(ArtikelFilialPreise art)
    {
        if (!string.IsNullOrWhiteSpace(art.Text)) return art.Text;
        if (!string.IsNullOrWhiteSpace(art.Farbe)) return art.Farbe;
        return $"Variante {art.Variante}";
    }

    private static string FormatEuro(int cents)
        => (cents / 100m).ToString("C", CultureInfo.GetCultureInfo("de-DE"));
}
