// Login overlay + Account panel (logout / change password).
//
// Cookie is set server-side as HttpOnly so JS never sees it -- that defeats
// XSS-based exfiltration. We only briefly hold the password during input.
"use strict";

// We deliberately don't import apiJson here -- change-password returns its
// own error messages and we want to surface them verbatim to the user.

let overlayShown = false;
async function showOverlay(stateOverride) {
    if (overlayShown) return;
    overlayShown = true;
    let state = stateOverride;
    if (!state) {
        try {
            const res = await fetch("/api/auth/state");
            if (res.ok) state = await res.json();
        } catch { /* network blip -- fall through to login */ }
    }
    state = state || { needsSetup: false };
    if (state.needsSetup) {
        const overlay = document.getElementById("setupOverlay");
        if (overlay) {
            overlay.hidden = false;
            document.getElementById("setupPassword")?.focus();
        }
    } else {
        const overlay = document.getElementById("loginOverlay");
        if (overlay) {
            overlay.hidden = false;
            document.getElementById("loginPassword")?.focus();
        }
    }
}

export function setupAuth() {
    document.addEventListener("authrequired", () => showOverlay());
    setupLoginForm();
    setupAccountPanel();
    setupSetupForm();
    // Eager state probe so the right overlay appears before any API call fails.
    fetch("/api/auth/state")
        .then(r => r.ok ? r.json() : null)
        .then(state => { if (state && !state.authed) showOverlay(state); })
        .catch(() => { /* let authrequired handle it */ });
}

function setupLoginForm() {
    const overlay = document.getElementById("loginOverlay");
    const input   = document.getElementById("loginPassword");
    const button  = document.getElementById("loginSubmit");
    const errorEl = document.getElementById("loginError");
    if (!overlay || !input || !button || !errorEl) return;

    async function tryLogin() {
        const pw = input.value;
        if (!pw) return;
        errorEl.textContent = "";
        button.disabled = true;
        try {
            const res = await fetch("/api/auth/login", {
                method:  "POST",
                headers: { "Content-Type": "application/json" },
                body:    JSON.stringify({ password: pw }),
            });
            if (res.status === 401) { errorEl.textContent = "Wrong password."; input.select(); return; }
            if (res.status === 429) { errorEl.textContent = "Too many attempts. Wait a minute."; return; }
            if (!res.ok)            { errorEl.textContent = `Error ${res.status}`; return; }
            // Server set the cookie. Reload so SSE / pollers pick it up.
            location.reload();
        } catch (e) {
            errorEl.textContent = e.message;
        } finally {
            button.disabled = false;
            input.value = "";
        }
    }

    button.addEventListener("click", tryLogin);
    input.addEventListener("keydown", e => { if (e.key === "Enter") tryLogin(); });
}

function setupSetupForm() {
    const overlay = document.getElementById("setupOverlay");
    const pw1     = document.getElementById("setupPassword");
    const pw2     = document.getElementById("setupConfirm");
    const button  = document.getElementById("setupSubmit");
    const errorEl = document.getElementById("setupError");
    if (!overlay || !pw1 || !pw2 || !button || !errorEl) return;

    async function trySetup() {
        errorEl.textContent = "";
        if (pw1.value.length < 8) { errorEl.textContent = "Must be at least 8 characters."; pw1.select(); return; }
        if (pw1.value !== pw2.value) { errorEl.textContent = "Passwords don't match."; pw2.select(); return; }
        button.disabled = true;
        try {
            const res = await fetch("/api/auth/setup", {
                method:  "POST",
                headers: { "Content-Type": "application/json" },
                body:    JSON.stringify({ password: pw1.value }),
            });
            if (res.status === 429) { errorEl.textContent = "Too many attempts. Wait a minute."; return; }
            const body = await res.json().catch(() => ({}));
            if (!res.ok) { errorEl.textContent = body.error || `Error ${res.status}`; return; }
            // Server has set the cookie and saved the password -- reload to enter
            // the panel as a freshly-authed session.
            location.reload();
        } catch (e) {
            errorEl.textContent = e.message;
        } finally {
            button.disabled = false;
            pw1.value = pw2.value = "";
        }
    }

    button.addEventListener("click", trySetup);
    pw2.addEventListener("keydown", e => { if (e.key === "Enter") trySetup(); });
}

function setupAccountPanel() {
    const logoutBtn = document.getElementById("acctLogout");
    const changeBtn = document.getElementById("acctChangePw");
    const form      = document.getElementById("acctChangeForm");
    const cur       = document.getElementById("acctCurrent");
    const nxt       = document.getElementById("acctNew");
    const cnf       = document.getElementById("acctConfirm");
    const submit    = document.getElementById("acctSubmit");
    const cancel    = document.getElementById("acctCancel");
    const msg       = document.getElementById("acctMsg");
    if (!logoutBtn || !changeBtn) return;

    logoutBtn.addEventListener("click", async () => {
        if (!confirm("Log out of the panel?")) return;
        try { await fetch("/api/auth/logout", { method: "POST" }); }
        finally { location.reload(); }
    });

    changeBtn.addEventListener("click", () => {
        form.hidden = !form.hidden;
        msg.textContent = "";
        if (!form.hidden) cur.focus();
    });
    cancel.addEventListener("click", () => {
        form.hidden = true;
        cur.value = nxt.value = cnf.value = "";
        msg.textContent = "";
    });

    submit.addEventListener("click", async () => {
        msg.className = "acct-msg";
        msg.textContent = "";
        if (nxt.value.length < 8) { msg.textContent = "New password must be at least 8 characters."; return; }
        if (nxt.value !== cnf.value) { msg.textContent = "New password and confirmation don't match."; return; }
        submit.disabled = true;
        try {
            const res = await fetch("/api/auth/change-password", {
                method:  "POST",
                headers: { "Content-Type": "application/json" },
                body:    JSON.stringify({ current: cur.value, next: nxt.value }),
            });
            const body = await res.json().catch(() => ({}));
            if (!res.ok) { msg.textContent = body.error || `Error ${res.status}`; return; }
            msg.className = "acct-msg ok";
            msg.textContent = "Password changed.";
            cur.value = nxt.value = cnf.value = "";
            setTimeout(() => { form.hidden = true; msg.textContent = ""; }, 1500);
        } catch (e) {
            msg.textContent = e.message;
        } finally {
            submit.disabled = false;
        }
    });
}
