@using CRS.HybridSearch.Models
@model ConfigurationModel

@{
    Layout = "_ConfigureModule";
}

<style>
    /* Hide expert rows by default (when the form is not in advanced-mode). The wrapper class
       is set conditionally below and toggled by JS when the AdvancedMode checkbox changes —
       no flash-of-advanced-content on page load. */
    form.crs-no-advanced .js-advanced-only { display: none !important; }
</style>

<form asp-action="Configure" class="@(Model.AdvancedMode ? "" : "crs-no-advanced")">
    <widget target-zone="admin_button_toolbar_before">
        <button id="SaveConfigButton" type="submit" name="save" class="btn btn-warning" value="save">
            <i class="fa fa-check"></i>
            <span>@T("Admin.Common.Save")</span>
        </button>
    </widget>

    <div asp-validation-summary="All"></div>

    <tabstrip id="hybridsearch-config" sm-nav-style="Material" sm-remember-selected-tab="true">

        @* amamamamamamam TAB 0: Allgemeines amamamamamamam *@
        <tab sm-title="Allgemeines" sm-selected="true" sm-icon="fa fa-cog">
            <div class="adminContent">
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="AdvancedMode" /></div>
                    <div class="adminData"><setting-editor asp-for="AdvancedMode"></setting-editor></div>
                </div>

                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">Lizenz</div>
                    </div>
                </div>

                @if (ViewBag.LicenseStatusVm is CRS.HybridSearch.Models.LicenseStatusVm lic)
                {
                    @* ---------- Full-width status banner + diagnostics ---------- *@
                    <div class="w-100 mb-3">
                        @if (lic.IsLicensed)
                        {
                            <div class="alert alert-success mb-0">
                                <i class="fa fa-check-circle"></i>
                                Lizenz aktiv: <code>@lic.DisplayLicenseKey</code> &mdash; gueltig bis <strong>@lic.ValidUntilUtc?.ToString("yyyy-MM-dd")</strong>.
                            </div>
                        }
                        else if (lic.IsLicensedInGrace)
                        {
                            <div class="alert alert-warning mb-0">
                                <i class="fa fa-exclamation-triangle"></i>
                                Lizenz <strong>abgelaufen</strong> &mdash; Modul laeuft noch in der Karenzfrist (<strong>@lic.GraceRemainingDays</strong> Tage Rest). Bitte erneuern.
                            </div>
                        }
                        else if (lic.IsLicensedExpired)
                        {
                            <div class="alert alert-danger mb-0">
                                <i class="fa fa-times-circle"></i>
                                Lizenz und Karenzfrist abgelaufen. Modul deaktiviert. Bitte aktivieren Sie einen neuen Lizenzschluessel.
                            </div>
                        }
                        else if (lic.IsRemoteKilled)
                        {
                            <div class="alert alert-danger mb-0">
                                <i class="fa fa-ban"></i>
                                Vom Server gesperrt (<code>ServerLocked</code>): @lic.RemoteKillReason
                            </div>
                        }
                        else if (lic.IsTrialActive)
                        {
                            <div class="alert alert-info mb-0">
                                <i class="fa fa-clock"></i>
                                Testphase: noch <strong>@lic.TrialRemainingDays</strong> von @lic.TrialDays Tagen verbleibend.
                            </div>
                        }
                        else if (lic.IsTrialExpired)
                        {
                            <div class="alert alert-danger mb-0">
                                <i class="fa fa-exclamation-triangle"></i>
                                Testphase abgelaufen. Modul deaktiviert. Bitte aktivieren Sie eine Lizenz.
                            </div>
                        }
                        else
                        {
                            <div class="alert alert-warning mb-0">
                                Modul nicht konfiguriert. Bitte aktivieren Sie eine Lizenz.
                            </div>
                        }

                        @if (!lic.HasPublicKey)
                        {
                            <div class="alert alert-warning mt-2 mb-0 small">
                                <strong>Achtung:</strong> Es ist kein <em>Public Key</em> hinterlegt.
                                Server-Sperren werden deshalb verworfen und das Modul reagiert nicht auf eine serverseitige Deaktivierung.
                                Public Key in <code>CRS.Licensing.Server</code> &rarr; Configure kopieren und unten in <em>License Public Key Override</em> eintragen.
                            </div>
                        }

                        @if (lic.AutoActivationSuppressed)
                        {
                            <div class="alert alert-secondary mt-2 mb-0 small">
                                <i class="fa fa-pause-circle"></i>
                                <strong>Auto-Aktivierung gesperrt</strong> &mdash; nach "Lizenz entfernen" wird der Server-Key nicht automatisch wieder eingespielt.
                                <button type="button" id="HybridAllowAutoActivationBtn" class="btn btn-outline-primary btn-sm ml-2">
                                    <i class="fa fa-play"></i> Auto-Aktivierung wieder erlauben
                                </button>
                            </div>
                        }

                        @if (lic.LastHeartbeat is not null)
                        {
                            var hb = lic.LastHeartbeat;
                            <div class="small text-muted mt-2">
                                <strong>Letzter Heartbeat</strong> (State: <code>@hb.StateAtCall</code>):
                                @if (hb.Sent)
                                {
                                    <span class="badge badge-success">gesendet</span>
                                    <span> Server-Status: <code>@(string.IsNullOrEmpty(hb.Status) ? "ok" : hb.Status)</code></span>
                                    if (hb.KillApplied)
                                    {
                                        <span class="badge badge-danger ml-1">Server-Sperre angewendet: @hb.KillReason</span>
                                    }
                                    else if (string.Equals(hb.Status, "kill", StringComparison.OrdinalIgnoreCase))
                                    {
                                        <span class="badge badge-warning ml-1">Server-Sperre empfangen, aber NICHT angewendet</span>
                                        if (!string.IsNullOrWhiteSpace(hb.Error))
                                        {
                                            <span class="d-block mt-1"><strong>Grund:</strong> <code>@hb.Error</code></span>
                                        }
                                    }
                                    if (hb.AutoActivated)
                                    {
                                        <span class="badge badge-success ml-1">Auto-Aktiviert</span>
                                        if (!string.IsNullOrWhiteSpace(hb.AutoActivationLicenseKey))
                                        {
                                            <span class="ml-1">via Key <code>@hb.AutoActivationLicenseKey</code></span>
                                        }
                                    }
                                }
                                else
                                {
                                    <span class="badge badge-danger">fehlgeschlagen</span>
                                    <span> @hb.Error</span>
                                }
                                <span class="d-block">Ziel: <code>@(string.IsNullOrEmpty(lic.LicenseServerUrl) ? "—" : lic.LicenseServerUrl)</code></span>
                            </div>
                        }
                    </div>

                    @* ---------- Activate form (always visible so the user can re-activate) ---------- *@
                    <div class="adminRow">
                        <div class="adminTitle">
                            <label for="HybridLicenseKeyInput">Lizenzschluessel</label>
                        </div>
                        <div class="adminData">
                            <textarea id="HybridLicenseKeyInput" class="form-control" rows="2" autocomplete="off"
                                      placeholder="Lizenz-Schluessel (GUID) ODER Offline-Aktivierungs-Ticket"></textarea>
                            <button type="button" id="HybridLicenseActivateBtn" class="btn btn-primary mt-2">
                                <i class="fa fa-key"></i>
                                Aktivieren
                            </button>
                            @if (lic.IsLicensed || lic.IsLicensedInGrace || lic.IsLicensedExpired || lic.IsRemoteKilled)
                            {
                                <button type="button" id="HybridLicenseRemoveBtn" class="btn btn-outline-danger mt-2 ml-2">
                                    <i class="fa fa-trash"></i>
                                    Lizenz entfernen
                                </button>
                            }
                            <small class="text-muted d-block mt-1">
                                Der Schluessel steht in der Bestellbestaetigungs-Mail von crsoft.at. Bei fehlender Internet-
                                Verbindung kann der Support stattdessen ein <strong>Offline-Ticket</strong> ausstellen — auch das einfach hier einfuegen.
                            </small>
                            <div id="HybridLicenseActivateStatus" class="mt-2"></div>
                        </div>
                    </div>

                    @if (lic.LastServerPingUtc.HasValue)
                    {
                        <div class="adminRow js-advanced-only">
                            <div class="adminTitle"><label>Letzter Server-Kontakt</label></div>
                            <div class="adminData">
                                <small class="text-muted">@lic.LastServerPingUtc.Value.ToString("yyyy-MM-dd HH:mm") UTC</small>
                            </div>
                        </div>
                    }

                    <div class="adminRow js-advanced-only">
                        <div class="adminTitle">
                            <smart-label asp-for="LicenseServerUrlOverride" />
                        </div>
                        <div class="adminData">
                            <setting-editor asp-for="LicenseServerUrlOverride">
                                <input asp-for="LicenseServerUrlOverride" type="text" class="form-control" />
                            </setting-editor>
                            <small class="text-muted d-block mt-1">
                                Optional. Falls leer: Default <code>@CRS.HybridSearch.Module.LicenseOptions.LicenseServerUrl</code>.
                            </small>
                        </div>
                    </div>

                    <div class="adminRow js-advanced-only">
                        <div class="adminTitle">
                            <smart-label asp-for="LicensePublicKeyOverride" />
                        </div>
                        <div class="adminData">
                            <setting-editor asp-for="LicensePublicKeyOverride">
                                <textarea asp-for="LicensePublicKeyOverride" id="HybridLicensePublicKeyInput" class="form-control" rows="3" style="font-family: monospace; font-size: 0.85em;" placeholder="ECDSA-Public-Key (Base64)"></textarea>
                            </setting-editor>
                            <button type="button" id="HybridFetchPublicKeyBtn" class="btn btn-outline-secondary btn-sm mt-2">
                                <i class="fa fa-download"></i>
                                Public Key vom Server holen
                            </button>
                            <span id="HybridFetchPublicKeyStatus" class="ml-2 small"></span>
                            <small class="text-muted d-block mt-1">
                                Optional. Public-Key zur lokalen Verifikation von Aktivierungs-Tickets. Bei leer wird der hartcodierte Default verwendet.
                                Der Button laedt ihn direkt vom konfigurierten License-Server (<code>LicenseServerUrl</code> bzw. Override oben) und speichert ihn hier.
                            </small>
                        </div>
                    </div>

                    <script>
                        (function () {
                            // Base path of THIS Smartstore install — survives sub-path hosting
                            // ("https://kunde.de/shop/..."). The "~" resolves to the application root
                            // server-side, including any virtual directory / sub-app prefix.
                            var APP_BASE = '@Url.Content("~/")';
                            function admin(path) { return APP_BASE + 'admin/hybridsearch/' + path; }

                            // Unified POST helper: text-first response read, surfaces HTTP status
                            // + body snippet on non-2xx, surfaces non-JSON bodies (HTML error pages,
                            // login redirects) instead of failing with "Unexpected token '<'".
                            function crsPost(path, fields) {
                                var fd = new FormData();
                                if (fields) Object.keys(fields).forEach(function (k) { fd.append(k, fields[k]); });
                                var tokenEl = document.querySelector('input[name="__RequestVerificationToken"]');
                                if (tokenEl) fd.append('__RequestVerificationToken', tokenEl.value);
                                return fetch(admin(path), { method: 'POST', body: fd, credentials: 'same-origin' })
                                    .then(async function (r) {
                                        var text = await r.text();
                                        if (!r.ok) return { success: false, error: 'HTTP ' + r.status + ' ' + r.statusText + ' from ' + admin(path) + ' — body starts with: ' + text.slice(0, 160) };
                                        if (!text) return { success: false, error: 'Empty response from ' + admin(path) };
                                        try { return JSON.parse(text); }
                                        catch (e) { return { success: false, error: 'Non-JSON response from ' + admin(path) + ': ' + text.slice(0, 200) }; }
                                    });
                            }

                            var btn = document.getElementById('HybridLicenseActivateBtn');
                            var input = document.getElementById('HybridLicenseKeyInput');
                            var status = document.getElementById('HybridLicenseActivateStatus');
                            if (!btn || !input || !status) return;
                            btn.addEventListener('click', function () {
                                var key = (input.value || '').trim();
                                if (!key) {
                                    status.innerHTML = '<span class="text-danger">Bitte einen Lizenzschluessel eintragen.</span>';
                                    return;
                                }
                                status.innerHTML = '<span class="text-muted"><i class="fa fa-spinner fa-spin"></i> Aktiviere…</span>';
                                btn.disabled = true;
                                crsPost('activatelicense', { licenseKey: key })
                                .then(d => {
                                    btn.disabled = false;
                                    if (d && d.success) {
                                        status.innerHTML = '<span class="text-success"><i class="fa fa-check"></i> Lizenz aktiviert &mdash; gueltig bis ' + (d.validUntilUtc || '') + '. Seite wird neu geladen…</span>';
                                        setTimeout(function () { location.reload(); }, 1200);
                                    } else {
                                        status.innerHTML = '<span class="text-danger"><i class="fa fa-times"></i> ' + ((d && d.error) || 'Aktivierung fehlgeschlagen.') + '</span>';
                                    }
                                })
                                .catch(err => {
                                    btn.disabled = false;
                                    status.innerHTML = '<span class="text-danger">Unerwarteter Fehler: ' + (err && err.message ? err.message : err) + '</span>';
                                });
                            });

                            var allowBtn = document.getElementById('HybridAllowAutoActivationBtn');
                            if (allowBtn) {
                                allowBtn.addEventListener('click', function () {
                                    allowBtn.disabled = true;
                                    crsPost('allowautoactivation', null)
                                    .then(d => {
                                        if (d && d.success) location.reload();
                                        else { allowBtn.disabled = false; alert((d && d.error) || 'Fehlgeschlagen.'); }
                                    })
                                    .catch(err => { allowBtn.disabled = false; alert('Unerwarteter Fehler: ' + (err && err.message ? err.message : err)); });
                                });
                            }

                            var fetchPkBtn = document.getElementById('HybridFetchPublicKeyBtn');
                            var fetchPkStatus = document.getElementById('HybridFetchPublicKeyStatus');
                            var pkInput = document.getElementById('HybridLicensePublicKeyInput');
                            if (fetchPkBtn && fetchPkStatus && pkInput) {
                                fetchPkBtn.addEventListener('click', function () {
                                    fetchPkStatus.innerHTML = '<span class="text-muted"><i class="fa fa-spinner fa-spin"></i> Hole…</span>';
                                    fetchPkBtn.disabled = true;
                                    crsPost('fetchpublickey', null)
                                    .then(d => {
                                        fetchPkBtn.disabled = false;
                                        if (d && d.success && d.publicKey) {
                                            pkInput.value = d.publicKey;
                                            fetchPkStatus.innerHTML = '<span class="text-success"><i class="fa fa-check"></i> Geholt &amp; gespeichert. Seite wird neu geladen…</span>';
                                            setTimeout(function () { location.reload(); }, 900);
                                        } else {
                                            fetchPkStatus.innerHTML = '<span class="text-danger">' + ((d && d.error) || 'Fehlgeschlagen.') + '</span>';
                                        }
                                    })
                                    .catch(err => {
                                        fetchPkBtn.disabled = false;
                                        fetchPkStatus.innerHTML = '<span class="text-danger">Unerwarteter Fehler: ' + (err && err.message ? err.message : err) + '</span>';
                                    });
                                });
                            }

                            var removeBtn = document.getElementById('HybridLicenseRemoveBtn');
                            if (removeBtn) {
                                removeBtn.addEventListener('click', function () {
                                    if (!confirm('Lizenz aus dieser Installation entfernen?\n\nDas Modul faellt auf Trial/Expired zurueck. Der zentrale Lizenz-Server merkt sich nichts davon — falls Du den Schluessel wieder hier brauchst, einfach erneut einfuegen.')) return;
                                    removeBtn.disabled = true;
                                    crsPost('removelicense', null)
                                    .then(d => {
                                        if (d && d.success) location.reload();
                                        else { removeBtn.disabled = false; alert((d && d.error) || 'Entfernen fehlgeschlagen.'); }
                                    })
                                    .catch(err => { removeBtn.disabled = false; alert('Unerwarteter Fehler: ' + (err && err.message ? err.message : err)); });
                                });
                            }
                        })();
                    </script>
                }
                else if (ViewBag.TrialInfo is CRS.HybridSearch.Services.TrialInfo trial)
                {
                    @* Fallback: legacy trial banner if ICrsLicenseService isn't wired up yet *@
                    <div class="adminRow">
                        <div class="adminData">
                            @if (trial.IsExpired)
                            {
                                <div class="alert alert-danger">
                                    <i class="fa fa-exclamation-triangle"></i>
                                    Die Testphase ist abgelaufen. Das Modul ist deaktiviert. Bitte aktivieren Sie eine Lizenz.
                                </div>
                            }
                            else
                            {
                                <div class="alert alert-info">
                                    <i class="fa fa-clock"></i>
                                    Testphase: noch <strong>@trial.RemainingDays</strong> von @trial.TrialDays Tagen verbleibend.
                                </div>
                            }
                        </div>
                    </div>
                }

                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.InstantSearchAppearance")</div>
                        <div class="text-muted small">@T("Plugins.CRS.HybridSearch.InstantSearchAppearance.Hint")</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="InstantSearchBgPictureId" /></div>
                    <div class="adminData"><editor asp-for="InstantSearchBgPictureId" /></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="InstantSearchBgPictureOpacity" /></div>
                    <div class="adminData">
                        @* Live-updating range slider — same pattern as glass-opacity. *@
                        <div class="d-flex align-items-center" style="gap:10px">
                            <input type="range" min="0" max="100" step="1" asp-for="InstantSearchBgPictureOpacity"
                                   class="form-range flex-grow-1"
                                   oninput="this.parentElement.querySelector('.badge').textContent=this.value+'%'" />
                            <span class="badge bg-secondary" style="min-width:46px">@Model.InstantSearchBgPictureOpacity%</span>
                        </div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="InstantSearchBgPictureCover" /></div>
                    <div class="adminData"><setting-editor asp-for="InstantSearchBgPictureCover"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="InstantSearchBgColor" /></div>
                    <div class="adminData"><setting-editor asp-for="InstantSearchBgColor"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="InstantSearchGlassEnabled" /></div>
                    <div class="adminData"><setting-editor asp-for="InstantSearchGlassEnabled"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="InstantSearchGlassOpacity" /></div>
                    <div class="adminData">
                        <div class="d-flex align-items-center" style="gap:10px">
                            <input type="range" min="0" max="100" step="1" asp-for="InstantSearchGlassOpacity"
                                   class="form-range flex-grow-1"
                                   oninput="this.parentElement.querySelector('.badge').textContent=this.value+'%'" />
                            <span class="badge bg-secondary" style="min-width:46px">@Model.InstantSearchGlassOpacity%</span>
                        </div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="InstantSearchBorderRadius" /></div>
                    <div class="adminData">
                        <div class="d-flex align-items-center" style="gap:10px">
                            <input type="range" min="0" max="32" step="1" asp-for="InstantSearchBorderRadius"
                                   class="form-range flex-grow-1"
                                   oninput="this.parentElement.querySelector('.badge').textContent=this.value+'px'" />
                            <span class="badge bg-secondary" style="min-width:46px">@(Model.InstantSearchBorderRadius)px</span>
                        </div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="InstantSearchHover3D" /></div>
                    <div class="adminData"><setting-editor asp-for="InstantSearchHover3D"></setting-editor></div>
                </div>

                @* Setup: rescue button for upgrade scenarios where the old plugin DLL stayed
                   installed (InstallAsync never ran, tuned defaults never written). Force-
                   re-applies the snapshot from `Module.BuildTunedDefaults` and bypasses the
                   install-time sentinel. Overwrites every HybridSearchSettings.* row, so the
                   operator confirms before triggering. *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.Setup")</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle">
                        <label class="col-form-label">@T("Plugins.CRS.HybridSearch.Setup.ResetDefaults.Title")</label>
                        <div class="muted small mt-1">@T("Plugins.CRS.HybridSearch.Setup.ResetDefaults.Hint")</div>
                    </div>
                    <div class="adminData">
                        <form asp-action="ResetToTunedDefaults" method="post" class="d-inline-block"
                              onsubmit="return confirm('@T("Plugins.CRS.HybridSearch.Setup.ResetDefaults.Confirm")');">
                            <button type="submit" class="btn btn-warning">
                                <i class="fa fa-undo"></i>
                                @T("Plugins.CRS.HybridSearch.Setup.ResetDefaults.Button")
                            </button>
                        </form>
                    </div>
                </div>

                <div class="adminRow js-advanced-only">
                    <div class="admin-config-group">
                        <div class="head">Logging</div>
                    </div>
                </div>
                <div class="adminRow js-advanced-only">
                    <div class="adminTitle"><smart-label asp-for="EnableDebugLogging" /></div>
                    <div class="adminData"><setting-editor asp-for="EnableDebugLogging"></setting-editor></div>
                </div>
                <div class="adminRow js-advanced-only">
                    <div class="adminTitle"><smart-label asp-for="ShowSearchTime" /></div>
                    <div class="adminData"><setting-editor asp-for="ShowSearchTime"></setting-editor></div>
                </div>
                <div class="adminRow js-advanced-only">
                    <div class="adminTitle"><smart-label asp-for="LogSearch" /></div>
                    <div class="adminData"><setting-editor asp-for="LogSearch"></setting-editor></div>
                </div>
                <div class="adminRow js-advanced-only">
                    <div class="adminTitle"><smart-label asp-for="LogFacets" /></div>
                    <div class="adminData"><setting-editor asp-for="LogFacets"></setting-editor></div>
                </div>
                <div class="adminRow js-advanced-only">
                    <div class="adminTitle"><smart-label asp-for="LogPerformance" /></div>
                    <div class="adminData"><setting-editor asp-for="LogPerformance"></setting-editor></div>
                </div>
                <div class="adminRow js-advanced-only">
                    <div class="adminTitle"><smart-label asp-for="LogOutputCache" /></div>
                    <div class="adminData"><setting-editor asp-for="LogOutputCache"></setting-editor></div>
                </div>
                <div class="adminRow js-advanced-only">
                    <div class="adminTitle"><smart-label asp-for="LogTrial" /></div>
                    <div class="adminData"><setting-editor asp-for="LogTrial"></setting-editor></div>
                </div>
            </div>
        </tab>

        @* amamamamamamam TAB 1: Lucene Search amamamamamamam *@
        <tab sm-title="Lucene Suche" sm-icon="fa fa-search">
            <div class="adminContent">
                @* --- Aktivierung --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">Aktivierung</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="Enabled" /></div>
                    <div class="adminData"><setting-editor asp-for="Enabled"></setting-editor></div>
                </div>

                @* ---- BEGIN advanced (hidden when AdvancedMode = false), ends just before "Index-Verwaltung" ---- *@
                <div class="js-advanced-only">
                @* --- Indexing --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">Indexierung</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="AlwaysRebuildIndex" /></div>
                    <div class="adminData"><setting-editor asp-for="AlwaysRebuildIndex"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="BatchSize" /></div>
                    <div class="adminData"><setting-editor asp-for="BatchSize"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="IndexFullDescription" /></div>
                    <div class="adminData"><setting-editor asp-for="IndexFullDescription"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="StoreTermPositions" /></div>
                    <div class="adminData"><setting-editor asp-for="StoreTermPositions"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="ShowHitCounts" /></div>
                    <div class="adminData"><setting-editor asp-for="ShowHitCounts"></setting-editor></div>
                </div>

                @* --- Search Behavior --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.GroupSearch")</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="HitsContainAllSearchedTerms" /></div>
                    <div class="adminData"><setting-editor asp-for="HitsContainAllSearchedTerms"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="InstantSearchAllFields" /></div>
                    <div class="adminData"><setting-editor asp-for="InstantSearchAllFields"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="MinTermLength" /></div>
                    <div class="adminData"><setting-editor asp-for="MinTermLength"></setting-editor></div>
                </div>

                @* --- Features --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.GroupFeatures")</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="DemoteUnavailableProducts" /></div>
                    <div class="adminData"><setting-editor asp-for="DemoteUnavailableProducts"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="IsSpellCheckerActive" /></div>
                    <div class="adminData"><setting-editor asp-for="IsSpellCheckerActive"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="SpellCheckerMaxSuggestions" /></div>
                    <div class="adminData"><setting-editor asp-for="SpellCheckerMaxSuggestions"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="SpellCheckerMinQueryLength" /></div>
                    <div class="adminData"><setting-editor asp-for="SpellCheckerMinQueryLength"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="IsTopCategoriesActive" /></div>
                    <div class="adminData"><setting-editor asp-for="IsTopCategoriesActive"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="MaxTopCategories" /></div>
                    <div class="adminData"><setting-editor asp-for="MaxTopCategories"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="IsTopManufacturersActive" /></div>
                    <div class="adminData"><setting-editor asp-for="IsTopManufacturersActive"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="MaxTopManufacturers" /></div>
                    <div class="adminData"><setting-editor asp-for="MaxTopManufacturers"></setting-editor></div>
                </div>

                @* --- Boosting --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.GroupBoosting")</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="EnableBoost" /></div>
                    <div class="adminData"><setting-editor asp-for="EnableBoost"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="BoostName" /></div>
                    <div class="adminData"><setting-editor asp-for="BoostName"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="BoostSku" /></div>
                    <div class="adminData"><setting-editor asp-for="BoostSku"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="BoostShortDescription" /></div>
                    <div class="adminData"><setting-editor asp-for="BoostShortDescription"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="BoostTags" /></div>
                    <div class="adminData"><setting-editor asp-for="BoostTags"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="BoostKeywords" /></div>
                    <div class="adminData"><setting-editor asp-for="BoostKeywords"></setting-editor></div>
                </div>

                @* --- Lucene Performance --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.GroupPerformance")</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="EnableCacheBoost" /></div>
                    <div class="adminData"><setting-editor asp-for="EnableCacheBoost"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="UseSortedSetFacets" /></div>
                    <div class="adminData"><setting-editor asp-for="UseSortedSetFacets"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="ForceMergeAfterRebuild" /></div>
                    <div class="adminData"><setting-editor asp-for="ForceMergeAfterRebuild"></setting-editor></div>
                </div>
                </div>
                @* ---- END advanced ---- *@

                @* --- Index Actions --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.GroupIndex")</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminData">
                        <div class="d-grid gap-2" style="grid-template-columns: repeat(auto-fill, 220px);"
                            <button type="button" id="btnRebuildIndex" class="btn btn-primary">
                                <i class="fa fa-sync"></i>
                                <span>@T("Plugins.CRS.HybridSearch.RebuildIndex")</span>
                            </button>
                            <button type="button" id="btnUpdateIndex" class="btn btn-secondary">
                                <i class="fa fa-refresh"></i>
                                <span>@T("Plugins.CRS.HybridSearch.UpdateIndex")</span>
                            </button>
                            <button type="button" id="btnDeleteIndex" class="btn btn-danger">
                                <i class="fa fa-trash"></i>
                                <span>@T("Plugins.CRS.HybridSearch.DeleteIndex")</span>
                            </button>
                            <a href="@Url.Action("OpenScheduledTask", "HybridSearchAdmin", new { area = "Admin" })" class="btn btn-outline-secondary">
                                <i class="fa fa-clock"></i>
                                <span>Scheduled Task</span>
                            </a>
                        </div>
                        <div class="mt-2">
                            <span id="indexActionResult"></span>
                            <span id="indexProgress" class="ml-2 text-muted small"></span>
                        </div>
                    </div>
                </div>

                @* --- Index Status --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.GroupIndexStatus")</div>
                    </div>
                </div>
                <div class="adminRow wide">
                    <div class="adminData wide">
                        @await Html.PartialAsync("_ScopeList")
                    </div>
                </div>

                @* --- Text Analysis --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.GroupTextAnalysis")</div>
                    </div>
                </div>
                <div class="adminRow wide">
                    <div class="adminData wide">
                        @await Html.PartialAsync("_TextAnalysis")
                    </div>
                </div>
            </div>
        </tab>

        @* amamamamamamam TAB 2: KI Suche — only rendered if the BGE-M3 ONNX model is present locally amamamamamamam *@
        @if (ViewBag.HasBgeModel == true)
        {
        <tab sm-title="KI Suche" sm-icon="fa fa-brain">
            <div class="adminContent">
                <div class="alert alert-info mb-4">
                    <i class="fa fa-brain fa-lg mr-2"></i>
                    <strong>Semantische KI-Suche</strong> &mdash;
                    Die KI-Suche ergaenzt die Lucene-Volltextsuche um semantisches Verstaendnis.
                    Sie erkennt Bedeutung, Synonyme und natuerlichsprachige Umschreibungen
                    (z.B. <em>"das Ding das man sich vors Gesicht haengt um keinen Rauch einzuatmen"</em> findet Atemschutzmasken).
                    <br class="mt-1"/>
                    <strong>Voraussetzung:</strong> Die Lucene-Suche muss auf dem Tab "Lucene-Suche" aktiviert sein.
                    Die KI-Suche erweitert und verbessert die bestehenden Suchergebnisse &mdash; sie ersetzt die Lucene-Suche nicht.
                </div>
                @* --- Semantische Suche --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.GroupVectorSearch")</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="EnableVectorSearch" /></div>
                    <div class="adminData"><setting-editor asp-for="EnableVectorSearch"></setting-editor></div>
                </div>

                @* ---- BEGIN advanced (hidden when AdvancedMode = false), ends just before "Vektor-Aktionen" ---- *@
                <div class="js-advanced-only">
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="EmbeddingProvider" /></div>
                    <div class="adminData">
                        <select asp-for="EmbeddingProvider" class="form-control">
                            <option value="onnx">ONNX BGE-M3 (lokal CPU/GPU)</option>
                            <option value="remote">Remote HTTP Endpoint</option>
                        </select>
                        <span asp-validation-for="EmbeddingProvider"></span>
                    </div>
                </div>
                <div id="onnxProviderRows">
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OnnxModelPath" /></div>
                    <div class="adminData"><setting-editor asp-for="OnnxModelPath"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OnnxExecutionProvider" /></div>
                    <div class="adminData">
                        <select asp-for="OnnxExecutionProvider" class="form-control">
                            <option value="auto">Auto (empfohlen - waehlt automatisch CPU oder DirectML)</option>
                            <option value="cpu">CPU (immer CPU)</option>
                            <option value="directml">DirectML (immer DirectML mit fester Device-ID)</option>
                        </select>
                        @* Hidden fields preserve the auto-selection across Configure POST. *@
                        <input type="hidden" asp-for="OnnxAutoSelectedProvider" />
                        <input type="hidden" asp-for="OnnxAutoSelectedDescription" />
                        @if (!string.IsNullOrEmpty(Model.OnnxAutoSelectedProvider))
                        {
                            <div class="text-muted small mt-1">
                                <i class="fa fa-info-circle"></i> Auto-Auswahl: <code>@Model.OnnxAutoSelectedProvider</code>
                                @if (!string.IsNullOrEmpty(Model.OnnxAutoSelectedDescription))
                                {
                                    <br/><span>@Model.OnnxAutoSelectedDescription</span>
                                }
                            </div>
                        }
                        else
                        {
                            <div class="text-warning small mt-1">
                                <i class="fa fa-exclamation-triangle"></i> Noch kein Hardware-Benchmark durchgefuehrt - bei "auto" wird CPU verwendet.
                            </div>
                        }
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OnnxDirectMlDeviceId" /></div>
                    <div class="adminData">
                        <setting-editor asp-for="OnnxDirectMlDeviceId"></setting-editor>
                        <small class="text-muted d-block mt-1">Nur relevant wenn Provider auf "DirectML" gestellt ist (manueller Modus).</small>
                        <div class="d-flex flex-wrap gap-2 align-items-center mt-2">
                            <button type="button" id="btnRunHardwareBenchmark" class="btn btn-outline-success">
                                <i class="fa fa-tachometer-alt"></i>
                                <span>Hardware-Auto-Detection</span>
                            </button>
                            <button type="button" id="btnListDirectMlDevices" class="btn btn-outline-info">
                                <i class="fa fa-search"></i>
                                <span>Geraete auflisten + benchmarken</span>
                            </button>
                        </div>
                        <div id="hardwareBenchmarkResult" class="mt-2"></div>
                        <div id="directMlDevicesResult" class="mt-2"></div>
                    </div>
                </div>
                </div>@* /#onnxProviderRows *@

                <div id="remoteProviderRows">
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="RemoteEmbeddingEndpoint" /></div>
                    <div class="adminData"><setting-editor asp-for="RemoteEmbeddingEndpoint"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="RemoteEmbeddingAuthScheme" /></div>
                    <div class="adminData">
                        <select asp-for="RemoteEmbeddingAuthScheme" class="form-control" id="RemoteEmbeddingAuthScheme">
                            <option value="None">Keine</option>
                            <option value="Bearer">Bearer Token (HuggingFace, TEI, OpenAI)</option>
                            <option value="ApiKeyHeader">Custom Header (Azure, Anthropic, Qdrant-Style)</option>
                            <option value="Basic">Basic Auth (Username + Passwort)</option>
                        </select>
                    </div>
                </div>
                <div class="adminRow" id="row_RemoteEmbeddingAuthHeaderName">
                    <div class="adminTitle"><smart-label asp-for="RemoteEmbeddingAuthHeaderName" /></div>
                    <div class="adminData"><setting-editor asp-for="RemoteEmbeddingAuthHeaderName"></setting-editor></div>
                </div>
                <div class="adminRow" id="row_RemoteEmbeddingBasicUser">
                    <div class="adminTitle"><smart-label asp-for="RemoteEmbeddingBasicUser" /></div>
                    <div class="adminData"><setting-editor asp-for="RemoteEmbeddingBasicUser"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="RemoteEmbeddingApiKey" /></div>
                    <div class="adminData"><input asp-for="RemoteEmbeddingApiKey" type="password" class="form-control" autocomplete="off" /></div>
                </div>
                </div>@* /#remoteProviderRows *@
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="EmbeddingBatchSize" /></div>
                    <div class="adminData"><setting-editor asp-for="EmbeddingBatchSize"></setting-editor></div>
                </div>

                @* --- Hybrid-Search Einstellungen --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.GroupVectorSettings")</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="RrfConstant" /></div>
                    <div class="adminData"><setting-editor asp-for="RrfConstant"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="VectorSearchWeight" /></div>
                    <div class="adminData"><setting-editor asp-for="VectorSearchWeight"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="VectorSearchTopN" /></div>
                    <div class="adminData"><setting-editor asp-for="VectorSearchTopN"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="InstantSearchCapKiAtLimit" /></div>
                    <div class="adminData">
                        <setting-editor asp-for="InstantSearchCapKiAtLimit"></setting-editor>
                        <small class="text-muted d-block mt-1">An: KI fuellt nur die vom Lucene-Suchergebnis offen gelassenen Plaetze bis zum globalen InstantSearch-Limit auf (Anzahl der Treffer). Aus: KI-Treffer werden unabhaengig vom Limit zusaetzlich angezeigt.</small>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="InstantSearchMaxKiHits" /></div>
                    <div class="adminData">
                        <setting-editor asp-for="InstantSearchMaxKiHits"></setting-editor>
                        <small class="text-muted d-block mt-1">Nur relevant im "Add"-Modus (Cap aus): maximale Anzahl semantischer KI-Treffer, die zusaetzlich zu den Lucene-Treffern angezeigt werden. Default: 8.</small>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="CosineSimilarityThreshold" /></div>
                    <div class="adminData"><setting-editor asp-for="CosineSimilarityThreshold"></setting-editor></div>
                </div>

                @* --- Vektor-Speicher --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">Vektor-Speicher</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="VectorStoreProvider" /></div>
                    <div class="adminData">
                        <select asp-for="VectorStoreProvider" class="form-control">
                            <option value="local">Lokal (App_Data, bis ~2M Produkte)</option>
                            <option value="qdrant">Qdrant (externer Service, unbegrenzt)</option>
                        </select>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="QdrantUrl" /></div>
                    <div class="adminData">
                        <setting-editor asp-for="QdrantUrl"></setting-editor>
                        <small class="text-muted d-block mt-1">Lokal: http://localhost:6333 | Cloud: https://xxx.cloud.qdrant.io</small>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="QdrantApiKey" /></div>
                    <div class="adminData">
                        <input asp-for="QdrantApiKey" type="password" class="form-control" autocomplete="off" />
                        <small class="text-muted d-block mt-1">Nur fuer Qdrant Cloud erforderlich (JWT API-Key). Leer lassen fuer lokale Instanzen.</small>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="QdrantCollectionName" /></div>
                    <div class="adminData"><setting-editor asp-for="QdrantCollectionName"></setting-editor></div>
                </div>
                </div>
                @* ---- END advanced ---- *@

                @* --- Vektor-Aktionen --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.GroupVectorActions")</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminData">
                        <div class="d-grid gap-2" style="grid-template-columns: repeat(auto-fill, 220px);">
                            <button type="button" id="btnRebuildVectorIndex" class="btn btn-primary">
                                <i class="fa fa-sync"></i>
                                <span>Vektor-Index neu erstellen</span>
                            </button>
                            <button type="button" id="btnUpdateVectorIndex" class="btn btn-secondary">
                                <i class="fa fa-refresh"></i>
                                <span>Vektor-Index aktualisieren</span>
                            </button>
                            <button type="button" id="btnDeleteVectors" class="btn btn-danger">
                                <i class="fa fa-trash"></i>
                                <span>@T("Plugins.CRS.HybridSearch.VectorDeleteAll")</span>
                            </button>
                            <button type="button" id="btnTestEmbedding" class="btn btn-outline-primary">
                                <i class="fa fa-flask"></i>
                                <span>@T("Plugins.CRS.HybridSearch.VectorTestSearch")</span>
                            </button>
                            <a href="@Url.Action("OpenVectorScheduledTask", "HybridSearchAdmin", new { area = "Admin" })" class="btn btn-outline-secondary">
                                <i class="fa fa-clock"></i>
                                <span>Scheduled Task</span>
                            </a>
                        </div>
                        <div class="mt-2">
                            <span id="vectorActionResult"></span>
                            <span id="vectorProgress" class="ml-2 text-muted small"></span>
                        </div>
                    </div>
                </div>

                @* --- Test Embedding Result --- *@
                <div id="vectorTestResult" class="adminRow" style="display:none;">
                    <div class="adminData">
                        <div class="card card-body bg-light">
                            <pre id="vectorTestOutput" class="mb-0" style="white-space: pre-wrap; font-size: 0.85em;"></pre>
                        </div>
                    </div>
                </div>

                @* --- Vektor-Status --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">@T("Plugins.CRS.HybridSearch.GroupVectorStatus")</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminData">
                        <div id="vectorStatusInfo" class="text-muted small">
                            Lade...
                        </div>
                    </div>
                </div>
            </div>
        </tab>
        }

        @* amamamamamamam TAB 3: Bestell-Suche amamamamamamam *@
        <tab sm-title="Bestell-Suche" sm-icon="fa fa-receipt">
            <div class="adminContent">
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">Order-Index</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OrderIndexEnabled" /></div>
                    <div class="adminData"><setting-editor asp-for="OrderIndexEnabled"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OrderIndexBatchSize" /></div>
                    <div class="adminData"><setting-editor asp-for="OrderIndexBatchSize"></setting-editor></div>
                </div>

                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">Index-Aktionen</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminData">
                        <div class="d-grid gap-2" style="grid-template-columns: repeat(auto-fill, 220px);"
                            <button type="button" id="btnRebuildOrderIndex" class="btn btn-primary">
                                <i class="fa fa-sync"></i>
                                <span>Index neu erstellen</span>
                            </button>
                            <button type="button" id="btnUpdateOrderIndex" class="btn btn-secondary">
                                <i class="fa fa-refresh"></i>
                                <span>Index aktualisieren</span>
                            </button>
                            <button type="button" id="btnDeleteOrderIndex" class="btn btn-danger">
                                <i class="fa fa-trash"></i>
                                <span>Index loeschen</span>
                            </button>
                            <a href="@Url.Action("OpenOrderScheduledTask", "HybridSearchAdmin", new { area = "Admin" })" class="btn btn-outline-secondary">
                                <i class="fa fa-clock"></i>
                                <span>Scheduled Task</span>
                            </a>
                        </div>
                        <div class="mt-2">
                            <span id="orderIndexActionResult"></span>
                            <span id="orderIndexProgress" class="ml-2 text-muted small"></span>
                        </div>
                    </div>
                </div>

                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">Index-Status</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminData">
                        <div id="orderIndexStats" class="text-muted small">
                            Lade...
                        </div>
                    </div>
                </div>
            </div>
        </tab>

        @* amamamamamamam TAB 4: Performance & Cache amamamamamamam *@
        <tab sm-title="Performance & Cache" sm-icon="fa fa-bolt">
            <div class="adminContent">
                @* --- Output Cache --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">Output Cache</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OutputCacheEnabled" /></div>
                    <div class="adminData"><setting-editor asp-for="OutputCacheEnabled"></setting-editor></div>
                </div>

                @* ---- BEGIN advanced (hidden when AdvancedMode = false), runs to end of tab ---- *@
                <div class="js-advanced-only">
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OutputCacheDuration" /></div>
                    <div class="adminData"><setting-editor asp-for="OutputCacheDuration"></setting-editor></div>
                </div>

                @* --- Cacheable Pages --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">Cacheable Pages</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OutputCacheHomePage" /></div>
                    <div class="adminData"><setting-editor asp-for="OutputCacheHomePage"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OutputCacheCategoryPages" /></div>
                    <div class="adminData"><setting-editor asp-for="OutputCacheCategoryPages"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OutputCacheProductPages" /></div>
                    <div class="adminData"><setting-editor asp-for="OutputCacheProductPages"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OutputCacheManufacturerPages" /></div>
                    <div class="adminData"><setting-editor asp-for="OutputCacheManufacturerPages"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OutputCacheSearchResults" /></div>
                    <div class="adminData"><setting-editor asp-for="OutputCacheSearchResults"></setting-editor></div>
                </div>
                <div class="adminRow">
                    <div class="adminTitle"><smart-label asp-for="OutputCacheTopicPages" /></div>
                    <div class="adminData"><setting-editor asp-for="OutputCacheTopicPages"></setting-editor></div>
                </div>

                @* --- Cache Actions --- *@
                <div class="adminRow">
                    <div class="admin-config-group">
                        <div class="head">Cache Management</div>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminData">
                        <button type="button" id="btnClearOutputCache" class="btn btn-warning">
                            <i class="fa fa-broom"></i>
                            <span>Output Cache leeren</span>
                        </button>
                        <span id="cacheActionResult" class="ml-3"></span>
                    </div>
                </div>
                <div class="adminRow">
                    <div class="adminData">
                        <div id="cacheStats" class="text-muted small mt-2">
                            Cache-Statistiken werden geladen...
                        </div>
                    </div>
                </div>
                </div>
                @* ---- END advanced ---- *@
            </div>
        </tab>

        @* amamamamamamam TAB: HybridMenu amamamamamamam *@
        @* fa-bars matches the visual language of the other tabs (Lucene/KI/Bestell-Suche
           all use FontAwesome). Bootstrap Icons (bi-...) are not loaded by the Smartstore
           admin layout, so the previous `bi bi-menu-down` rendered as an empty box. *@
        <tab sm-title="Hybrid-Menu" sm-icon="fa fa-bars">
            <partial name="_Configure.HybridMenu" model="Model" />
        </tab>

    </tabstrip>
