// App shell — auth gate + real routing.
// Signed-out → Onboarding (Sign in step shows Google).
// Signed-in + no kids → Onboarding (skips to "Add your kid" step).
// Signed-in + kids → Dashboard / Kid view / etc, navigable via hash routes.

const { StoreProvider, useStore } = window;

const ROUTES = [
  { id: 'dashboard',  label: 'Family',     icon: '🏠' },
  { id: 'kidview',    label: 'Kid view',   icon: '✨' },
  { id: 'tasks',      label: 'Tasks & jars', icon: '☑️' },
  { id: 'share',      label: 'Share',      icon: '👥' },
];

function useHashRoute(defaultRoute = 'dashboard') {
  const [route, setRoute] = React.useState(() => {
    const h = window.location.hash.replace('#/', '').replace('#', '') || defaultRoute;
    return h;
  });
  React.useEffect(() => {
    const onHash = () => {
      const h = window.location.hash.replace('#/', '').replace('#', '') || defaultRoute;
      setRoute(h);
    };
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, [defaultRoute]);
  const nav = React.useCallback((r) => { window.location.hash = '#/' + r; }, []);
  return [route, nav];
}

function AppShell() {
  const s = useStore();
  const joinToken = useJoinToken();

  if (s.status === 'loading') return <BootScreen />;
  if (s.status === 'error')   return <ErrorScreen message={s.error} />;

  // /#/join/<token> — unauthenticated invitee landing page.
  if (joinToken && (s.status === 'signed-out' || !s.user)) {
    return <JoinScreen token={joinToken} />;
  }
  // /#/join/<token> — already signed in; redeem immediately and land in app.
  if (joinToken && s.user) {
    return <JoinRedeem token={joinToken} />;
  }

  // Signed-out → onboarding (sign-in step)
  if (s.status === 'signed-out' || !s.user) {
    return <window.Onboarding accent="mango" />;
  }

  // Signed-in but no kids yet → onboarding (post-sign-in path: Family → Kid → …)
  if (!s.kids.length) {
    return <window.Onboarding accent="mango" startStep={0} skipSignIn />;
  }

  return <MainApp />;
}

// Returns the join token if the current hash is #/join/<token>, else null.
function useJoinToken() {
  const read = () => {
    const m = window.location.hash.match(/^#\/join\/([A-Za-z0-9_-]+)/);
    return m ? m[1] : null;
  };
  const [token, setToken] = React.useState(read);
  React.useEffect(() => {
    const onHash = () => setToken(read());
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);
  return token;
}

// Shown to an unauthenticated invitee on /#/join/<token>.
// Peeks the invitation (no auth required) and prompts Google sign-in.
function JoinScreen({ token }) {
  const s = useStore();
  const [info, setInfo] = React.useState(undefined); // undefined = loading, null = not-found
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);

  React.useEffect(() => {
    let alive = true;
    sessionStorage.setItem('sirisora.pendingInviteToken', token);
    (async () => {
      try {
        const row = await window.db.peekInvitation(token);
        if (alive) setInfo(row);
      } catch (e) {
        if (alive) { setInfo(null); setErr(e?.message || 'Could not load invitation.'); }
      }
    })();
    return () => { alive = false; };
  }, [token]);

  const go = async () => {
    setBusy(true); setErr(null);
    try { await s.signInWithGoogle(); }
    catch (e) { setErr(e?.message || 'Sign-in failed'); setBusy(false); }
  };

  return (
    <div className="onb-wrap" style={{ minHeight: '100vh' }}>
      <style>{`
        .join-card {
          max-width: 540px;
          margin: 60px auto;
          background: var(--paper-2);
          border-radius: 28px;
          padding: 40px 36px;
          box-shadow: 0 4px 8px rgba(31,26,61,0.08), 0 24px 60px -16px rgba(31,26,61,0.2);
          text-align: center;
        }
        .join-mascot { display: grid; place-items: center; margin-bottom: 18px; }
        .join-tag {
          display: inline-block;
          padding: 6px 12px; border-radius: 999px;
          background: var(--butter-soft); color: var(--ink);
          font-family: var(--font-display); font-weight: 700; font-size: 12px;
          letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 16px;
        }
      `}</style>
      <div className="join-card">
        <div className="join-mascot">
          <window.Suri mood="wave" size={120} color="#FF6B2C" wave />
        </div>
        <span className="join-tag">You're invited</span>
        {info === undefined && (
          <div style={{ color: 'var(--ink-soft)' }}>Loading invitation…</div>
        )}
        {info === null && (
          <>
            <h1 className="h-display h2" style={{ marginBottom: 10 }}>Hmm, that link didn't work.</h1>
            <p className="lede" style={{ color: 'var(--ink-soft)' }}>
              The invite may have been revoked, already used, or expired. Ask the person who sent it to create a new one.
            </p>
            <a href="#/" className="btn btn-ghost" style={{ marginTop: 18 }}>Go home</a>
          </>
        )}
        {info && info.status !== 'pending' && (
          <>
            <h1 className="h-display h2" style={{ marginBottom: 10 }}>This invite is no longer active.</h1>
            <p className="lede" style={{ color: 'var(--ink-soft)' }}>
              Status: {info.status}. Please ask the owner to send a new invite.
            </p>
          </>
        )}
        {info && info.status === 'pending' && (
          <>
            <h1 className="h-display h2" style={{ marginBottom: 10 }}>
              Join <em style={{ fontStyle: 'normal', color: 'var(--mango)' }}>{info.household_name}</em>
            </h1>
            <p className="lede" style={{ color: 'var(--ink-soft)', maxWidth: 420, margin: '0 auto' }}>
              You'll join as <strong>{labelForRole(info.role)}</strong> for the email <strong>{info.invited_email}</strong>.
              Sign in with Google to accept.
            </p>
            <div style={{ marginTop: 28 }}>
              <button className="btn btn-google" onClick={go} disabled={busy}
                style={{ opacity: busy ? 0.6 : 1 }}>
                <GoogleG /> {busy ? 'Opening Google…' : 'Continue with Google'}
              </button>
              {err && <div style={{ marginTop: 12, color: 'var(--alert)' }}>{err}</div>}
              <div style={{ fontSize: 12, color: 'var(--ink-faint)', marginTop: 14 }}>
                We use your Google account to confirm it's really you — no passwords to share.
              </div>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

// Already signed in and visiting /#/join/<token>: redeem and route to dashboard.
function JoinRedeem({ token }) {
  const s = useStore();
  const ranRef = React.useRef(false);
  React.useEffect(() => {
    if (ranRef.current) return;
    ranRef.current = true;
    (async () => {
      try {
        const { data, error } = await window.db.client.rpc('redeem_invitation', { p_token: token });
        if (error) throw error;
        const row = data && data[0];
        if (row) {
          sessionStorage.setItem('sirisora.lastInviteJoined', JSON.stringify(row));
          sessionStorage.setItem('sirisora.preferHouseholdId', row.household_id);
        }
        await s.rehydrate?.();
      } catch (e) {
        sessionStorage.setItem('sirisora.lastInviteError', e?.message || 'Could not redeem invitation.');
      } finally {
        window.location.hash = '#/share';
      }
    })();
  }, [token, s]);
  return <BootScreen />;
}

function labelForRole(role) {
  if (role === 'parent') return 'Co-parent';
  if (role === 'helper') return 'Helper';
  if (role === 'viewer') return 'Viewer';
  return role || 'Member';
}

function GoogleG() {
  return (
    <svg width="20" height="20" viewBox="0 0 48 48" aria-hidden="true">
      <path fill="#FFC107" d="M43.6 20.5H42V20H24v8h11.3c-1.6 4.7-6 8-11.3 8-6.6 0-12-5.4-12-12s5.4-12 12-12c3 0 5.8 1.1 7.9 3l5.7-5.7C34 6.1 29.3 4 24 4 12.9 4 4 12.9 4 24s8.9 20 20 20 20-8.9 20-20c0-1.3-.1-2.4-.4-3.5z"/>
      <path fill="#FF3D00" d="M6.3 14.7l6.6 4.8C14.7 16 19 13 24 13c3 0 5.8 1.1 7.9 3l5.7-5.7C34 6.1 29.3 4 24 4 16.3 4 9.7 8.3 6.3 14.7z"/>
      <path fill="#4CAF50" d="M24 44c5.2 0 9.9-2 13.4-5.3l-6.2-5.2c-2 1.5-4.5 2.5-7.2 2.5-5.3 0-9.7-3.3-11.3-8L6.2 33C9.5 39.5 16.2 44 24 44z"/>
      <path fill="#1976D2" d="M43.6 20.5H42V20H24v8h11.3c-.8 2.2-2.2 4.1-4 5.5l6.2 5.2C41.4 35.6 44 30.2 44 24c0-1.3-.1-2.4-.4-3.5z"/>
    </svg>
  );
}

function MainApp() {
  const [route, nav] = useHashRoute('dashboard');
  const [menuOpen, setMenuOpen] = React.useState(false);

  const kidDetailMatch = route.match(/^kid\/(.+)$/);
  const screen = kidDetailMatch ? 'kid' : route;
  const kidDetailId = kidDetailMatch ? kidDetailMatch[1] : null;

  // The "+ Add kid" flow: render the Onboarding step "Your kid" + "Tasks"
  // without the topbar, so it feels like a focused flow.
  if (screen === 'add-kid') {
    return <window.Onboarding accent="mango" skipSignIn startStep={1} mode="add-kid" />;
  }

  return (
    <div className="app">
      <TopBar route={route} nav={nav} menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
      <main>
        {screen === 'dashboard' && <window.Dashboard onOpenKid={(id) => nav('kid/' + id)} />}
        {screen === 'kidview'   && <window.KidView />}
        {screen === 'kid'       && <window.KidDetail kidId={kidDetailId} onBack={() => nav('dashboard')} />}
        {screen === 'tasks'     && <window.TaskManager />}
        {screen === 'share'     && <window.ShareScreen />}
      </main>
    </div>
  );
}

function TopBar({ route, nav, menuOpen, setMenuOpen }) {
  const s = useStore();
  const meta = (s.user && s.user.user_metadata) || {};
  const displayName = meta.full_name || meta.name || s.user?.email || 'Signed in';
  const email = s.user?.email || '';
  const initial = (displayName || '?').trim().charAt(0).toUpperCase();

  return (
    <>
      <nav className="screen-switcher">
        <div className="brand" style={{ cursor: 'pointer' }} onClick={() => nav('dashboard')}>
          <span className="brand-mark">s</span>
          sirisora
        </div>

        <div className="screen-tabs">
          {ROUTES.map(r => (
            <button key={r.id}
              className={`screen-tab ${route === r.id ? 'active' : ''}`}
              onClick={() => nav(r.id)}>
              {r.label}
            </button>
          ))}
        </div>

        <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 16, position: 'relative', minWidth: 0 }}>
          <span className="family-sticker" title={s.household?.name || 'My Family'}>
            <span className="family-sticker-emoji" aria-hidden="true">♥</span>
            <FamilyName text={s.household?.name || 'My Family'} />
          </span>
          <button onClick={() => setMenuOpen(o => !o)} aria-label="Account menu" style={{
            width: 38, height: 38, borderRadius: '50%',
            background: 'var(--periwinkle-soft)', color: 'var(--periwinkle-deep)',
            fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 15,
            display: 'grid', placeItems: 'center',
            border: '1.5px solid var(--rule-strong)',
          }}>{initial}</button>

          {menuOpen && (
            <div style={{
              position: 'absolute', top: 50, right: 0,
              background: 'var(--paper-2)', borderRadius: 16,
              boxShadow: 'var(--shadow-2)', padding: 14, minWidth: 240, zIndex: 100,
              border: '1px solid var(--rule)',
              fontFamily: 'var(--font-body)',
            }}>
              <div style={{ padding: '4px 6px 12px', borderBottom: '1px solid var(--rule)', marginBottom: 8 }}>
                <div style={{ fontWeight: 700, fontSize: 14, color: 'var(--ink)' }}>{displayName}</div>
                <div style={{ fontSize: 12, color: 'var(--ink-soft)', wordBreak: 'break-all' }}>{email}</div>
              </div>
              <button onClick={async () => { setMenuOpen(false); await s.signOut(); }} style={{
                display: 'block', width: '100%', textAlign: 'left',
                padding: '10px 8px', borderRadius: 8,
                color: 'var(--alert)', fontWeight: 600, fontSize: 14,
                fontFamily: 'inherit', cursor: 'pointer', background: 'transparent',
              }}>Sign out</button>
            </div>
          )}
        </div>
      </nav>
    </>
  );
}

function DevBanner() {
  return (
    <div style={{
      background: 'var(--berry-soft, #fde8f0)',
      color: 'var(--berry-deep, #9b2c5f)',
      textAlign: 'center',
      padding: '6px 12px',
      fontFamily: 'var(--font-body)',
      fontSize: 12,
      fontWeight: 700,
      letterSpacing: '0.3px',
      borderBottom: '1px solid var(--rule)',
    }}>
      Dev database — safe to experiment
    </div>
  );
}

function BootScreen() {
  const ACTS = [
    { mood: 'wave',  msg: 'Hoot hoot!',       anim: 'boot-idle',  shades: false },
    { mood: 'dance', msg: 'Getting ready…',   anim: 'boot-dance', shades: false },
    { mood: 'kiss',  msg: 'Muah! 💋',         anim: 'boot-kiss',  shades: false },
    { mood: 'wink',  msg: 'Looking cool!',    anim: 'boot-cool',  shades: true  },
    { mood: 'cheer', msg: 'Jump jump!',       anim: 'boot-jump',  shades: false },
    { mood: 'happy', msg: 'Welcome!',         anim: 'boot-welcome', shades: false },
  ];
  const DURATIONS = [800, 1100, 900, 1000, 900, 1400];

  const [step, setStep] = React.useState(0);
  const welcomed = React.useRef(false);
  const act = ACTS[step];

  React.useEffect(() => {
    const ms = DURATIONS[step] ?? 900;
    const t = setTimeout(() => {
      if (step === ACTS.length - 1) {
        if (!welcomed.current && window.sprinkleStars) {
          welcomed.current = true;
          window.sprinkleStars({ count: 28, duration: 2000 });
        }
        setStep(0);
      } else {
        setStep(step + 1);
      }
    }, ms);
    return () => clearTimeout(t);
  }, [step]);

  return (
    <div className="boot-screen">
      <div className="boot-sparkle s1" aria-hidden="true">✨</div>
      <div className="boot-sparkle s2" aria-hidden="true">⭐</div>
      <div className="boot-sparkle s3" aria-hidden="true">✨</div>
      <div className="boot-screen-inner">
        <div className={`boot-mascot-wrap ${act.anim}`} key={`m-${step}`}>
          <window.Suri
            mood={act.mood}
            size={168}
            color="#FF6B2C"
            wave={act.mood === 'wave'}
          />
          {act.shades && <div className="boot-shades" aria-hidden="true">🕶️</div>}
        </div>
        <div className="boot-bubble pop-in" key={`b-${step}`}>
          <window.SuriBubble>{act.msg}</window.SuriBubble>
        </div>
      </div>
    </div>
  );
}

function ErrorScreen({ message }) {
  return (
    <div style={{
      position: 'fixed', inset: 0,
      display: 'flex', flexDirection: 'column',
      alignItems: 'center', justifyContent: 'center',
      gap: 16, background: 'var(--paper)',
      padding: 32, textAlign: 'center',
      fontFamily: 'var(--font-body)',
    }}>
      <div style={{ fontSize: 56 }}>😕</div>
      <div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 24, color: 'var(--ink)' }}>
        Something went wrong
      </div>
      <div style={{ maxWidth: 420, color: 'var(--ink-soft)' }}>
        {message || 'Please refresh and try again.'}
      </div>
      <button onClick={() => window.location.reload()} className="btn btn-primary" style={{ marginTop: 12 }}>
        Refresh
      </button>
    </div>
  );
}

// Renders the family name in chunky Lilita One (same as the big "stars"
// headline) in solid mango orange — keeps the topbar to the same
// orange + white palette as the brand mark.
function FamilyName({ text }) {
  return (
    <span className="family-sticker-text" aria-label={text}>{text}</span>
  );
}

function SiteFooter() {
  const linkStyle = {
    color: 'var(--ink-soft)',
    textDecoration: 'none',
    margin: '0 10px',
    fontFamily: 'var(--font-body)',
    fontSize: 13,
  };
  return (
    <footer style={{
      borderTop: '1px solid var(--rule)',
      padding: '20px 24px 28px',
      textAlign: 'center',
      color: 'var(--ink-faint)',
      fontFamily: 'var(--font-body)',
      fontSize: 13,
      background: 'var(--paper)',
    }}>
      <div>
        <a href="/privacy.html" style={linkStyle}>Privacy</a>
        <span style={{ color: 'var(--rule-strong)' }}>·</span>
        <a href="/terms.html" style={linkStyle}>Terms</a>
        <span style={{ color: 'var(--rule-strong)' }}>·</span>
        <a href="mailto:hello@sirisora.com" style={linkStyle}>Contact</a>
      </div>
      <div style={{ marginTop: 8 }}>&copy; {new Date().getFullYear()} Sirisora</div>
    </footer>
  );
}

function App() {
  const showDevBanner = window.APP_CONFIG?.ENV === 'development';
  return (
    <StoreProvider>
      {showDevBanner && <DevBanner />}
      <AppShell />
      <SiteFooter />
    </StoreProvider>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
