/* global React, ReactDOM, SigninScreen, HomeScreen, PGALineupScreen, PGAStandingsScreen, PGAMatchupScreen, GolferDetailScreen, ClubhouseScreen, StatsScreen, SettingsScreen, AdminScreen, ProfileScreen, MemberLineupSheet, MemberPickerSheet, STORE, useStore, C */
// app.jsx — real app shell. Wraps the screens in a responsive, navigable
// container and exposes window.appNav for headers, bottom nav, tabs, and
// any in-screen taps to call.

const ROUTES = {
  home:               { Screen: () => <HomeScreen />,         label: 'Home' },
  'pools':            { Screen: () => <PGALineupScreen />,    label: 'Pools' },
  'pools/lineup':     { Screen: () => <PGALineupScreen />,    label: 'Lineup' },
  'pools/standings':  { Screen: () => <PGAStandingsScreen />, label: 'Standings' },
  'pools/matchup':    { Screen: () => <PGAMatchupScreen />,   label: 'Matchup' },
  'pools/clubhouse':  { Screen: () => <ClubhouseScreen />,    label: 'Clubhouse' },
  stats:              { Screen: () => <StatsScreen />,        label: 'Stats' },
  signin:             { Screen: () => <SigninScreen />,       label: 'Sign in' },
  profile:            { Screen: () => <ProfileScreen />,      label: 'Profile' },
  admin:              { Screen: () => <AdminScreen />,        label: 'Admin' },
};

// "Board" in the bottom nav is the season-level leaderboard; until that
// screen exists, route to the live tournament standings.
ROUTES['board'] = ROUTES['pools/standings'];

