// auth.jsx — Firebase Auth (compat SDK, email/password).
//
// AuthGate and signOut drive the app's top-level auth state.
// The localStorage registry stubs below keep UserAccess working while
// that view awaits its Firestore rewrite (Part 1B admin UI).

// ─── Firebase sign-out ────────────────────────────────────────────────────

function signOut() {
  return firebase.auth().signOut();
}

// ─── Login screen ─────────────────────────────────────────────────────────

function Login() {
  const [mode,     setMode]     = React.useState(() => {
    try {
      if (sessionStorage.getItem('norwill-start-in-reset-mode') === '1') {
        sessionStorage.removeItem('norwill-start-in-reset-mode');
        return 'reset';
      }
    } catch {}
    return 'login';
  });
  const [email,    setEmail]    = React.useState(() => {
    try {
      const v = sessionStorage.getItem('norwill-prefill-email-v1');
      if (v) {
        sessionStorage.removeItem('norwill-prefill-email-v1');
        return v;
      }
    } catch {}
    return '';
  });
  const [password, setPassword] = React.useState('');
  const [err,      setErr]      = React.useState('');
  const [info,     setInfo]     = React.useState('');
  const [busy,     setBusy]     = React.useState(false);

  const AUTH_ERRORS = {
    'auth/user-not-found':     'No account found for that email.',
    'auth/wrong-password':     'Incorrect password.',
    'auth/invalid-email':      'Enter a valid email address.',
    'auth/too-many-requests':  'Too many attempts — try again in a few minutes.',
    'auth/invalid-credential': 'Invalid email or password.',
    'auth/user-disabled':      'This account has been disabled.',
  };

  const switchMode = (next) => {
    setMode(next);
    setErr('');
    setInfo('');
  };

  const submitLogin = async (e) => {
    e.preventDefault();
    setBusy(true);
    setErr('');
    try {
      await firebase.auth().signInWithEmailAndPassword(email.trim(), password);
    } catch (error) {
      setErr(AUTH_ERRORS[error.code] || error.message || 'Sign-in failed.');
    } finally {
      setBusy(false);
    }
  };

  const submitReset = async (e) => {
    e.preventDefault();
    setBusy(true);
    setErr('');
    setInfo('');
    try {
      await firebase.auth().sendPasswordResetEmail(email.trim());
      setInfo('Reset link sent — check your email. The link expires in 1 hour.');
    } catch (error) {
      setErr(AUTH_ERRORS[error.code] || 'Could not send reset email. Check the address and try again.');
    } finally {
      setBusy(false);
    }
  };

  const inputStyle = {
    padding: '11px 13px',
    border: '1px solid var(--line-strong)',
    borderRadius: 10,
    fontSize: 14,
    background: 'var(--card-alt)',
    color: 'var(--ink-900)',
    width: '100%',
    boxSizing: 'border-box',
  };

  const labelStyle = { display: 'flex', flexDirection: 'column', gap: 6 };
  const labelTextStyle = {
    fontSize: 11, fontWeight: 600, textTransform: 'uppercase',
    letterSpacing: 0.08, color: 'var(--ink-600)',
  };

  return (
    <div className="brand-wash" style={{
      minHeight: '100vh',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24,
    }}>
      <div style={{
        width: '100%', maxWidth: 420,
        background: 'var(--card)',
        border: '1px solid var(--line)',
        borderRadius: 18,
        boxShadow: 'var(--shadow-md)',
        padding: '36px 32px 28px',
      }} className="slide-up">

        {/* Logo + title */}
        <div style={{
          display: 'flex', flexDirection: 'column', alignItems: 'center',
          gap: 10, marginBottom: 24,
        }}>
          <img src="Logo.png" alt="Norwill" style={{ width: 112, height: 112, objectFit: 'contain' }}/>
          <div style={{
            fontSize: 11, letterSpacing: 0.14, textTransform: 'uppercase',
            color: 'var(--brand-700)', fontWeight: 700,
          }}>Scorecard OS</div>
        </div>

        {/* ── Sign-in form ── */}
        {mode === 'login' && (
          <form onSubmit={submitLogin} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            <label style={labelStyle}>
              <span style={labelTextStyle}>Email</span>
              <input
                autoFocus
                type="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                autoComplete="email"
                placeholder="you@norwillhcs.com"
                required
                style={inputStyle}
              />
            </label>

            <label style={labelStyle}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span style={labelTextStyle}>Password</span>
                <button
                  type="button"
                  onClick={() => switchMode('reset')}
                  style={{
                    background: 'none', border: 'none', padding: 0,
                    fontSize: 12, color: 'var(--brand-600)',
                    cursor: 'pointer', fontWeight: 500,
                    textDecoration: 'underline', textUnderlineOffset: 2,
                  }}
                >Forgot password?</button>
              </div>
              <input
                type="password"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                autoComplete="current-password"
                placeholder="••••••••"
                required
                style={inputStyle}
              />
            </label>

            {err && (
              <div style={{
                padding: '9px 12px', background: 'var(--bad-bg)', color: 'var(--bad)',
                borderRadius: 9, fontSize: 12.5, fontWeight: 500,
              }}>{err}</div>
            )}

            <button type="submit" disabled={busy} style={{
              marginTop: 4, padding: '12px 14px', border: 'none', borderRadius: 10,
              background: 'linear-gradient(135deg, var(--brand-700), var(--brand-500))',
              color: '#fff', fontSize: 14, fontWeight: 600, letterSpacing: 0.02,
              cursor: busy ? 'wait' : 'pointer', opacity: busy ? 0.75 : 1,
              boxShadow: '0 4px 14px rgba(11, 106, 116, 0.28)',
            }}>
              {busy ? 'Signing in…' : 'Sign in'}
            </button>
          </form>
        )}

        {/* ── Forgot password form ── */}
        {mode === 'reset' && (
          <form onSubmit={submitReset} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            <p style={{ margin: 0, fontSize: 13.5, color: 'var(--ink-600)', lineHeight: 1.55 }}>
              Enter your email and we'll send you a link to set your password.
            </p>

            <label style={labelStyle}>
              <span style={labelTextStyle}>Email</span>
              <input
                autoFocus
                type="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                autoComplete="email"
                placeholder="you@norwillhcs.com"
                required
                style={inputStyle}
              />
            </label>

            {err && (
              <div style={{
                padding: '9px 12px', background: 'var(--bad-bg)', color: 'var(--bad)',
                borderRadius: 9, fontSize: 12.5, fontWeight: 500,
              }}>{err}</div>
            )}

            {info && (
              <div style={{
                padding: '9px 12px', background: 'var(--ok-bg)', color: 'var(--ok)',
                borderRadius: 9, fontSize: 12.5, fontWeight: 500,
              }}>{info}</div>
            )}

            <button type="submit" disabled={busy || !!info} style={{
              marginTop: 4, padding: '12px 14px', border: 'none', borderRadius: 10,
              background: 'linear-gradient(135deg, var(--brand-700), var(--brand-500))',
              color: '#fff', fontSize: 14, fontWeight: 600,
              cursor: (busy || info) ? 'default' : 'pointer',
              opacity: (busy || info) ? 0.65 : 1,
              boxShadow: '0 4px 14px rgba(11, 106, 116, 0.28)',
            }}>
              {busy ? 'Sending…' : 'Send reset link'}
            </button>

            <button
              type="button"
              onClick={() => switchMode('login')}
              style={{
                background: 'none', border: 'none', padding: '4px 0',
                fontSize: 13, color: 'var(--ink-500)', cursor: 'pointer',
                textAlign: 'center',
              }}
            >← Back to sign in</button>
          </form>
        )}

      </div>
    </div>
  );
}

