// mariusson — local auth + account persistence
//
// This is a *mock* auth system that lives entirely in localStorage. There's
// no server. We keep two keys:
//
//   mariusson:users    array of {id, name, handle, email, pwhash, role, ...}
//   mariusson:session  id of the user that's currently signed in
//
// What this enables, from the user's POV:
//   - Create account → role + name/email/password → persisted, signed in.
//   - Sign in        → email + password → verified against the users list.
//   - Sign out       → session cleared but the user stays in the users list,
//                      so they can sign back in with the same email.
//   - Edit profile   → changes saved to the users list and the session
//                      account in one motion (UserProfileDrawer.onSave).
//   - Refresh        → the session is restored, so you're still signed in.
//
// Passwords are obfuscated, NOT cryptographically secure. This is a demo;
// don't ship it to the real internet.

(() => {
  // Legacy "art.nation:*" keys are migrated to "mariusson:*" by the
  // pre-paint script in index.html, so by the time we run here the
  // data is already under the new key names.
  const USERS_KEY = 'mariusson:users';
  const SESSION_KEY = 'mariusson:session';

  function readUsers() {
    try {
      const raw = localStorage.getItem(USERS_KEY);
      return raw ? JSON.parse(raw) : [];
    } catch { return []; }
  }
  function writeUsers(users) {
    try { localStorage.setItem(USERS_KEY, JSON.stringify(users)); } catch {}
  }
  function readSession() {
    try { return localStorage.getItem(SESSION_KEY) || null; } catch { return null; }
  }
  function writeSession(id) {
    try {
      if (id) localStorage.setItem(SESSION_KEY, id);
      else localStorage.removeItem(SESSION_KEY);
    } catch {}
  }

  // Obfuscation only — NOT a real password hash. Good enough for a mock so
  // the password isn't sitting around as plaintext in JSON.
  function pwHash(password, email) {
    // Salt kept as the legacy 'art.nation:v1:' so existing pwhashes still
    // verify after the brand rename. Don't change this without a password-
    // reset migration; it's irrelevant anyway once D1 auth lands.
    const salt = 'art.nation:v1:';
    try {
      return btoa(unescape(encodeURIComponent(salt + email.toLowerCase().trim() + ':' + password)));
    } catch {
      return salt + email + ':' + password;
    }
  }
  function pwCheck(password, email, stored) {
    return pwHash(password, email) === stored;
  }

  function makeId() {
    return 'u_' + Math.random().toString(36).slice(2, 10) + Date.now().toString(36).slice(-4);
  }

  function findUserByEmail(email) {
    const e = email.toLowerCase().trim();
    return readUsers().find((u) => (u.email || '').toLowerCase() === e) || null;
  }

  function publicUser(u) {
    if (!u) return null;
    const { pwhash, ...safe } = u;
    return safe;
  }

  // ── public API ────────────────────────────────────────────────────────

  function register({ name, email, password, role, region, bio, studio, website, acceptsDonations }) {
    if (!email || !password) throw new Error('Email and password required');
    if (findUserByEmail(email)) throw new Error('An account with that email already exists');

    const id = makeId();
    const handle = (name || email.split('@')[0] || 'studio')
      .toLowerCase().replace(/[^a-z0-9._]/g, '').slice(0, 24) || 'studio';
    const user = {
      id,
      name: name || 'Friend',
      handle,
      email: email.toLowerCase().trim(),
      pwhash: pwHash(password, email),
      role: role || 'viewer',
      region: region || 'France',
      bio: bio || '',
      studio: studio || '',
      website: website || '',
      acceptsDonations: acceptsDonations !== false,
      createdAt: Date.now(),
    };
    const users = readUsers();
    users.push(user);
    writeUsers(users);
    writeSession(id);
    return publicUser(user);
  }

  function login({ email, password }) {
    const u = findUserByEmail(email);
    if (!u) throw new Error('No account with that email');
    if (!pwCheck(password, email, u.pwhash)) throw new Error('Wrong password');
    writeSession(u.id);
    return publicUser(u);
  }

  function logout() {
    writeSession(null);
  }

  function currentAccount() {
    const id = readSession();
    if (!id) return null;
    const u = readUsers().find((u) => u.id === id);
    return publicUser(u);
  }

  function updateAccount(patch) {
    const id = readSession();
    if (!id) throw new Error('Not signed in');
    const users = readUsers();
    const idx = users.findIndex((u) => u.id === id);
    if (idx < 0) throw new Error('Session points to no user');
    // Don't let the editor overwrite secrets/identifiers
    const { id: _i, email: _e, pwhash: _p, createdAt: _c, ...editable } = patch || {};
    users[idx] = { ...users[idx], ...editable };
    writeUsers(users);
    return publicUser(users[idx]);
  }

  function changePassword(oldPassword, newPassword) {
    const id = readSession();
    if (!id) throw new Error('Not signed in');
    const users = readUsers();
    const idx = users.findIndex((u) => u.id === id);
    if (idx < 0) throw new Error('Session points to no user');
    const u = users[idx];
    if (!pwCheck(oldPassword, u.email, u.pwhash)) throw new Error('Wrong current password');
    u.pwhash = pwHash(newPassword, u.email);
    writeUsers(users);
    return true;
  }

  // ── React hook ────────────────────────────────────────────────────────

  function useAuth() {
    const [account, setAccount] = React.useState(() => currentAccount());

    const refresh = React.useCallback(() => setAccount(currentAccount()), []);

    // Cross-tab sync: if another tab signs in/out, mirror it here.
    React.useEffect(() => {
      const onStorage = (e) => {
        if (e.key === SESSION_KEY || e.key === USERS_KEY || e.key === null) refresh();
      };
      window.addEventListener('storage', onStorage);
      return () => window.removeEventListener('storage', onStorage);
    }, [refresh]);

    return {
      account,
      register: (form) => { const a = register(form); setAccount(a); return a; },
      login:    (form) => { const a = login(form);    setAccount(a); return a; },
      logout:   () => { logout(); setAccount(null); },
      updateAccount: (patch) => { const a = updateAccount(patch); setAccount(a); return a; },
      changePassword,
    };
  }

  window.AN_AUTH = {
    register, login, logout, currentAccount, updateAccount, changePassword,
    USERS_KEY, SESSION_KEY,
  };
  window.useAuth = useAuth;
})();
