// /public/assets/js/fakecheck/fakecheck.browser.js

(function () {
    // Core / Namespace muss geladen sein
    if (!window.usbcheck) return;

    const {
        cfg,
        log: logLine,
        setStatus,
        setModeLabel,
        setProgress,
        setOverallStatus,
        formatBytes,
        formatMbps,
        formatDuration,
        t,
        tFmt
    } = window.usbcheck;

    const root = document.getElementById("fc-root");
    if (!root) {
        // Seite ohne Fakecheck-Tool → nichts tun
        return;
    }

    // --- DOM-Helper ---------------------------------------------------------
    const $  = (sel) => document.querySelector(sel);
    const $$ = (sel) => Array.from(document.querySelectorAll(sel));

    const fsapiWarning     = $("#fc-fsapi-warning");
    const selectedPathText = $("#fc-selected-path-label");
    const saveHint         = $("#fc-save-hint");
    const saveError        = $("#fc-save-error");

    const resMode        = $("#fc-res-mode");
    const resDuration    = $("#fc-res-duration");
    const resWriteSpeed  = $("#fc-res-write-speed");
    const resReadSpeed   = $("#fc-res-read-speed");
    const resWritten     = $("#fc-res-written-bytes");
    const resVerified    = $("#fc-res-verified-bytes");

    const btnPickDir  = $("#fc-btn-pick-directory");
    const btnClearSel = $("#fc-btn-clear-selection");
    const btnStart    = $("#fc-btn-start-tests");
    const btnCancel   = $("#fc-btn-cancel-tests");
    const modeTiles   = $$("#fc-mode-grid .fc-mode-tile");

    // Login-Indikator
    if (cfg.loggedIn && saveHint) {
        saveHint.style.display = "block";
    }

    // --- Test-Engine (Browser) ---------------------------------------------

    class UsbBrowserTester {
        constructor() {
            this.rootHandle        = null;
            this.abortController   = null;
            this.capacityBytes     = null;
            this.capacityProbeFile = "usbcheck_capacity_probe.bin";
        }

        hasFsApiSupport() {
            return "showDirectoryPicker" in window;
        }

        async pickDirectory() {
            if (!this.hasFsApiSupport()) {
                throw new Error(t("fake_ui.error_fsapi_not_supported", "File System Access API wird von diesem Browser nicht unterstützt."));
            }
            const handle = await window.showDirectoryPicker();
            this.rootHandle = handle;
            return handle;
        }

        async clearSelection() {
            this.rootHandle = null;
            this.capacityBytes = null;
        }

        // Freispeicher-Ermittlung
        async ensureCapacity(abortSignal) {
            if (this.capacityBytes != null) return this.capacityBytes;
            if (!this.rootHandle) {
                throw new Error(t("fake_ui.error_no_directory_selected", "Kein Verzeichnis ausgewählt."));
            }

            const dirHandle = this.rootHandle;
            const PROBE_FILENAME = this.capacityProbeFile;
            const CHUNK_SIZE = 1024 * 1024; // 1 MiB
            const MAX_BYTES  = 128 * 1024 * 1024; // max. 128 MiB testen

            logLine(t("fake_ui.log_capacity_probe_start", "Ermittle verfügbaren Speicherplatz im gewählten Verzeichnis..."), "info");

            let bytesWritten = 0;
            let writable = null;

            try {
                const fileHandle = await dirHandle.getFileHandle(PROBE_FILENAME, { create: true });
                writable = await fileHandle.createWritable();

                const chunk = new Uint8Array(CHUNK_SIZE);
                chunk.fill(0x5a);

                while (bytesWritten + CHUNK_SIZE <= MAX_BYTES) {
                    if (abortSignal && abortSignal.aborted) {
                        await writable.abort();
                        throw new DOMException("Abgebrochen", "AbortError");
                    }

                    await writable.write(chunk);
                    bytesWritten += CHUNK_SIZE;
                }

                await writable.close();
            } catch (err) {
                if (writable) {
                    try { await writable.close(); } catch (e) {}
                }
                if (err && err.name === "AbortError") {
                    throw err;
                }
                // sonst: „Out of space“ → okay, wir nehmen bytesWritten als Limit
            } finally {
                try {
                    await dirHandle.removeEntry(PROBE_FILENAME);
                } catch (e) {
                    // egal
                }
            }

            if (!bytesWritten) {
                throw new Error(t("fake_ui.error_no_space_detected", "Es konnte kein freier Speicher im gewählten Verzeichnis reserviert werden."));
            }

            this.capacityBytes = bytesWritten;
            logLine(
                tFmt(
                    "fake_ui.log_capacity_probe_result",
                    "Ermittelter für Tests nutzbarer Speicher: {size} (Schreibprobe).",
                    { size: formatBytes(bytesWritten) }
                ),
                "info"
            );

            return this.capacityBytes;
        }

        planSizeBytes({ defaultMB, minMB, maxFraction }) {
            const MiB = 1024 * 1024;
            const cap = this.capacityBytes || (64 * MiB);

            const minBytes      = (minMB || 1) * MiB;
            const defaultBytes  = (defaultMB || 8) * MiB;
            const maxBytesByCap = Math.max(minBytes, cap * (maxFraction || 0.25));

            let target = Math.min(defaultBytes, maxBytesByCap);

            const CHUNK_SIZE = MiB;
            target = Math.floor(target / CHUNK_SIZE) * CHUNK_SIZE;
            if (target < CHUNK_SIZE) target = CHUNK_SIZE;

            return target;
        }

        // Quick-Check
        async runQuickCheck(report, progressCb, abortSignal) {
            const TEST_FILENAME = "usbcheck_quick_test.bin";
            const CHUNK_SIZE    = 1024 * 1024;

            const dirHandle = this.rootHandle;
            if (!dirHandle) throw new Error(t("fake_ui.error_no_directory_selected", "Kein Verzeichnis ausgewählt."));

            const totalBytes = this.planSizeBytes({
                defaultMB: 8,
                minMB: 1,
                maxFraction: 0.25
            });

            logLine(
                tFmt(
                    "fake_ui.log_quick_prepare",
                    "Quick-Check: Vorbereitung... (Testgröße: {size})",
                    { size: formatBytes(totalBytes) }
                ),
                "info"
            );

            const fileHandle = await dirHandle.getFileHandle(TEST_FILENAME, { create: true });
            const writable   = await fileHandle.createWritable();

            let writtenBytes = 0;

            const writeStart = performance.now();
            while (writtenBytes < totalBytes) {
                if (abortSignal.aborted) {
                    await writable.abort();
                    throw new DOMException("Abgebrochen", "AbortError");
                }
                const remaining = totalBytes - writtenBytes;
                const chunkLen  = Math.min(CHUNK_SIZE, remaining);
                const chunk     = new Uint8Array(chunkLen);
                for (let i = 0; i < chunkLen; i++) {
                    chunk[i] = (i + writtenBytes) % 251;
                }
                await writable.write(chunk);
                writtenBytes += chunkLen;
                progressCb((writtenBytes / totalBytes) * 100 * 0.5);
            }
            await writable.close();
            const writeEnd = performance.now();

            logLine(t("fake_ui.log_quick_verify_start", "Quick-Check: Schreiben abgeschlossen. Verifiziere Daten..."), "info");

            const file = await fileHandle.getFile();
            const readStart = performance.now();

            const reader = file.stream().getReader();
            let offset = 0;
            let verifiedBytes = 0;
            while (true) {
                if (abortSignal.aborted) {
                    reader.cancel();
                    throw new DOMException("Abgebrochen", "AbortError");
                }
                const { done, value } = await reader.read();
                if (done) break;
                const chunk = value;
                for (let i = 0; i < chunk.length; i++) {
                    const expected = (offset + i) % 251;
                    if (chunk[i] !== expected) {
                        logLine(
                            tFmt(
                                "fake_ui.log_quick_data_error",
                                "Quick-Check: Datenfehler bei Byte {byte}",
                                { byte: (offset + i).toString() }
                            ),
                            "error"
                        );
                        throw new Error(
                            tFmt(
                                "fake_ui.error_quick_data_error",
                                "Datenfehler im Quick-Check bei Byte {byte}",
                                { byte: (offset + i).toString() }
                            )
                        );
                    }
                }
                offset += chunk.length;
                verifiedBytes += chunk.length;
                progressCb(50 + (verifiedBytes / totalBytes) * 100 * 0.5);
            }

            const readEnd = performance.now();

            const writeSeconds = (writeEnd - writeStart) / 1000;
            const readSeconds  = (readEnd - readStart) / 1000;

            report.quick = {
                mode: "quick",
                test_file: TEST_FILENAME,
                size_bytes: totalBytes,
                write_bytes: writtenBytes,
                read_bytes: verifiedBytes,
                write_duration_s: writeSeconds,
                read_duration_s: readSeconds,
                write_mbit_s: writeSeconds ? (writtenBytes * 8 / (writeSeconds * 1e6)) : null,
                read_mbit_s:  readSeconds  ? (verifiedBytes * 8 / (readSeconds * 1e6)) : null,
                ok: true
            };

            try {
                await dirHandle.removeEntry(TEST_FILENAME);
            } catch (e) {
                logLine(t("fake_ui.log_quick_delete_warn", "Quick-Check: Konnte Testdatei nicht löschen (nicht kritisch)."), "warn");
            }

            logLine(t("fake_ui.log_quick_success", "Quick-Check: Erfolgreich abgeschlossen."), "info");
        }

        // Benchmark
        async runBenchmark(report, progressCb, abortSignal) {
            const TEST_FILENAME = "usbcheck_benchmark.bin";
            const CHUNK_SIZE    = 1024 * 1024;

            const dirHandle = this.rootHandle;
            if (!dirHandle) throw new Error(t("fake_ui.error_no_directory_selected", "Kein Verzeichnis ausgewählt."));

            const totalBytes = this.planSizeBytes({
                defaultMB: 32,
                minMB: 4,
                maxFraction: 0.5
            });

            logLine(
                tFmt(
                    "fake_ui.log_bench_start",
                    "Benchmark: Start – schreibe Testdatei ({size})...",
                    { size: formatBytes(totalBytes) }
                ),
                "info"
            );

            const fileHandle = await dirHandle.getFileHandle(TEST_FILENAME, { create: true });
            const writable   = await fileHandle.createWritable();

            let writtenBytes = 0;

            const writeStart = performance.now();
            while (writtenBytes < totalBytes) {
                if (abortSignal.aborted) {
                    await writable.abort();
                    throw new DOMException("Abgebrochen", "AbortError");
                }
                const remaining = totalBytes - writtenBytes;
                const chunkLen  = Math.min(CHUNK_SIZE, remaining);
                const chunk     = new Uint8Array(chunkLen);
                for (let i = 0; i < chunkLen; i++) {
                    chunk[i] = 0xaa;
                }
                await writable.write(chunk);
                writtenBytes += chunkLen;
                progressCb((writtenBytes / totalBytes) * 100 * 0.4);
            }
            await writable.close();
            const writeEnd = performance.now();

            logLine(t("fake_ui.log_bench_read_start", "Benchmark: Lesen & Timing..."), "info");

            const file = await fileHandle.getFile();
            const readStart = performance.now();
            const reader = file.stream().getReader();
            let readBytes = 0;
            while (true) {
                if (abortSignal.aborted) {
                    reader.cancel();
                    throw new DOMException("Abgebrochen", "AbortError");
                }
                const { done, value } = await reader.read();
                if (done) break;
                readBytes += value.length;
                progressCb(40 + (readBytes / totalBytes) * 100 * 0.6);
            }
            const readEnd = performance.now();

            const writeSeconds = (writeEnd - writeStart) / 1000;
            const readSeconds  = (readEnd - readStart) / 1000;

            report.benchmark = {
                mode: "benchmark",
                test_file: TEST_FILENAME,
                size_bytes: totalBytes,
                write_bytes: writtenBytes,
                read_bytes: readBytes,
                write_duration_s: writeSeconds,
                read_duration_s: readSeconds,
                write_mbit_s: writeSeconds ? (writtenBytes * 8 / (writeSeconds * 1e6)) : null,
                read_mbit_s:  readSeconds  ? (readBytes  * 8 / (readSeconds  * 1e6)) : null,
                ok: true
            };

            try {
                await dirHandle.removeEntry(TEST_FILENAME);
            } catch (e) {
                logLine(t("fake_ui.log_bench_delete_warn", "Benchmark: Konnte Testdatei nicht löschen (nicht kritisch)."), "warn");
            }

            logLine(t("fake_ui.log_bench_success", "Benchmark: Erfolgreich abgeschlossen."), "info");
        }

        // Write/Verify
        async runWriteVerify(report, progressCb, abortSignal) {
            const BASE_FILENAME = "usbcheck_block_";
            const BLOCKS        = 4;
            const CHUNK_SIZE    = 1024 * 1024;

            const dirHandle = this.rootHandle;
            if (!dirHandle) throw new Error(t("fake_ui.error_no_directory_selected", "Kein Verzeichnis ausgewählt."));

            const totalBytesPlanned = this.planSizeBytes({
                defaultMB: 128,
                minMB: 8,
                maxFraction: 0.75
            });

            const blockBytes = Math.max(
                CHUNK_SIZE,
                Math.floor(totalBytesPlanned / BLOCKS / CHUNK_SIZE) * CHUNK_SIZE
            );

            const totalBytes = blockBytes * BLOCKS;

            logLine(
                tFmt(
                    "fake_ui.log_wv_start",
                    "Write/Verify: Start – {blocks} Blöcke à {size} (gesamt {total})...",
                    {
                        blocks: BLOCKS.toString(),
                        size:   formatBytes(blockBytes),
                        total:  formatBytes(totalBytes)
                    }
                ),
                "info"
            );

            let writtenBytes  = 0;
            let verifiedBytes = 0;

            const globalStart = performance.now();
            const writeDetails = [];
            const readDetails  = [];

            for (let b = 0; b < BLOCKS; b++) {
                const filename = `${BASE_FILENAME}${String(b + 1).padStart(2, "0")}.bin`;
                logLine(
                    tFmt(
                        "fake_ui.log_wv_block_start",
                        "Write/Verify: Block {num}/{blocks} – {file}",
                        {
                            num: (b + 1).toString(),
                            blocks: BLOCKS.toString(),
                            file: filename
                        }
                    ),
                    "info"
                );

                const fileHandle = await dirHandle.getFileHandle(filename, { create: true });
                const writable   = await fileHandle.createWritable();

                const blockBytesTotal = blockBytes;
                let blockWritten = 0;
                const blockWriteStart = performance.now();

                while (blockWritten < blockBytesTotal) {
                    if (abortSignal.aborted) {
                        await writable.abort();
                        throw new DOMException("Abgebrochen", "AbortError");
                    }
                    const remaining = blockBytesTotal - blockWritten;
                    const chunkLen  = Math.min(CHUNK_SIZE, remaining);
                    const chunk     = new Uint8Array(chunkLen);
                    for (let i = 0; i < chunkLen; i++) {
                        chunk[i] = (i + blockWritten + b * 13) % 251;
                    }
                    await writable.write(chunk);
                    blockWritten  += chunkLen;
                    writtenBytes  += chunkLen;
                    const progress = (writtenBytes + verifiedBytes) / (totalBytes * 2) * 100;
                    progressCb(progress);
                }
                await writable.close();
                const blockWriteEnd = performance.now();
                writeDetails.push({
                    block: b + 1,
                    bytes: blockBytesTotal,
                    duration_s: (blockWriteEnd - blockWriteStart) / 1000
                });

                const file = await fileHandle.getFile();
                const reader = file.stream().getReader();
                let blockOffset = 0;
                const blockReadStart = performance.now();

                while (true) {
                    if (abortSignal.aborted) {
                        reader.cancel();
                        throw new DOMException("Abgebrochen", "AbortError");
                    }
                    const { done, value } = await reader.read();
                    if (done) break;
                    const chunk = value;
                    for (let i = 0; i < chunk.length; i++) {
                        const expected = (i + blockOffset + b * 13) % 251;
                        if (chunk[i] !== expected) {
                            logLine(
                                tFmt(
                                    "fake_ui.log_wv_data_error",
                                    "Write/Verify: Datenfehler in Block {num} bei Byte {byte}",
                                    {
                                        num: (b + 1).toString(),
                                        byte: (blockOffset + i).toString()
                                    }
                                ),
                                "error"
                            );
                            throw new Error(
                                tFmt(
                                    "fake_ui.error_wv_data_error",
                                    "Datenfehler in Block {num} bei Byte {byte}",
                                    {
                                        num: (b + 1).toString(),
                                        byte: (blockOffset + i).toString()
                                    }
                                )
                            );
                        }
                    }
                    blockOffset   += chunk.length;
                    verifiedBytes += chunk.length;
                    const progress = (writtenBytes + verifiedBytes) / (totalBytes * 2) * 100;
                    progressCb(progress);
                }
                const blockReadEnd = performance.now();
                readDetails.push({
                    block: b + 1,
                    bytes: blockBytesTotal,
                    duration_s: (blockReadEnd - blockReadStart) / 1000
                });

                try {
                    await dirHandle.removeEntry(filename);
                } catch (e) {
                    logLine(
                        tFmt(
                            "fake_ui.log_wv_delete_warn",
                            "Write/Verify: Konnte Blockdatei {file} nicht löschen (nicht kritisch).",
                            { file: filename }
                        ),
                        "warn"
                    );
                }
            }

            const globalEnd = performance.now();
            const totalDuration = (globalEnd - globalStart) / 1000;

            const sumWrite = writeDetails.reduce((acc, d) => acc + d.bytes, 0);
            const sumRead  = readDetails.reduce((acc, d) => acc + d.bytes, 0);
            const writeSec = writeDetails.reduce((acc, d) => acc + d.duration_s, 0);
            const readSec  = readDetails.reduce((acc, d) => acc + d.duration_s, 0);

            report.writeverify = {
                mode: "writeverify",
                blocks: BLOCKS,
                block_size_bytes: blockBytes,
                total_bytes: totalBytes,
                written_bytes: writtenBytes,
                verified_bytes: verifiedBytes,
                write_duration_s: writeSec,
                read_duration_s: readSec,
                write_mbit_s: writeSec ? (sumWrite * 8 / (writeSec * 1e6)) : null,
                read_mbit_s:  readSec  ? (sumRead  * 8 / (readSec  * 1e6)) : null,
                ok: true
            };

            report.writeverify_total_duration_s = totalDuration;

            logLine(t("fake_ui.log_wv_success", "Write/Verify: Alle Blöcke erfolgreich verifiziert."), "info");
        }

        async run(mode, updateProgressCb, abortSignal) {
            if (!this.rootHandle) {
                throw new Error(t("fake_ui.error_no_directory_selected", "Kein Verzeichnis ausgewählt."));
            }

            await this.ensureCapacity(abortSignal);

            const report = {
                meta: {
                    base_url: cfg.baseUrl || "",
                    locale:   cfg.locale || "en",
                    user_agent: navigator.userAgent,
                    started_at: new Date().toISOString()
                },
                tool: "usbcheck_browser",
                tool_version: "0.1.0",
                mode_requested: mode,
                quick: null,
                benchmark: null,
                writeverify: null,
                total_duration_s: null
            };

            const t0 = performance.now();

            if (mode === "quick") {
                await this.runQuickCheck(report, updateProgressCb, abortSignal);
            } else if (mode === "benchmark") {
                await this.runBenchmark(report, updateProgressCb, abortSignal);
            } else if (mode === "writeverify") {
                await this.runWriteVerify(report, updateProgressCb, abortSignal);
            } else if (mode === "all") {
                const modes = ["quick", "benchmark", "writeverify"];
                for (let i = 0; i < modes.length; i++) {
                    const subMode = modes[i];
                    logLine(
                        tFmt(
                            "fake_ui.log_all_subtest_start",
                            "All-Inclusive: Starte Teiltest \"{mode}\" ({num}/{total})...",
                            {
                                mode: subMode,
                                num: (i + 1).toString(),
                                total: modes.length.toString()
                            }
                        ),
                        "info"
                    );

                    const base  = (i / modes.length) * 100;
                    const span  = (1 / modes.length) * 100;
                    const mapProgress = (p) => {
                        const mapped = base + (p / 100) * span;
                        updateProgressCb(mapped);
                    };

                    if (subMode === "quick") {
                        await this.runQuickCheck(report, mapProgress, abortSignal);
                    } else if (subMode === "benchmark") {
                        await this.runBenchmark(report, mapProgress, abortSignal);
                    } else if (subMode === "writeverify") {
                        await this.runWriteVerify(report, mapProgress, abortSignal);
                    }
                }
            } else {
                throw new Error(tFmt("fake_ui.error_unknown_mode", "Unbekannter Modus: {mode}", { mode }));
            }

            const t1 = performance.now();
            report.total_duration_s = (t1 - t0) / 1000;
            report.meta.ended_at = new Date().toISOString();

            return report;
        }
    }

    const tester = new UsbBrowserTester();
    let currentMode = null;
    let isRunning   = false;

    if (!tester.hasFsApiSupport()) {
        if (fsapiWarning) fsapiWarning.style.display = "block";
        logLine(
            t("fake_ui.log_fsapi_partial", "Dein Browser unterstützt die File System Access API nicht voll. Einige Funktionen sind deaktiviert."),
            "warn"
        );
    }

    function updateStartButtonState() {
        const hasDir  = !!tester.rootHandle;
        const hasMode = !!currentMode;
        if (btnStart)  btnStart.disabled  = !(hasDir && hasMode && !isRunning);
        if (btnCancel) btnCancel.disabled = !isRunning;
    }

    // --- Event-Handler ------------------------------------------------------

    let isPickingDir = false;

    if (btnPickDir) {
        btnPickDir.addEventListener("click", () => {
            if (isPickingDir) return;
            isPickingDir = true;

            if (!("showDirectoryPicker" in window)) {
                logLine(t("fake_ui.error_fsapi_not_supported", "File System Access API wird von diesem Browser nicht unterstützt."), "error");
                if (fsapiWarning) fsapiWarning.style.display = "block";
                isPickingDir = false;
                return;
            }

            window.showDirectoryPicker()
                .then((handle) => {
                    tester.rootHandle    = handle;
                    tester.capacityBytes = null;

                    if (selectedPathText) {
                        selectedPathText.textContent = tFmt(
                            "fake_ui.selected_path_label",
                            'USB-Ordner ausgewählt (Name: "{name}").',
                            { name: (handle.name || "Unbekannt") }
                        );
                    }
                    if (btnClearSel) btnClearSel.disabled = false;
                    setStatus(t("fake_ui.status_dir_selected", "USB-Verzeichnis ausgewählt. Wähle jetzt einen Testmodus."));
                    logLine(
                        tFmt(
                            "fake_ui.log_dir_selected",
                            "Verzeichnis ausgewählt: {name}",
                            { name: (handle.name || "[ohne Namen]") }
                        ),
                        "info"
                    );
                    updateStartButtonState();
                })
                .catch((err) => {
                    if (err && err.name === "AbortError") {
                        logLine(t("fake_ui.log_pick_abort", "Verzeichnisauswahl abgebrochen."), "warn");
                    } else if (err) {
                        logLine(
                            tFmt(
                                "fake_ui.log_pick_error",
                                "Fehler bei Verzeichnisauswahl: {msg}",
                                { msg: err.message || "unbekannt" }
                            ),
                            "error"
                        );
                    } else {
                        logLine(t("fake_ui.log_pick_error_unknown", "Unbekannter Fehler bei Verzeichnisauswahl."), "error");
                    }
                })
                .finally(() => {
                    isPickingDir = false;
                });
        });
    }

    if (btnClearSel) {
        btnClearSel.addEventListener("click", async () => {
            await tester.clearSelection();
            if (selectedPathText) {
                selectedPathText.textContent = t("fake_ui.selected_path_none", "Noch kein Verzeichnis gewählt.");
            }
            btnClearSel.disabled = true;
            setStatus(t("fake_ui.status_ready", "Bereit. Wähle zuerst deinen USB-Stick aus."));
            logLine(t("fake_ui.log_dir_reset", "Verzeichnisauswahl zurückgesetzt."), "info");
            updateStartButtonState();
        });
    }

    modeTiles.forEach((tile) => {
        tile.addEventListener("click", () => {
            if (tile.classList.contains("disabled")) return;
            if (isRunning) return;
            modeTiles.forEach((tEl) => tEl.classList.remove("selected"));
            tile.classList.add("selected");
            currentMode = tile.getAttribute("data-mode");
            const titleEl = tile.querySelector("h4");
            const label = titleEl ? titleEl.textContent : currentMode;
            setModeLabel(label || "");
            setStatus(
                tFmt(
                    "fake_ui.status_mode_selected",
                    'Modus "{mode}" ausgewählt. Du kannst den Test jetzt starten.',
                    { mode: label || currentMode || "" }
                )
            );
            logLine(
                tFmt(
                    "fake_ui.log_mode_selected",
                    "Modus gewählt: {mode}",
                    { mode: currentMode || "" }
                ),
                "info"
            );
            updateStartButtonState();
        });
    });

    if (btnStart) {
        btnStart.addEventListener("click", async () => {
            if (!currentMode || !tester.rootHandle || isRunning) return;
            isRunning = true;
            updateStartButtonState();
            if (btnCancel) btnCancel.disabled = false;
            if (saveError) saveError.style.display = "none";
            setProgress(0);
            logLine(
                tFmt(
                    "fake_ui.log_test_start",
                    "Starte Tests im Modus: {mode}",
                    { mode: (currentMode || "").toUpperCase() }
                ),
                "info"
            );
            setStatus(t("fake_ui.status_running", "Test läuft... bitte USB-Stick nicht entfernen."));
            setOverallStatus("warn", t("fake_ui.overall_running", "Test läuft..."));

            const abortController = new AbortController();
            tester.abortController = abortController;

            const updateProgressCb = (percent) => setProgress(percent);
            let report = null;

            try {
                report = await tester.run(currentMode, updateProgressCb, abortController.signal);

                setProgress(100);
                setStatus(t("fake_ui.status_done", "Test abgeschlossen."));
                setOverallStatus("ok", t("fake_ui.overall_done", "Browser-Test erfolgreich abgeschlossen."));
                applyReportToDashboard(report);

                console.log("USB Browser Test Report (fakecheck):", report);

                await saveReportToBackend(report);
            } catch (err) {
                if (err && err.name === "AbortError") {
                    setStatus(t("fake_ui.status_aborted", "Test wurde abgebrochen."));
                    setOverallStatus("warn", t("fake_ui.overall_aborted", "Test abgebrochen."));
                    logLine(t("fake_ui.log_test_aborted", "Test wurde vom Benutzer abgebrochen."), "warn");
                } else if (err) {
                    setStatus(
                        tFmt(
                            "fake_ui.status_error",
                            "Fehler: {msg}",
                            { msg: err.message || "unbekannt" }
                        )
                    );
                    setOverallStatus("bad", t("fake_ui.overall_error", "Fehler im Browser-Test."));
                    logLine(
                        tFmt(
                            "fake_ui.log_test_error",
                            "Fehler im Test: {msg}",
                            { msg: err.message || "unbekannt" }
                        ),
                        "error"
                    );
                } else {
                    setStatus(t("fake_ui.status_error_unknown", "Unbekannter Fehler im Test."));
                    setOverallStatus("bad", t("fake_ui.overall_error", "Fehler im Browser-Test."));
                    logLine(t("fake_ui.log_test_error_unknown", "Unbekannter Fehler im Test."), "error");
                }
            } finally {
                isRunning = false;
                tester.abortController = null;
                updateStartButtonState();
                if (btnCancel) btnCancel.disabled = true;
            }
        });
    }

    if (btnCancel) {
        btnCancel.addEventListener("click", () => {
            if (!isRunning || !tester.abortController) return;
            tester.abortController.abort();
        });
    }

    // --- Dashboard-Füllung --------------------------------------------------

    function applyReportToDashboard(report) {
        const modeLabelMap = {
            quick: t("fake_ui.mode_quick", "Quick-Check"),
            benchmark: t("fake_ui.mode_benchmark", "Benchmark"),
            writeverify: t("fake_ui.mode_writeverify", "Write & Verify"),
            all: t("fake_ui.mode_all", "All-Inclusive (alle Browser-Tests)")
        };

        if (resMode) {
            resMode.textContent = modeLabelMap[report.mode_requested] || report.mode_requested || "–";
        }
        if (resDuration) {
            resDuration.textContent = formatDuration(report.total_duration_s);
        }

        let aggWriteBytes = 0;
        let aggReadBytes  = 0;
        let writeSec = 0;
        let readSec  = 0;

        if (report.quick) {
            aggWriteBytes += report.quick.write_bytes || 0;
            aggReadBytes  += report.quick.read_bytes  || 0;
            writeSec      += report.quick.write_duration_s || 0;
            readSec       += report.quick.read_duration_s  || 0;
        }
        if (report.benchmark) {
            aggWriteBytes += report.benchmark.write_bytes || 0;
            aggReadBytes  += report.benchmark.read_bytes  || 0;
            writeSec      += report.benchmark.write_duration_s || 0;
            readSec       += report.benchmark.read_duration_s  || 0;
        }
        if (report.writeverify) {
            aggWriteBytes += report.writeverify.written_bytes || 0;
            aggReadBytes  += report.writeverify.verified_bytes || 0;
            writeSec      += report.writeverify.write_duration_s || 0;
            readSec       += report.writeverify.read_duration_s  || 0;
        }

        if (resWritten) {
            resWritten.textContent = aggWriteBytes ? formatBytes(aggWriteBytes) : "–";
        }
        if (resVerified) {
            resVerified.textContent = aggReadBytes ? formatBytes(aggReadBytes) : "–";
        }

        const avgWriteMbps = (aggWriteBytes && writeSec) ? formatMbps(aggWriteBytes, writeSec) : "–";
        const avgReadMbps  = (aggReadBytes  && readSec)  ? formatMbps(aggReadBytes,  readSec)  : "–";

        if (resWriteSpeed) resWriteSpeed.textContent = avgWriteMbps;
        if (resReadSpeed)  resReadSpeed.textContent  = avgReadMbps;
    }

    // --- Backend-Speicherung ------------------------------------------------

    async function saveReportToBackend(report) {
        const url = "/api/result/browser-quick-test.php";
        try {
            const response = await fetch(url, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify(report),
                credentials: "include"
            });

            if (!response.ok) {
                const msg = "HTTP " + response.status;
                logLine(
                    tFmt(
                        "fake_ui.log_backend_save_error_status",
                        "Backend: Konnte Ergebnis nicht speichern ({status}).",
                        { status: msg }
                    ),
                    "warn"
                );
                if (response.status >= 500 && saveError) {
                    saveError.style.display = "block";
                }
                return;
            }

            const data = await response.json().catch(() => null);
            logLine(
                tFmt(
                    "fake_ui.log_backend_save_ok",
                    "Backend: Testergebnis gespeichert{suffix}",
                    { suffix: (data && data.id ? ` (ID: ${data.id})` : "") }
                ),
                "info"
            );
        } catch (err) {
            if (saveError) saveError.style.display = "block";
            logLine(
                tFmt(
                    "fake_ui.log_backend_save_error",
                    "Fehler beim Speichern im Backend: {msg}",
                    { msg: err ? err.message || "unbekannt" : "unbekannt" }
                ),
                "error"
            );
        }
    }

    // --- Initialzustand -----------------------------------------------------

    setStatus(t("fake_ui.status_ready", "Bereit. Wähle zuerst deinen USB-Stick aus."));
    setModeLabel(t("fake_ui.status_mode_none", "Kein Modus selektiert"));
    setOverallStatus("ok", t("fake_ui.overall_initial", "Noch kein Test durchgeführt."));
    logLine(
        t("fake_ui.log_loaded", "USB-Browser-Test (fakecheck) geladen. Warte auf Verzeichnisauswahl und Modus."),
        "info"
    );
    updateStartButtonState();
})();