function getInitialRoute() {
  const hash = (window.location.hash || '').replace(/^#\/?/, '');
  return ROUTES[hash] ? hash : 'home';
}

function App() {
  const [route, setRoute] = React.useState(getInitialRoute);
  const [history, setHistory] = React.useState([]);
  const [sheet, setSheet]    = React.useState(null);
  const authed = useStore((s) => s.authed);
  const palette = useStore((s) => s.settings.palette);
  const toast = useStore((s) => s.toast);

  // Apply palette during render so children's inline styles see the new
  // C constants on this pass. Idempotent — safe to call every render.
  applyPalette(palette);

  const go = React.useCallback((next) => {
    if (!ROUTES[next]) return;
    setRoute((cur) => {
      if (cur !== next) {
        setHistory((h) => [...h, cur]);
        window.location.hash = '/' + next;
      }
      return next;
    });
    setSheet(null);
  }, []);

  const back = React.useCallback(() => {
    if (sheet) { setSheet(null); return; }
    setHistory((h) => {
      if (h.length === 0) {
        setRoute('home');
        window.location.hash = '/home';
        return h;
      }
      const prev = h[h.length - 1];
      setRoute(prev);
      window.location.hash = '/' + prev;
      return h.slice(0, -1);
    });
  }, [sheet]);

  const openSheet  = React.useCallback((s, payload) => {
    STORE.set({ sheetPayload: payload || null });
    setSheet(s);
  }, []);
  const closeSheet = React.useCallback(() => {
    setSheet(null);
    STORE.set({ sheetPayload: null });
  }, []);

  // Expose imperative nav API for header/tab/bottom-nav buttons.
  React.useEffect(() => {
    window.appNav = { go, back, openSheet, closeSheet, current: () => route };
    return () => { delete window.appNav; };
  }, [go, back, openSheet, closeSheet, route]);

  // Cross-tab/browser back-button sync. Hash change also closes any open sheet.
  React.useEffect(() => {
    const onHash = () => {
      const next = (window.location.hash || '').replace(/^#\/?/, '');
      if (ROUTES[next] && next !== route) { setRoute(next); setSheet(null); }
    };
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, [route]);

  // Esc closes any open sheet.
  React.useEffect(() => {
    if (!sheet) return;
    const onKey = (e) => { if (e.key === 'Escape') closeSheet(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [sheet, closeSheet]);

  // Passkey enrollment auto-prompt. Fires once when the user lands fresh
  // from a magic-link (not on session restore / page reload). If they
  // don't already have a passkey enrolled, ask if they want to add one —
  // accept = Face ID prompt → done; "Not now" = persistent flag, never
  // ask again on this device.
  const [showPasskeyPrompt, setShowPasskeyPrompt] = React.useState(false);
  React.useEffect(() => {
    const api = window.cambamApi;
    if (!api || !api.onAuthChange) return;
    return api.onAuthChange(async (event) => {
      // Only fresh sign-ins trigger the prompt. INITIAL_SESSION is what
      // fires on page reload with a persisted session — we skip that.
      if (event !== 'SIGNED_IN') return;
      if (!api.webauthnSupported || !api.webauthnSupported()) return;
      let dismissed = null;
      try { dismissed = localStorage.getItem('cambam-passkey-prompted'); } catch {}
      if (dismissed === '1') return;
      const passkeys = await api.listPasskeys();
      if (passkeys && passkeys.length > 0) return;
      setShowPasskeyPrompt(true);
    });
  }, []);

  const dismissPasskeyPrompt = React.useCallback(() => {
    try { localStorage.setItem('cambam-passkey-prompted', '1'); } catch {}
    setShowPasskeyPrompt(false);
  }, []);

  // Auth gate — render SigninScreen until authed.
  if (!authed) {
    return (
      <div className="app-shell">
        <div className="app-frame">
          <SigninScreen />
          {toast && <Toast text={toast.text} />}
        </div>
      </div>
    );
  }

  const RouteScreen = (ROUTES[route] || ROUTES.home).Screen;

  const SheetScreen = sheet === 'settings'      ? SettingsScreen
                    : sheet === 'admin'         ? AdminScreen
                    : sheet === 'profile'       ? ProfileScreen
                    : sheet === 'golfer-detail' ? GolferDetailScreen
                    : sheet === 'member-lineup' ? MemberLineupSheet
                    : sheet === 'member-picker' ? MemberPickerSheet
                    : null;

  return (
    <div className="app-shell">
      <div className="app-frame">
        <RouteScreen />
        {SheetScreen && (
          <div className="app-sheet-layer" onClick={(e) => {
            if (e.target === e.currentTarget) closeSheet();
          }}>
            <SheetScreen />
          </div>
        )}
        {showPasskeyPrompt && <PasskeyPrompt onDismiss={dismissPasskeyPrompt} />}
        {toast && <Toast text={toast.text} />}
      </div>
    </div>
  );
}

// ─── Passkey enrollment auto-prompt ─────────────────────────────────
// Fires once after a fresh magic-link sign-in if the user has no passkeys
// enrolled. Either button (Add or Not now) sets a localStorage flag so
// we never re-prompt on this device — the user can always go to Settings
// → Sign in → Add a passkey later.
function PasskeyPrompt({ onDismiss }) {
  const me = useStore((s) => s.me);
  const [busy, setBusy] = React.useState(false);

  const add = async () => {
    if (busy) return;
    setBusy(true);
    try {
      const res = await window.cambamApi.enrollPasskey(me.email);
      if (res.ok) {
        STORE.toast('Passkey saved — sign in with Face ID next time');
        onDismiss();
      } else if (res.cancelled) {
        // User pressed cancel in the OS prompt. Keep the modal open so they
        // can choose deliberately — Add to retry, Not now to never see it.
      } else {
        STORE.toast(res.error || 'Could not save passkey');
      }
    } finally { setBusy(false); }
  };

  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 250,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24,
      background: 'rgba(0,0,0,0.65)',
      animation: 'sheet-in 200ms ease-out',
    }}>
      <div style={{
        width: '100%', maxWidth: 340,
        background: C.surface, borderRadius: 16,
        padding: '28px 24px 20px',
        textAlign: 'center',
      }}>
        <div style={{
          width: 56, height: 56, borderRadius: 999, margin: '0 auto 14px',
          background: 'rgba(31,138,91,0.15)', color: C.emerald,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Passkey size={28} />
        </div>
        <div style={{ font: '700 19px/24px Inter', color: C.text, letterSpacing: -0.01 * 19 }}>
          Skip the email next time?
        </div>
        <div style={{ font: '400 14px/20px Inter', color: C.text2, marginTop: 8 }}>
          Save a passkey to this device. Future sign-ins are one tap with Face ID — no email, no waiting.
        </div>
        <button
          onClick={add}
          disabled={busy}
          style={{
            width: '100%', height: 48, marginTop: 20,
            background: C.emerald, color: '#0a0a0a',
            border: 'none', borderRadius: 8,
            font: '600 15px/1 Inter',
            cursor: busy ? 'wait' : 'pointer',
          }}>
          {busy ? 'Saving…' : 'Add passkey'}
        </button>
        <button
          onClick={onDismiss}
          disabled={busy}
          style={{
            width: '100%', height: 40, marginTop: 8,
            background: 'transparent', color: C.text3,
            border: 'none',
            font: '500 13px/1 Inter',
            cursor: busy ? 'wait' : 'pointer',
          }}>
          Not now
        </button>
      </div>
    </div>
  );
}

function Toast({ text }) {
  return (
    <div style={{
      position: 'absolute', left: '50%', bottom: 96, zIndex: 300,
      transform: 'translateX(-50%)',
      background: 'rgba(31, 138, 91, 0.95)', color: '#0a0a0a',
      padding: '10px 16px', borderRadius: 999,
      font: '600 13px/16px Inter',
      boxShadow: '0 6px 14px rgba(0,0,0,0.4)',
      pointerEvents: 'none',
      animation: 'toast-in 200ms ease-out',
    }}>{text}</div>
  );
}

// Palette swap — adjusts the CSS variables that drive emerald accents.
const PALETTE_VARS = {
  dusk:      { emerald: '#1f8a5b', mute: '#0c3d28', bg: '#0a0a0a', surf: '#141414', surf2: '#1c1c1c', text: '#f5f5f4', text2: '#a3a3a3', text3: '#525252' },
  dawn:      { emerald: '#2fa46a', mute: '#143625', bg: '#13110d', surf: '#1c1a16', surf2: '#252220', text: '#f3ede2', text2: '#b3a999', text3: '#5e564b' },
  fireplace: { emerald: '#b08d2f', mute: '#3a2e10', bg: '#0b0907', surf: '#161210', surf2: '#1f1a17', text: '#f5ece1', text2: '#a99a85', text3: '#5b4f43' },
  moonlit:   { emerald: '#5bb89a', mute: '#163128', bg: '#0a0d10', surf: '#13171b', surf2: '#1b2026', text: '#eaedf1', text2: '#9aa3ad', text3: '#4b525a' },
};
function applyPalette(key) {
  const p = PALETTE_VARS[key] || PALETTE_VARS.dusk;
  const r = document.documentElement;
  r.style.setProperty('--emerald',      p.emerald);
  r.style.setProperty('--emerald-mute', p.mute);
  r.style.setProperty('--emerald-15',   hexToRgba(p.emerald, 0.15));
  r.style.setProperty('--emerald-08',   hexToRgba(p.emerald, 0.08));
  r.style.setProperty('--bg',           p.bg);
  r.style.setProperty('--surface',      p.surf);
  r.style.setProperty('--surface-2',    p.surf2);
  r.style.setProperty('--text',         p.text);
  r.style.setProperty('--text-2',       p.text2);
  r.style.setProperty('--text-3',       p.text3);

  // Mirror into the JS color object so inline-style references update on next
  // render. Components read window.C at render time, so this propagates the
  // new palette through the React tree without prop-drilling.
  if (window.C) {
    window.C.emerald     = p.emerald;
    window.C.emeraldMute = p.mute;
    window.C.bg          = p.bg;
    window.C.surface     = p.surf;
    window.C.surface2    = p.surf2;
    window.C.text        = p.text;
    window.C.text2       = p.text2;
    window.C.text3       = p.text3;
  }
}
function hexToRgba(hex, a) {
  const x = hex.replace('#', '');
  const n = parseInt(x.length === 3 ? x.split('').map(c => c + c).join('') : x, 16);
  return `rgba(${(n >> 16) & 255}, ${(n >> 8) & 255}, ${n & 255}, ${a})`;
}

window.APP_MODE = true;
window.App = App;

// Apply the persisted palette synchronously, before the first render, so the
// initial paint already uses the right pine/gold/silver tone.
applyPalette(window.STORE.state.settings.palette);

ReactDOM.createRoot(document.getElementById('root')).render(<App />);