// ─── AuthGate ─────────────────────────────────────────────────────────────
// Wraps the entire app. Listens to Firebase auth state and fetches the
// /users/{uid} profile doc on each sign-in to build the authUser object
// the rest of the app consumes.

function AuthGate() {
  // Firebase Auth action handler: ?mode=resetPassword&oobCode=... short-circuits
  // the normal auth flow and renders the branded reset screen instead.
  const params = new URLSearchParams(window.location.search);
  const resetCode = (params.get('mode') === 'resetPassword') ? params.get('oobCode') : null;

  // undefined = still resolving, null = signed out, object = signed in + profile loaded
  const [authUser, setAuthUser] = React.useState(undefined);

  React.useEffect(() => {
    if (resetCode) return undefined; // skip auth subscription during reset handoff
    const unsub = firebase.auth().onAuthStateChanged(async (fbUser) => {
      if (!fbUser) {
        setAuthUser(null);
        return;
      }
      try {
        const snap = await firebase.firestore().collection('users').doc(fbUser.uid).get();
        if (snap.exists) {
          setAuthUser({ uid: fbUser.uid, email: fbUser.email, ...snap.data() });
        } else {
          console.warn('[norwill] No /users/ profile for uid', fbUser.uid, '— signing out');
          await firebase.auth().signOut();
          setAuthUser(null);
        }
      } catch (err) {
        console.error('[norwill] Profile fetch failed:', err);
        setAuthUser(null);
      }
    });
    return unsub;
  }, [resetCode]);

  if (resetCode) return <ResetPassword oobCode={resetCode} />;

  if (authUser === undefined) {
    return (
      <div className="brand-wash" style={{
        minHeight: '100vh',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <div style={{ color: 'var(--ink-400)', fontSize: 14, letterSpacing: 0.02 }}>
          Loading…
        </div>
      </div>
    );
  }

  if (authUser === null) return <Login />;

  return <App authUser={authUser} onSignOut={signOut} />;
}

// ─── Admin "View as" impersonation ────────────────────────────────────────
// Lets admin/owner mirror a teammate's filtered view (scorecard, entries,
// nav) without changing their own write identity. Persisted in localStorage
// so the override survives reloads. Writes always go as the real user —
// `submittedBy` stays true to who actually clicked the button.

const IMPERSONATE_KEY = 'norwill-impersonate-v1';

function getImpersonation() {
  try { return localStorage.getItem(IMPERSONATE_KEY) || null; }
  catch { return null; }
}

function setImpersonation(personaId) {
  try {
    if (personaId) localStorage.setItem(IMPERSONATE_KEY, personaId);
    else           localStorage.removeItem(IMPERSONATE_KEY);
    // Notify same-tab listeners (storage event only fires cross-tab).
    window.dispatchEvent(new CustomEvent('norwill:impersonation-changed'));
  } catch (e) { console.warn('[norwill] impersonation write failed', e); }
}

function clearImpersonation() { setImpersonation(null); }

// Map persona id → the auth role that persona should have when an admin
// "Views as" them. Mirrors LEGACY_USERS / the live /users collection so the
// rendered sidebar and CEO-only views match what that person would actually
// see. Only Olie (CEO) gets owner-level access; everyone else is a member.
function roleForPersona(personaId) {
  if (personaId === 'olie' || personaId === 'maria') return 'owner';
  return 'member';
}

// Returns the effective authUser to render with: real user if not
// impersonating, or a synthesized identity that mirrors the impersonated
// teammate's role + persona. Never elevates privilege beyond what that
// teammate has in their own account.
function applyImpersonation(authUser) {
  if (!authUser) return authUser;
  const isPriv = authUser.role === 'admin' || authUser.role === 'owner';
  if (!isPriv) return authUser;
  const target = getImpersonation();
  if (!target) return authUser;
  const PEOPLE = window.NORWILL_DATA?.PEOPLE || [];
  const person = PEOPLE.find(p => p.id === target);
  if (!person) return authUser;
  return {
    ...authUser,
    role: roleForPersona(target),
    personaId: target,
    name: person.name,
    title: person.role,
    _impersonating: true,
    _realRole: authUser.role,
    _realName: authUser.name,
  };
}

window.norwillImpersonation = { get: getImpersonation, set: setImpersonation, clear: clearImpersonation, apply: applyImpersonation };

// ─── Legacy localStorage registry stubs ───────────────────────────────────
// These keep UserAccess functional while it awaits a Firestore rewrite.
// Do not add new callers. Remove when admin UI lands.

const REGISTRY_KEY = 'norwill-user-registry-v1';
const SALT         = 'norwill-salt-v1';
const SEED_PASSWORD_HASH = 'b453b0067add193b6fb3a79c4d30ca569ee16a1854c97310381b977a50bc0a8b';

const LEGACY_USERS = [
  { username: 'dave',   name: 'Dave Worden',     role: 'admin',  personaId: null,      title: 'Triumph Advisor · Admin' },
  { username: 'olie',   name: 'Olie Mogilevsky', role: 'owner',  personaId: 'olie',    title: 'Owner / CEO' },
  { username: 'ashley', name: 'Ashley M.',       role: 'member', personaId: 'ashley',  title: 'Recruitment Lead' },
  { username: 'carmen', name: 'Carmen S.',       role: 'member', personaId: 'carmen',  title: 'Scheduling / Ops' },
  { username: 'maria',  name: 'Maria Mann',      role: 'owner',  personaId: 'maria',   title: 'Executive Manager' },
];

async function hashPassword(plain) {
  const encoder = new TextEncoder();
  const bytes   = encoder.encode(String(plain) + SALT);
  const buf     = await crypto.subtle.digest('SHA-256', bytes);
  return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
}

function loadUserRegistry() {
  try {
    const raw = localStorage.getItem(REGISTRY_KEY);
    if (raw) {
      const parsed = JSON.parse(raw);
      if (parsed && Array.isArray(parsed.users) && parsed.users.length) return parsed.users;
    }
  } catch (e) {
    console.warn('[norwill] registry parse failed; reseeding', e);
  }
  const seeded = LEGACY_USERS.map(u => ({
    ...u, passwordHash: SEED_PASSWORD_HASH, active: true, createdAt: Date.now(),
  }));
  saveUserRegistry(seeded);
  return seeded;
}

function saveUserRegistry(users) {
  localStorage.setItem(REGISTRY_KEY, JSON.stringify({ version: 1, users }));
}

function findUserByUsername(username) {
  const clean = (username || '').trim().toLowerCase();
  return loadUserRegistry().find(u => u.username === clean) || null;
}

async function addUser({ username, password, name, role, personaId, title }) {
  const clean = String(username || '').trim().toLowerCase();
  if (!clean)    throw new Error('Username is required.');
  if (!password) throw new Error('Password is required.');
  const users = loadUserRegistry();
  if (users.some(u => u.username === clean)) throw new Error(`Username "${clean}" is already taken.`);
  const passwordHash = await hashPassword(password);
  const next = [...users, {
    username: clean, passwordHash,
    name: name || clean, role: role || 'member',
    personaId: personaId || null, title: title || '',
    active: true, createdAt: Date.now(),
  }];
  saveUserRegistry(next);
  return findUserByUsername(clean);
}

async function updateUser(username, patch) {
  const clean = String(username || '').trim().toLowerCase();
  const users = loadUserRegistry();
  const idx   = users.findIndex(u => u.username === clean);
  if (idx < 0) throw new Error(`User "${clean}" not found.`);
  const next  = { ...users[idx] };
  for (const key of ['name', 'role', 'personaId', 'title', 'active']) {
    if (patch && Object.prototype.hasOwnProperty.call(patch, key)) next[key] = patch[key];
  }
  if (patch && patch.username && patch.username.trim().toLowerCase() !== clean) {
    const nu = patch.username.trim().toLowerCase();
    if (users.some(u => u.username === nu)) throw new Error(`Username "${nu}" is already taken.`);
    next.username = nu;
  }
  if (patch && patch.password) next.passwordHash = await hashPassword(patch.password);
  users[idx] = next;
  saveUserRegistry(users);
  return next;
}

function removeUser(username) {
  const clean = String(username || '').trim().toLowerCase();
  saveUserRegistry(loadUserRegistry().filter(u => u.username !== clean));
}

// getAuthUser is no longer the source of truth — Firebase onAuthStateChanged drives
// auth state. Kept as a shim for any legacy callers.
function getAuthUser() {
  const fbUser = (typeof firebase !== 'undefined') ? firebase.auth().currentUser : null;
  if (fbUser) return null; // real auth is live; don't use the local shim
  try {
    const raw = localStorage.getItem('norwill-auth-v1');
    if (!raw) return null;
    const saved = JSON.parse(raw);
    return findUserByUsername(saved.username);
  } catch { return null; }
}

Object.assign(window, {
  // Auth (Firebase-backed)
  signOut, Login, AuthGate,
  // Legacy registry (UserAccess — remove when Firestore admin UI lands)
  getAuthUser, loadUserRegistry, saveUserRegistry,
  findUserByUsername, addUser, updateUser, removeUser, hashPassword,
});