</form>

<script>
    $(function () {
        // --- Advanced-Mode Toggle: flips a wrapper class on the form. CSS handles the actual
        //     visibility (zero flash on page-load — the server already renders the form with the
        //     correct class based on the saved setting). Toggling the checkbox shows/hides
        //     immediately without a save; the saved value only affects the initial page state.
        function applyAdvancedMode() {
            var on = $('#AdvancedMode').is(':checked');
            $('form').toggleClass('crs-no-advanced', !on);
        }
        $('#AdvancedMode').on('change', applyAdvancedMode);

        // --- Embedding-Provider Toggle: show only the rows relevant to the selected provider. ---
        function updateEmbeddingProviderRows() {
            var provider = $('#EmbeddingProvider').val();
            if (provider === 'remote') {
                $('#onnxProviderRows').hide();
                $('#remoteProviderRows').show();
            } else {
                $('#onnxProviderRows').show();
                $('#remoteProviderRows').hide();
            }
        }
        function updateRemoteAuthRows() {
            var scheme = $('#RemoteEmbeddingAuthScheme').val();
            $('#row_RemoteEmbeddingAuthHeaderName').toggle(scheme === 'ApiKeyHeader');
            $('#row_RemoteEmbeddingBasicUser').toggle(scheme === 'Basic');
        }
        $('#EmbeddingProvider').on('change', updateEmbeddingProviderRows);
        $('#RemoteEmbeddingAuthScheme').on('change', updateRemoteAuthRows);
        updateEmbeddingProviderRows();
        updateRemoteAuthRows();

        function runIndexAction(url, label) {
            var $result = $('#indexActionResult');
            $('#btnRebuildIndex, #btnUpdateIndex, #btnDeleteIndex').prop('disabled', true);
            $result.text(label).removeClass('text-success text-danger');
            startProgressPolling();

            $.ajax({
                url: url,
                type: 'POST',
                timeout: 0, // no timeout (indexing can take minutes)
                success: function (data) {
                    $result.text(data.message).toggleClass('text-success', data.success).toggleClass('text-danger', !data.success);
                },
                error: function () { $result.text('Request failed.').addClass('text-danger'); },
                complete: function () {
                    $('#btnRebuildIndex, #btnUpdateIndex, #btnDeleteIndex').prop('disabled', false);
                    stopProgressPolling();
                    $('#indexProgress').text('');
                    if (typeof window.refreshIndexStatus === 'function') window.refreshIndexStatus();
                }
            });
        }

        $('#btnRebuildIndex').on('click', function () {
            runIndexAction('@Url.Action("RebuildIndex", "HybridSearchAdmin", new { area = "Admin" })', 'Rebuilding...');
        });

        $('#btnUpdateIndex').on('click', function () {
            runIndexAction('@Url.Action("UpdateIndex", "HybridSearchAdmin", new { area = "Admin" })', 'Updating...');
        });

        $('#btnDeleteIndex').on('click', function () {
            if (!confirm('Are you sure?')) return;
            var $btn = $(this);
            var $result = $('#indexActionResult');
            $btn.prop('disabled', true);

            $.ajax({
                url: '@Url.Action("DeleteIndex", "HybridSearchAdmin", new { area = "Admin" })',
                type: 'POST',
                success: function (data) {
                    $result.text(data.message).toggleClass('text-success', data.success).toggleClass('text-danger', !data.success);
                },
                complete: function () {
                    $btn.prop('disabled', false);
                    if (typeof window.refreshIndexStatus === 'function') window.refreshIndexStatus();
                }
            });
        });

        $('#btnClearOutputCache').on('click', function () {
            var $btn = $(this);
            var $result = $('#cacheActionResult');
            $btn.prop('disabled', true);
            $result.text('Clearing...').removeClass('text-success text-danger');

            $.ajax({
                url: '@Url.Action("ClearOutputCache", "HybridSearchAdmin", new { area = "Admin" })',
                type: 'POST',
                success: function (data) {
                    $result.text(data.message).toggleClass('text-success', data.success).toggleClass('text-danger', !data.success);
                    loadCacheStats();
                },
                error: function () { $result.text('Request failed.').addClass('text-danger'); },
                complete: function () { $btn.prop('disabled', false); }
            });
        });

        function loadCacheStats() {
            $.get('@Url.Action("OutputCacheStats", "HybridSearchAdmin", new { area = "Admin" })', function (data) {
                $('#cacheStats').html(
                    '<strong>' + data.count + '</strong> Eintraege im Cache' +
                    (data.enabled ? ' <span class="badge badge-success">Aktiv</span>' : ' <span class="badge badge-secondary">Deaktiviert</span>')
                );
            }).fail(function () {
                $('#cacheStats').text('Statistiken nicht verfuegbar.');
            });
        }

        loadCacheStats();

        // Index progress polling
        var progressTimer = null;
        function startProgressPolling() {
            $('#indexProgress').text('');
            progressTimer = setInterval(function () {
                $.get('@Url.Action("IndexProgress", "HybridSearchAdmin", new { area = "Admin" })', function (data) {
                    if (data.isRunning) {
                        $('#indexProgress').html('<i class="fa fa-spinner fa-spin"></i> ' + data.percent + '% - ' + data.message);
                    } else {
                        $('#indexProgress').text('');
                        stopProgressPolling();
                    }
                });
            }, 3000);
        }
        function stopProgressPolling() {
            if (progressTimer) { clearInterval(progressTimer); progressTimer = null; }
        }

        // --- Order Index ---
        function runOrderIndexAction(url, label) {
            var $result = $('#orderIndexActionResult');
            $('#btnRebuildOrderIndex, #btnUpdateOrderIndex, #btnDeleteOrderIndex').prop('disabled', true);
            $result.text(label).removeClass('text-success text-danger');

            $.ajax({
                url: url,
                type: 'POST',
                timeout: 0,
                success: function (data) {
                    $result.text(data.message).toggleClass('text-success', data.success).toggleClass('text-danger', !data.success);
                    loadOrderIndexStats();
                },
                error: function () { $result.text('Request failed.').addClass('text-danger'); },
                complete: function () {
                    $('#btnRebuildOrderIndex, #btnUpdateOrderIndex, #btnDeleteOrderIndex').prop('disabled', false);
                }
            });
        }

        $('#btnRebuildOrderIndex').on('click', function () {
            runOrderIndexAction('@Url.Action("RebuildOrderIndex", "HybridSearchAdmin", new { area = "Admin" })', 'Rebuilding Order-Index...');
        });
        $('#btnUpdateOrderIndex').on('click', function () {
            runOrderIndexAction('@Url.Action("UpdateOrderIndex", "HybridSearchAdmin", new { area = "Admin" })', 'Updating Order-Index...');
        });
        $('#btnDeleteOrderIndex').on('click', function () {
            if (!confirm('Order-Index wirklich loeschen?')) return;
            runOrderIndexAction('@Url.Action("DeleteOrderIndex", "HybridSearchAdmin", new { area = "Admin" })', 'Deleting...');
        });

        function loadOrderIndexStats() {
            $.get('@Url.Action("OrderIndexStatus", "HybridSearchAdmin", new { area = "Admin" })', function (data) {
                if (data.exists) {
                    $('#orderIndexStats').html(
                        '<strong>Orders:</strong> ' + data.orderCount +
                        ' | <strong>Kunden:</strong> ' + data.customerCount +
                        ' | <strong>Adressen:</strong> ' + data.addressCount +
                        ' | <strong>Gesamt:</strong> ' + data.totalDocuments +
                        ' | <strong>Groesse:</strong> ' + data.indexSizeFormatted
                    );
                } else {
                    $('#orderIndexStats').text('Kein Index vorhanden.');
                }
            }).fail(function () {
                $('#orderIndexStats').text('Status nicht verfuegbar.');
            });
        }
        loadOrderIndexStats();

        // --- Vector Search (KI Suche) ---
        function loadVectorStatus() {
            $.get('@Url.Action("VectorStatus", "HybridSearchAdmin", new { area = "Admin" })', function (data) {
                var providerBadge = data.activeProvider
                    ? ' <span class="badge badge-' + (data.activeProvider.indexOf('directml') >= 0 ? 'success' : 'secondary') + '">' + data.activeProvider + '</span>'
                    : '';
                var html = '<strong>Embedding:</strong> ' + data.provider + providerBadge +
                    ' | <strong>Verfuegbar:</strong> ' + (data.available ? '<span class="text-success">Ja</span>' : '<span class="text-danger">Nein</span>') +
                    ' | <strong>Dimensionen:</strong> ' + data.dimension +
                    '<br/><strong>Speicher:</strong> ' + data.storeProvider +
                    ' | <strong>Erreichbar:</strong> ' + (data.storeAvailable ? '<span class="text-success">Ja</span>' : '<span class="text-danger">Nein</span>') +
                    ' | <strong>Vektoren:</strong> <span class="badge badge-info">' + (data.pointCount || 0).toLocaleString() + '</span>' +
                    ' | <strong>Aktiviert:</strong> ' + (data.enabled ? '<span class="badge badge-success">Ja</span>' : '<span class="badge badge-secondary">Nein</span>');
                $('#vectorStatusInfo').html(html);
            }).fail(function () {
                $('#vectorStatusInfo').text('Status nicht verfuegbar.');
            });
        }
        loadVectorStatus();

        $('#btnDeleteVectors').on('click', function () {
            if (!confirm('Alle Vektoren wirklich loeschen?')) return;
            var $btn = $(this);
            var $result = $('#vectorActionResult');
            $btn.prop('disabled', true);
            $.ajax({
                url: '@Url.Action("DeleteVectorCollection", "HybridSearchAdmin", new { area = "Admin" })',
                type: 'POST',
                success: function (data) {
                    $result.text(data.message).toggleClass('text-success', data.success).toggleClass('text-danger', !data.success);
                    loadVectorStatus();
                },
                complete: function () { $btn.prop('disabled', false); }
            });
        });

        // --- Vektor-Index Rebuild/Update ---
        var vectorProgressTimer = null;
        function startVectorProgressPolling() {
            $('#vectorProgress').text('');
            vectorProgressTimer = setInterval(function () {
                $.get('@Url.Action("VectorEmbeddingProgress", "HybridSearchAdmin", new { area = "Admin" })', function (data) {
                    if (data.isRunning) {
                        $('#vectorProgress').html('<i class="fa fa-spinner fa-spin"></i> ' + data.percent + '% - ' + data.message);
                    } else {
                        $('#vectorProgress').text('');
                        stopVectorProgressPolling();
                    }
                });
            }, 3000);
        }
        function stopVectorProgressPolling() {
            if (vectorProgressTimer) { clearInterval(vectorProgressTimer); vectorProgressTimer = null; }
        }

        function runVectorIndexAction(url, label) {
            var $result = $('#vectorActionResult');
            $('#btnRebuildVectorIndex, #btnUpdateVectorIndex, #btnDeleteVectors').prop('disabled', true);
            $result.text(label).removeClass('text-success text-danger');
            startVectorProgressPolling();

            $.ajax({
                url: url,
                type: 'POST',
                timeout: 0, // no timeout (vector generation can take hours)
                success: function (data) {
                    $result.text(data.message).toggleClass('text-success', data.success).toggleClass('text-danger', !data.success);
                    loadVectorStatus();
                },
                error: function () { $result.text('Request failed.').addClass('text-danger'); },
                complete: function () {
                    $('#btnRebuildVectorIndex, #btnUpdateVectorIndex, #btnDeleteVectors').prop('disabled', false);
                    stopVectorProgressPolling();
                    $('#vectorProgress').text('');
                    loadVectorStatus();
                }
            });
        }

        $('#btnRebuildVectorIndex').on('click', function () {
            if (!confirm('Vektor-Index komplett neu erstellen? Bestehende Vektoren werden geloescht.')) return;
            runVectorIndexAction('@Url.Action("RebuildVectorIndex", "HybridSearchAdmin", new { area = "Admin" })', 'Vektor-Index wird erstellt...');
        });

        $('#btnRunHardwareBenchmark').on('click', function () {
            var $btn = $(this);
            var $result = $('#hardwareBenchmarkResult');
            $btn.prop('disabled', true);
            $result.html('<i class="fa fa-spinner fa-spin"></i> Hardware-Benchmark laeuft (kann 30+ Sekunden dauern)...');

            $.ajax({
                url: '@Url.Action("RunHardwareBenchmark", "HybridSearchAdmin", new { area = "Admin" })',
                type: 'POST',
                timeout: 0,
                data: { __RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val() },
                success: function (data) {
                    if (!data.success) {
                        $result.html('<div class="alert alert-danger">' + (data.message || 'Benchmark fehlgeschlagen') + '</div>');
                        return;
                    }
                    var html = '<div class="alert alert-success">';
                    html += '<i class="fa fa-check-circle"></i> <strong>Auto-Auswahl gespeichert: <code>' + data.selectedProvider + '</code></strong>';
                    html += '<div class="small mt-1">' + data.description + '</div>';
                    html += '</div>';
                    if (data.dmlCandidates && data.dmlCandidates.length > 0) {
                        html += '<table class="table table-sm table-bordered" style="font-size:0.85em;">';
                        html += '<thead><tr><th>Device</th><th>Hardware</th><th>Avg Inferenz</th></tr></thead><tbody>';
                        html += '<tr><td><strong>CPU</strong></td><td>baseline</td><td>' + data.cpuMs + ' ms</td></tr>';
                        data.dmlCandidates.forEach(function (c) {
                            html += '<tr><td>DirectML ' + c.deviceId + '</td><td>' + c.adapterName + '</td><td>' + c.avgMs + ' ms</td></tr>';
                        });
                        html += '</tbody></table>';
                    }
                    html += '<div class="text-muted small">' + (data.hint || '') + ' Seite ggf. neu laden um die aktualisierten Settings zu sehen.</div>';
                    $result.html(html);
                },
                error: function (xhr) { $result.html('<div class="alert alert-danger">Request failed: ' + (xhr.statusText || 'unknown') + '</div>'); },
                complete: function () { $btn.prop('disabled', false); }
            });
        });

        $('#btnListDirectMlDevices').on('click', function () {
            var $btn = $(this);
            var $result = $('#directMlDevicesResult');
            $btn.prop('disabled', true);
            $result.html('<i class="fa fa-spinner fa-spin"></i> Geraete werden gescannt und benchmarkt (kann 30+ Sekunden dauern)...');

            $.ajax({
                url: '@Url.Action("ListDirectMlDevices", "HybridSearchAdmin", new { area = "Admin" })',
                type: 'GET',
                timeout: 0,
                success: function (data) {
                    if (!data.success) {
                        $result.html('<div class="alert alert-danger">' + (data.message || 'Fehler') + '</div>');
                        return;
                    }

                    var html = '<table class="table table-sm table-bordered" style="font-size:0.85em;">';
                    html += '<thead><tr><th>Device</th><th>Hardware</th><th>Typ</th><th>Init</th><th>Avg Inferenz</th><th>Runs</th><th>Bewertung</th></tr></thead><tbody>';
                    data.devices.forEach(function (d, idx) {
                        if (d.success) {
                            var label = d.deviceId === -1 ? (d.label || 'CPU') : ('Device ' + d.deviceId);
                            var hardware = d.deviceId === -1 ? '-' : (d.adapterName || '?') + (d.vendor ? ' (' + d.vendor + ')' : '');
                            var typeBadge = d.deviceId === -1 ? '' :
                                '<span class="badge badge-' + (d.deviceType === 'NPU' ? 'success' : d.deviceType === 'dGPU' ? 'primary' : d.deviceType === 'iGPU' ? 'info' : 'secondary') + '">' + (d.deviceType || '?') + '</span>';
                            var color = d.recommendation && d.recommendation.indexOf('EXCELLENT') >= 0 ? 'success'
                                : d.recommendation && d.recommendation.indexOf('GOOD') >= 0 ? 'info'
                                : d.recommendation && d.recommendation.indexOf('POOR') >= 0 ? 'warning'
                                : 'secondary';
                            html += '<tr class="table-' + color + '">';
                            html += '<td><strong>' + label + '</strong></td>';
                            html += '<td>' + hardware + '</td>';
                            html += '<td>' + typeBadge + '</td>';
                            html += '<td>' + d.initMs + ' ms</td>';
                            html += '<td><strong>' + d.avgInferenceMs + ' ms</strong></td>';
                            html += '<td>[' + (d.runs || []).join(', ') + ']</td>';
                            html += '<td>' + (d.recommendation || '') + '</td>';
                            html += '</tr>';
                        } else {
                            var rowClass = d.notFound ? 'table-light text-muted' : 'table-warning';
                            var icon = d.notFound ? '<i class="fa fa-stop-circle"></i>' : '<i class="fa fa-exclamation-triangle text-danger"></i>';
                            var shortMsg = d.shortError || d.error || '(unknown)';
                            var detailsId = 'errDetails_' + idx;
                            html += '<tr class="' + rowClass + '">';
                            html += '<td>' + icon + ' Device ' + d.deviceId + '</td>';
                            html += '<td colspan="6">';
                            html += '<div>' + shortMsg + '</div>';
                            if (!d.notFound && d.error) {
                                html += '<a href="#" onclick="document.getElementById(\'' + detailsId + '\').style.display=\'block\';return false;" class="small">[Vollstaendigen Fehler anzeigen]</a>';
                                html += '<pre id="' + detailsId + '" style="display:none;font-size:0.7em;background:#f0f0f0;padding:8px;margin-top:4px;white-space:pre-wrap;">' + d.error.replace(/[<>]/g, '') + '\n\nException Type: ' + (d.exceptionType || 'unknown') + '</pre>';
                            }
                            html += '</td>';
                            html += '</tr>';
                        }
                    });
                    html += '</tbody></table>';
                    html += '<div class="text-muted small">Wenn ein DirectML-Device eine Inferenz-Zeit nahe der CPU-Baseline hat, fehlt die echte Hardware-Beschleunigung (Silent CPU Fallback).</div>';

                    // DXCore adapters block (MCDM compute accelerators / NPUs not visible via DXGI)
                    if (data.dxCoreAdapters && data.dxCoreAdapters.length > 0) {
                        html += '<hr/>';
                        html += '<h6 class="mt-3"><i class="fa fa-microchip"></i> DXCore Adapter (inkl. MCDM / NPU)</h6>';
                        html += '<div class="text-muted small mb-2">DXCore listet zusaetzlich Compute-Accelerators (NPUs), die nicht in DXGI auftauchen. Adapter mit Attributen <code>CORE_COMPUTE</code> oder <code>GENERIC_ML</code> ohne <code>GRAPHICS</code> sind typischerweise NPUs.</div>';
                        html += '<table class="table table-sm table-bordered" style="font-size:0.85em;">';
                        html += '<thead><tr><th>Hardware</th><th>Vendor</th><th>Typ</th><th>Speicher</th><th>Attribute</th><th>Flags</th></tr></thead><tbody>';
                        data.dxCoreAdapters.forEach(function (a) {
                            var typeColor = a.deviceType === 'NPU' || a.deviceType === 'NPU/MCDM' ? 'success'
                                : a.deviceType.indexOf('GPU') >= 0 ? 'info' : 'secondary';
                            var rowClass = a.deviceType === 'NPU' || a.deviceType === 'NPU/MCDM' ? 'table-success' : '';
                            html += '<tr class="' + rowClass + '">';
                            html += '<td><strong>' + a.description + '</strong><div class="small text-muted">' + a.vendorId + ' / ' + a.deviceId + '</div></td>';
                            html += '<td>' + a.vendor + '</td>';
                            html += '<td><span class="badge badge-' + typeColor + '">' + a.deviceType + '</span></td>';
                            html += '<td>' + a.memory + '</td>';
                            html += '<td>';
                            (a.attributes || []).forEach(function (att) {
                                html += '<span class="badge badge-secondary mr-1">' + att + '</span>';
                            });
                            html += '</td>';
                            html += '<td class="small">';
                            if (a.isHardware) html += 'Hardware ';
                            if (a.isIntegrated) html += '/ Integrated ';
                            if (a.isDetachable) html += '/ Detachable ';
                            html += '</td>';
                            html += '</tr>';
                        });
                        html += '</tbody></table>';
                        var npuFound = data.dxCoreAdapters.some(function (a) { return a.deviceType === 'NPU' || a.deviceType === 'NPU/MCDM'; });
                        if (npuFound) {
                            html += '<div class="alert alert-success small"><i class="fa fa-check-circle"></i> <strong>NPU via DXCore gefunden.</strong> Der NPU exponiert sich nur ueber das <code>HW_NPU</code>-Attribut und hat keinen D3D user-mode driver. <br/><strong>Wichtig:</strong> AMD Ryzen AI NPU ist <em>nicht</em> direkt via DirectML ansprechbar - dafuer braucht es das AMD Ryzen AI Software SDK mit Vitis AI Execution Provider, ein INT8-quantisiertes Modell, und ein eigenes ONNX Runtime Build. Siehe <a href="https://ryzenai.docs.amd.com/" target="_blank">ryzenai.docs.amd.com</a>.</div>';
                        } else {
                            html += '<div class="alert alert-warning small"><i class="fa fa-exclamation-triangle"></i> Keine NPU/MCDM-Adapter via DXCore gefunden. Pruefe ob der NPU-Treiber korrekt installiert ist.</div>';
                        }
                    } else {
                        html += '<hr/>';
                        html += '<div class="alert alert-secondary small"><i class="fa fa-info-circle"></i> Keine DXCore-Adapter gefunden (dxcore.dll evtl. nicht verfuegbar oder Filter werden nicht unterstuetzt).</div>';
                    }

                    // DXCore diagnostics (always shown, helps debugging when no adapters are found)
                    if (data.dxCoreDiagnostics && data.dxCoreDiagnostics.length > 0) {
                        html += '<details class="mt-2"><summary class="small text-muted">DXCore Diagnose-Log (' + data.dxCoreDiagnostics.length + ' Eintraege)</summary>';
                        html += '<pre style="font-size:0.75em;background:#f5f5f5;padding:8px;margin-top:4px;white-space:pre-wrap;">';
                        data.dxCoreDiagnostics.forEach(function (line) {
                            html += line.replace(/[<>]/g, '') + '\n';
                        });
                        html += '</pre></details>';
                    }

                    $result.html(html);
                },
                error: function () {
                    $result.html('<div class="alert alert-danger">Request failed.</div>');
                },
                complete: function () { $btn.prop('disabled', false); }
            });
        });

        $('#btnUpdateVectorIndex').on('click', function () {
            runVectorIndexAction('@Url.Action("UpdateVectorIndex", "HybridSearchAdmin", new { area = "Admin" })', 'Vektor-Index wird aktualisiert...');
        });

        $('#btnTestEmbedding').on('click', function () {
            var text = prompt('Text fuer Test-Suche (natuerliche Sprache oder Stichworte):', '');
            if (!text) return;

            var $btn = $(this);
            var $result = $('#vectorActionResult');
            $btn.prop('disabled', true);
            $result.text('Generiere Embedding + Suche...').removeClass('text-success text-danger');

            $.ajax({
                url: '@Url.Action("TestEmbedding", "HybridSearchAdmin", new { area = "Admin" })',
                type: 'POST',
                data: { text: text, topN: 10 },
                success: function (data) {
                    if (data.success) {
                        var summary = 'Embedding: ' + data.embeddingMs + 'ms | Suche: ' + data.searchMs + 'ms | Gesamt: ' + data.durationMs + 'ms | Sprache: ' + (data.languageId || '?') + ' | Vektoren: ' + (data.vectorCount || 0);
                        $result.text(summary).addClass('text-success');

                        var html = '';

                        // Hits table
                        if (data.hits && data.hits.length > 0) {
                            html += '<h6 class="mt-3"><i class="fa fa-search"></i> ' + data.hitCount + ' Treffer (Threshold: @Model.CosineSimilarityThreshold)</h6>';
                            html += '<table class="table table-sm table-bordered" style="font-size:0.85em;">';
                            html += '<thead><tr><th style="width:40px">#</th><th>Produkt</th><th style="width:80px">Score</th><th style="width:80px">Preis</th><th style="width:60px">ID</th></tr></thead><tbody>';
                            data.hits.forEach(function (h, idx) {
                                if (h.error) {
                                    html += '<tr class="table-danger"><td colspan="5">' + h.error + '</td></tr>';
                                } else {
                                    var scoreColor = h.score >= 0.7 ? 'success' : h.score >= 0.5 ? 'info' : h.score >= 0.3 ? 'warning' : 'secondary';
                                    html += '<tr>';
                                    html += '<td>' + (idx + 1) + '</td>';
                                    html += '<td><strong>' + (h.name || '?') + '</strong></td>';
                                    html += '<td><span class="badge badge-' + scoreColor + '">' + h.score + '</span></td>';
                                    html += '<td>' + (h.price > 0 ? h.price.toFixed(2) : '-') + '</td>';
                                    html += '<td><a href="/admin/product/edit/' + h.productId + '" target="_blank">' + h.productId + '</a></td>';
                                    html += '</tr>';
                                }
                            });
                            html += '</tbody></table>';
                        } else if (data.vectorCount > 0) {
                            html += '<div class="alert alert-warning small mt-2"><i class="fa fa-exclamation-triangle"></i> Keine Treffer ueber dem Threshold (@Model.CosineSimilarityThreshold). Versuche einen anderen Suchbegriff oder senke den Threshold.</div>';
                        } else {
                            html += '<div class="alert alert-info small mt-2"><i class="fa fa-info-circle"></i> Vektor-Index ist leer. Bitte zuerst den Vektor-Index aufbauen.</div>';
                        }

                        // Technical details (collapsible)
                        html += '<details class="mt-2"><summary class="small text-muted">Technische Details</summary>';
                        html += '<pre style="font-size:0.75em;background:#f5f5f5;padding:8px;margin-top:4px;white-space:pre-wrap;">' + JSON.stringify(data, null, 2) + '</pre>';
                        html += '</details>';

                        $('#vectorTestResult').show();
                        $('#vectorTestOutput').html(html);
                    } else {
                        $result.text(data.message).addClass('text-danger');
                        $('#vectorTestResult').hide();
                    }
                },
                error: function () { $result.text('Request failed.').addClass('text-danger'); },
                complete: function () { $btn.prop('disabled', false); }
            });
        });
    });
</script>
