// auth.jsx — local device auth (PIN lock + technician profile).
// ─────────────────────────────────────────────────────────────────────────────
// This is an OFFLINE, client-side gate: the PIN is hashed (SHA-256 + salt) and
// kept in localStorage; identity (name/license/station) lives alongside it and
// feeds the greeting, avatar and Profile. It is a device lock, NOT server-grade
// auth (anyone with devtools could clear localStorage) — fine for a personal /
// small-team line tool. `useAuth` is the seam: to upgrade to real accounts + sync
// later, swap its body for a Supabase provider (signUp/signIn/session) and keep
// the same { stage, profile, setup, unlock, lock, signOut } shape the UI uses.
// ─────────────────────────────────────────────────────────────────────────────

const AUTH_KEY = "aerolog.auth.v1";
const UNLOCK_KEY = "aerolog.unlocked";   // sessionStorage: stay unlocked within a tab session

// First run starts blank — the user types their own details (placeholders guide).
const DEFAULT_PROFILE = { name: "", license: "", emp: "", station: "", authz: "" };

function loadAuth() {
  try { const r = localStorage.getItem(AUTH_KEY); if (r) { const a = JSON.parse(r); if (a && a.pinHash) return a; } } catch (e) {}
  return null;
}
function saveAuth(a) { try { localStorage.setItem(AUTH_KEY, JSON.stringify(a)); } catch (e) {} }
function clearAuth() { try { localStorage.removeItem(AUTH_KEY); sessionStorage.removeItem(UNLOCK_KEY); } catch (e) {} }

function randHex(n) {
  const a = new Uint8Array(n);
  if (window.crypto && crypto.getRandomValues) crypto.getRandomValues(a);
  else for (let i = 0; i < n; i++) a[i] = Math.floor(Math.random() * 256);
  return [...a].map((b) => b.toString(16).padStart(2, "0")).join("");
}
async function hashPin(pin, salt) {
  const data = salt + ":" + pin;
  if (window.crypto && crypto.subtle) {
    const buf = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(data));
    return [...new Uint8Array(buf)].map((b) => b.toString(16).padStart(2, "0")).join("");
  }
  // weak fallback (non-secure context only) — keeps the gate functional
  let h = 5381; for (let i = 0; i < data.length; i++) { h = ((h << 5) + h) + data.charCodeAt(i); h |= 0; }
  return "x" + (h >>> 0).toString(16);
}
function initials(name) {
  const w = String(name || "").trim().split(/\s+/).filter(Boolean);
  if (!w.length) return "AE";
  return (w[0][0] + (w[1] ? w[1][0] : "")).toUpperCase();
}

// ── the auth seam ────────────────────────────────────────────────────────────
function useAuth() {
  const [auth, setAuthState] = React.useState(loadAuth);
  const [unlocked, setUnlocked] = React.useState(() => { try { return !!sessionStorage.getItem(UNLOCK_KEY); } catch (e) { return false; } });
  const stage = !auth ? "setup" : (unlocked ? "in" : "locked");
  const setup = async ({ profile, pin }) => {
    const salt = randHex(8); const pinHash = await hashPin(pin, salt);
    const a = { v: 1, salt, pinHash, profile };
    saveAuth(a); try { sessionStorage.setItem(UNLOCK_KEY, "1"); } catch (e) {}
    setAuthState(a); setUnlocked(true);
  };
  const unlock = async (pin) => {
    if (!auth) return false;
    const h = await hashPin(pin, auth.salt);
    if (h === auth.pinHash) { try { sessionStorage.setItem(UNLOCK_KEY, "1"); } catch (e) {} setUnlocked(true); return true; }
    return false;
  };
  const lock = () => { try { sessionStorage.removeItem(UNLOCK_KEY); } catch (e) {} setUnlocked(false); };
  const signOut = () => { clearAuth(); setAuthState(null); setUnlocked(false); };
  const updateProfile = (patch) => { if (!auth) return; const a = { ...auth, profile: { ...auth.profile, ...patch } }; saveAuth(a); setAuthState(a); };
  return { auth, profile: auth && auth.profile, stage, setup, unlock, lock, signOut, updateProfile };
}

// ── PIN pad (6 dots + numeric keypad) ────────────────────────────────────────
// onChange must be a React state setter (used as a functional updater so fast
// taps never drop a digit).
function PinPad({ value, onChange, max = 6, error }) {
  const press = (d) => onChange((v) => (v.length < max ? v + d : v));
  const del = () => onChange((v) => v.slice(0, -1));
  return (
    <>
      <div className={"pin-dots" + (error ? " pin-shake" : "")}>
        {Array.from({ length: max }).map((_, i) => <i key={i} className={"pin-dot" + (i < value.length ? " pin-dot--on" : "")} />)}
      </div>
      <div className="pin-pad">
        {[1, 2, 3, 4, 5, 6, 7, 8, 9].map((n) => <button key={n} type="button" className="pin-key" onClick={() => press("" + n)}>{n}</button>)}
        <span className="pin-key pin-key--ghost" />
        <button type="button" className="pin-key" onClick={() => press("0")}>0</button>
        <button type="button" className="pin-key pin-key--del" onClick={del} aria-label="delete">⌫</button>
      </div>
    </>
  );
}

// ── First-run setup: profile → PIN → confirm ─────────────────────────────────
function SetupScreen({ defaults, onDone }) {
  const [step, setStep] = React.useState(0);  // 0 profile · 1 set pin · 2 confirm
  const [p, setP] = React.useState(defaults || DEFAULT_PROFILE);
  const setF = (k, v) => setP((s) => ({ ...s, [k]: v }));
  const [pin, setPin] = React.useState("");
  const [pin2, setPin2] = React.useState("");
  const [err, setErr] = React.useState("");

  React.useEffect(() => { if (step === 1 && pin.length === 6) { setErr(""); setStep(2); } }, [pin, step]);
  React.useEffect(() => {
    if (step === 2 && pin2.length === 6) {
      if (pin2 === pin) {
        const name = (p.name || "").trim() || "Technician";
        onDone({ profile: { ...p, name, firstName: name.split(/\s+/)[0] }, pin });
      } else { setErr("PIN ไม่ตรงกัน ลองใหม่"); setPin(""); setPin2(""); setStep(1); }
    }
  }, [pin2, step]);

  const goPin = () => { if (!String(p.name || "").trim()) { setErr("กรอกชื่อก่อน"); return; } setErr(""); setPin(""); setStep(1); };

  if (step === 0) {
    return (
      <div className="auth">
        <div className="auth-top">
          <div className="auth-mark">AeroLog</div>
          <h1 className="auth-h">Set up your profile</h1>
          <p className="auth-sub">ข้อมูลช่างใช้แสดงในหน้าแอป + ติดกับ Work Log · เก็บในเครื่องนี้เท่านั้น</p>
        </div>
        <div className="auth-fields">
          <Field label="Full name" req><input className="inp" value={p.name} onChange={(e) => setF("name", e.target.value)} placeholder="ชื่อ–สกุล" /></Field>
          <Field label="License no."><input className="inp inp--mono" value={p.license} onChange={(e) => setF("license", e.target.value)} placeholder="TH-AME-B1 / ..." /></Field>
          <div className="timerow">
            <Field label="Employee ID"><input className="inp inp--mono" value={p.emp} onChange={(e) => setF("emp", e.target.value)} placeholder="EMP-..." /></Field>
            <Field label="Station"><input className="inp" value={p.station} onChange={(e) => setF("station", e.target.value)} placeholder="BKK" /></Field>
          </div>
          <Field label="Authorizations"><input className="inp" value={p.authz} onChange={(e) => setF("authz", e.target.value)} placeholder="A320 / A321 ..." /></Field>
          {err && <div className="auth-err">{err}</div>}
        </div>
        <div className="auth-actions">
          <Btn full kind="primary" onClick={goPin} icon={<Ic.arrowR width="18" height="18" />}>Continue · set PIN</Btn>
        </div>
      </div>
    );
  }
  const confirming = step === 2;
  return (
    <div className="auth auth--pin">
      <button className="auth-back" onClick={() => { setErr(""); confirming ? (setPin2(""), setStep(1)) : setStep(0); }}><Ic.back width="20" height="20" /></button>
      <div className="auth-mark">AeroLog</div>
      <h1 className="auth-h auth-h--c">{confirming ? "Confirm your PIN" : "Create a 6-digit PIN"}</h1>
      <p className="auth-sub auth-sub--c">{confirming ? "ใส่ PIN เดิมอีกครั้งเพื่อยืนยัน" : "ใช้ปลดล็อกแอปทุกครั้งที่เปิด"}</p>
      <PinPad value={confirming ? pin2 : pin} onChange={confirming ? setPin2 : setPin} error={!!err} />
      {err && <div className="lock-err">{err}</div>}
    </div>
  );
}

// ── Lock screen: enter PIN to unlock ─────────────────────────────────────────
function LockScreen({ profile, onUnlock, onForgot }) {
  const [pin, setPin] = React.useState("");
  const [err, setErr] = React.useState(false);
  React.useEffect(() => {
    if (pin.length === 6) {
      onUnlock(pin).then((ok) => { if (!ok) { setErr(true); setTimeout(() => { setPin(""); setErr(false); }, 550); } });
    }
  }, [pin]);
  return (
    <div className="auth auth--lock">
      <div className="lock-id">
        <div className="avatar avatar--lg">{initials(profile && profile.name)}</div>
        <div className="lock-name">{(profile && profile.name) || "AeroLog"}</div>
        <div className="lock-role">{(profile && profile.license) || "Line Maintenance"}</div>
      </div>
      <div className="lock-title">Enter PIN to unlock</div>
      <PinPad value={pin} onChange={setPin} error={err} />
      {err && <div className="lock-err">Wrong PIN</div>}
      {onForgot && <button className="lock-forgot" onClick={onForgot}>Forgot PIN? Reset profile</button>}
    </div>
  );
}

Object.assign(window, { useAuth, SetupScreen, LockScreen, PinPad, initials, DEFAULT_PROFILE });
