/* ============================================================
   Profile — account, subscription and app management.
   ============================================================ */
(function () {
  const { useState, useEffect } = React;

  const RED = 'oklch(0.58 0.17 25)';
  function getPref(k, d) { try { return localStorage.getItem('pref_' + k) || d; } catch (e) { return d; } }
  function setPref(k, v) { try { localStorage.setItem('pref_' + k, v); } catch (e) {} }

  // 2026-06-05 7:25PM — DB helpers for the profile section (doc 04 §3.6). PENDING USER TESTING
  const sb = () => window.sb;
  async function uid() {
    try { const { data } = await sb().auth.getUser(); return data && data.user ? data.user.id : null; }
    catch (e) { return null; }
  }
  // map theme value <-> label
  const THEME_LABEL = { light: 'Light', dark: 'Dark', system: 'System' };
  const LABEL_THEME = { Light: 'light', Dark: 'dark', System: 'system' };
  const GOAL_LABEL = { 5: '5 min', 10: '10 min', 15: '15 min', 30: '30 min' };
  const LABEL_GOAL = { '5 min': 5, '10 min': 10, '15 min': 15, '30 min': 30 };
  const ICONS = {
    person:(<React.Fragment><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 4-6 8-6s8 2 8 6"/></React.Fragment>),
    mail:(<React.Fragment><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></React.Fragment>),
    lock:(<React.Fragment><rect x="5" y="11" width="14" height="9" rx="2"/><path d="M8 11V8a4 4 0 018 0v3"/></React.Fragment>),
    globe:(<React.Fragment><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c3 3 3 15 0 18M12 3c-3 3-3 15 0 18"/></React.Fragment>),
    card:(<React.Fragment><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 10h18"/></React.Fragment>),
    receipt:(<path d="M6 3h12v18l-2-1.5-2 1.5-2-1.5-2 1.5-2-1.5L6 21zM9 8h6M9 12h6"/>),
    gift:(<React.Fragment><rect x="4" y="9" width="16" height="11" rx="1"/><path d="M4 9h16M12 9v11"/><path d="M12 9c-2 0-4-1-4-2.5S10 5 12 9c2-4 4-3 4-1.5S14 9 12 9z"/></React.Fragment>),
    target:(<React.Fragment><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="3"/></React.Fragment>),
    bell:(<path d="M6 9a6 6 0 0112 0c0 5 2 6 2 6H4s2-1 2-6M10 20a2 2 0 004 0"/>),
    speaker:(<path d="M4 9v6h4l5 4V5L8 9H4zM16 9a4 4 0 010 6"/>),
    download:(<path d="M12 4v10m0 0l-4-4m4 4l4-4M5 19h14"/>),
    sun:(<React.Fragment><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2M5 5l1.5 1.5M17.5 17.5L19 19M5 19l1.5-1.5M17.5 6.5L19 5"/></React.Fragment>),
    wave:(<path d="M3 12h2l2-5 3 12 3-9 2 4h6"/>),
    help:(<React.Fragment><circle cx="12" cy="12" r="9"/><path d="M9.5 9.2a2.5 2.5 0 113.5 2.3c-.8.4-1 .9-1 1.8M12 16.5h.01"/></React.Fragment>),
    message:(<path d="M4 5h16v11H9l-4 3v-3H4z"/>),
    heart:(<path d="M12 20s-7-4.5-7-9.5A3.5 3.5 0 0112 7a3.5 3.5 0 017 3.5C19 15.5 12 20 12 20z"/>),
    doc:(<React.Fragment><rect x="5" y="3" width="14" height="18" rx="2"/><path d="M8 8h8M8 12h8M8 16h5"/></React.Fragment>),
    shield:(<path d="M12 3l8 3v6c0 5-4 8-8 9-4-1-8-4-8-9V6z"/>),
  };

  function Icon({ name, bg }) {
    return (
      <div style={{ width:29, height:29, borderRadius:8, background:bg, flexShrink:0,
        display:'flex', alignItems:'center', justifyContent:'center' }}>
        <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2"
          strokeLinecap="round" strokeLinejoin="round">{ICONS[name]}</svg>
      </div>
    );
  }

  function Switch({ on, onToggle }) {
    return (
      <button onClick={(e) => { e.stopPropagation(); onToggle(); }}
        style={{ appearance:'none', border:'none', cursor:'pointer', width:46, height:28, borderRadius:999,
          background: on ? 'oklch(0.60 0.13 150)' : 'var(--line)', padding:2, transition:'background .2s', flexShrink:0 }}>
        <div style={{ width:24, height:24, borderRadius:999, background:'#fff',
          transform: on ? 'translateX(18px)' : 'translateX(0)', transition:'transform .2s',
          boxShadow:'0 1px 3px rgba(0,0,0,0.25)' }} />
      </button>
    );
  }

  function Row({ icon, bg, label, value, toggle, onToggle, onClick, last, danger }) {
    return (
      <div onClick={onClick} style={{ display:'flex', alignItems:'center', gap:12, padding:'11px 14px',
        cursor: onClick ? 'pointer' : 'default', position:'relative' }}>
        {icon && <Icon name={icon} bg={bg} />}
        <span style={{ flex:1, fontFamily:'"Hanken Grotesk",system-ui', fontWeight:650, fontSize:15,
          color: danger ? RED : 'var(--ink)' }}>{label}</span>
        {value && <span style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:14, color:'var(--muted)' }}>{value}</span>}
        {toggle !== undefined ? <Switch on={toggle} onToggle={onToggle} />
          : (onClick && !danger && <svg width="8" height="14" viewBox="0 0 8 14"><path d="M1 1l6 6-6 6" stroke="var(--muted)" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>)}
        {!last && <div style={{ position:'absolute', left: icon ? 55 : 14, right:0, bottom:0, height:1, background:'var(--line)' }} />}
      </div>
    );
  }

  function Group({ header, children }) {
    return (
      <div style={{ marginBottom:22 }}>
        {header && <div style={{ fontFamily:'"JetBrains Mono",monospace', fontSize:10.5, fontWeight:600,
          letterSpacing:'0.12em', textTransform:'uppercase', color:'var(--muted)', padding:'0 6px 8px' }}>{header}</div>}
        <div style={{ background:'var(--surface)', border:'1px solid var(--line)', borderRadius:18, overflow:'hidden' }}>
          {children}
        </div>
      </div>
    );
  }

  function Profile({ nav }) {
    const L = window.APP.learner;
    const email = L.email || '';
    const shortEmail = email.length > 18 ? email.slice(0, 15) + '…' : (email || '—');
    const [plan, setPlan] = useState('annual'); // Go-Pro card toggle (display only)
    const [reminders, setReminders] = useState(true);
    const [sfx, setSfx] = useState(true);
    const [haptics, setHaptics] = useState(true);
    const [goalLabel, setGoalLabel] = useState(GOAL_LABEL[L.dayGoalMin] || '10 min');
    const [themeLabel, setThemeLabel] = useState('Light');
    const [stats, setStats] = useState({ words: 0, lessons: 0 });
    const [sub, setSub] = useState({ plan: 'free', status: 'active' });

    // Load real settings, stats, and subscription from the DB.
    useEffect(() => {
      let live = true;
      (async () => {
        const id = await uid();
        if (!id || !sb()) return;
        try {
          const [settings, words, lessons, subscription] = await Promise.all([
            sb().from('user_settings').select('daily_goal_minutes,theme,reminders_enabled,sound_effects_enabled,haptics_enabled').eq('user_id', id).maybeSingle(),
            sb().from('user_progress').select('id', { count: 'exact', head: true }).eq('user_id', id).eq('item_type', 'letter').eq('status', 'learned'),
            sb().from('user_progress').select('id', { count: 'exact', head: true }).eq('user_id', id).eq('item_type', 'lesson').eq('status', 'done'),
            sb().from('user_subscriptions').select('plan,status,billing_interval').eq('user_id', id).maybeSingle(),
          ]);
          if (!live) return;
          if (settings.error) console.error('[auth:profile] settings read', settings.error.message);
          if (words.error) console.error('[auth:profile] words count', words.error.message);
          if (lessons.error) console.error('[auth:profile] lessons count', lessons.error.message);
          if (subscription.error) console.error('[auth:profile] subscription read', subscription.error.message);
          const s = settings.data;
          if (s) {
            setReminders(!!s.reminders_enabled);
            setSfx(!!s.sound_effects_enabled);
            setHaptics(!!s.haptics_enabled);
            setGoalLabel(GOAL_LABEL[s.daily_goal_minutes] || '10 min');
            setThemeLabel(THEME_LABEL[s.theme] || 'Light');
          }
          // "Words learned" counts learned letters (the only word-grade progress we persist in v1).
          setStats({ words: words.count || 0, lessons: lessons.count || 0 });
          if (subscription.data) setSub(subscription.data);
        } catch (e) { console.error('[auth:profile] load error', e); }
      })();
      return () => { live = false; };
    }, []);

    // Persist a single user_settings flag (DB is source of truth when signed in).
    const saveFlag = async (col, val) => {
      const id = await uid();
      if (!id || !sb()) return;
      const { error } = await sb().from('user_settings').update({ [col]: val, updated_at: new Date().toISOString() }).eq('user_id', id);
      if (error) { alert('Could not save that setting: ' + error.message); }
    };
    const toggleReminders = () => { setReminders(v => { const nv = !v; saveFlag('reminders_enabled', nv); return nv; }); };
    const toggleSfx = () => { setSfx(v => { const nv = !v; saveFlag('sound_effects_enabled', nv); return nv; }); };
    const toggleHaptics = () => { setHaptics(v => { const nv = !v; saveFlag('haptics_enabled', nv); return nv; }); };

    const startTrial = () => { alert('Payments are launching soon — thanks for your interest in Pro!'); };

    const signOut = async () => {
      try {
        if (sb()) { const { error } = await sb().auth.signOut(); if (error) console.error('[auth:profile] signOut', error.message); }
      } catch (e) { console.error('[auth:profile] signOut error', e); }
      try { localStorage.removeItem('ru_merged_v1'); } catch (e) {}
      nav.home();
    };

    const planLabel = sub.plan === 'pro' ? 'Pro' : 'Free';
    const isPro = sub.plan === 'pro';

    return (
      <div style={{ minHeight:'100%', background:'var(--bg)' }}>
        {/* header */}
        <div style={{ padding:'50px 18px 0', display:'flex', alignItems:'center', justifyContent:'space-between', gap:12 }}>
          <div style={{ fontFamily:'"Bricolage Grotesque",system-ui', fontWeight:800, fontSize:22,
            color:'var(--ink)', letterSpacing:'-0.02em' }}>Profile</div>
          <IconBtn kind="close" onClick={nav.back} />
        </div>

        <div style={{ padding:'14px 18px 40px' }}>
          {/* identity */}
          <div style={{ display:'flex', alignItems:'center', gap:14, padding:'4px 4px 18px' }}>
            <div style={{ width:64, height:64, borderRadius:999, background:'var(--primary)', flexShrink:0,
              display:'flex', alignItems:'center', justifyContent:'center', boxShadow:'0 8px 20px -8px var(--primary)' }}>
              <span style={{ fontFamily:'"Bricolage Grotesque",system-ui', fontWeight:800, fontSize:28, color:'#fff' }}>{L.name[0]}</span>
            </div>
            <div style={{ flex:1, minWidth:0 }}>
              <div style={{ fontFamily:'"Bricolage Grotesque",system-ui', fontWeight:800, fontSize:21, color:'var(--ink)' }}>{L.fullName}</div>
              <div style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:13.5, color:'var(--muted)', marginTop:1 }}>{email}</div>
              <div style={{ display:'flex', alignItems:'center', gap:8, marginTop:7 }}>
                <Badge color="var(--primary-deep)" bg="var(--primary-wash)">Level {L.level}</Badge>
                <span style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:12, color:'var(--muted)' }}>Member since {L.memberSince || new Date().getFullYear()}</span>
              </div>
            </div>
          </div>

          {/* stats */}
          <div style={{ display:'flex', gap:10, marginBottom:22 }}>
            {[{ v:L.streak, l:'Day streak' }, { v:stats.words, l:'Words learned' }, { v:stats.lessons, l:'Lessons done' }].map((s, i) => (
              <div key={i} style={{ flex:1, background:'var(--surface)', border:'1px solid var(--line)', borderRadius:16, padding:'13px 8px', textAlign:'center' }}>
                <div style={{ fontFamily:'"Bricolage Grotesque",system-ui', fontWeight:800, fontSize:22, color:'var(--ink)' }}>{s.v}</div>
                <div style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:11, color:'var(--muted)', marginTop:1 }}>{s.l}</div>
              </div>
            ))}
          </div>

          {/* Pro subscription card */}
          <div style={{ background:'var(--ink)', borderRadius:22, padding:'20px 20px 18px', color:'#fff',
            marginBottom:22, position:'relative', overflow:'hidden' }}>
            <div style={{ position:'absolute', right:-40, top:-40, width:160, height:160, borderRadius:999,
              background:'var(--primary)', opacity:0.45, filter:'blur(10px)' }} />
            <div style={{ position:'relative' }}>
              <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:14 }}>
                <svg width="24" height="24" viewBox="0 0 24 24" fill="#fff" style={{ flexShrink:0 }}><path d="M12 3l2.6 6.3 6.8.5-5.2 4.4 1.6 6.6L12 17.8 6.2 21.3l1.6-6.6L2.6 9.8l6.8-.5z"/></svg>
                <div style={{ minWidth:0 }}>
                  <div style={{ fontFamily:'"Bricolage Grotesque",system-ui', fontWeight:800, fontSize:21, lineHeight:1 }}>Go Pro</div>
                  <div style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:11.5, color:'rgba(255,255,255,0.65)', marginTop:3, whiteSpace:'nowrap' }}>Everything in Russian Learning App</div>
                </div>
              </div>
              <div style={{ display:'flex', flexDirection:'column', gap:9, marginBottom:16 }}>
                {['Unlimited smart review', 'Offline mode', 'Live conversation', 'Personal weekly coach'].map(f => (
                  <div key={f} style={{ display:'flex', alignItems:'center', gap:9 }}>
                    <svg width="16" height="16" viewBox="0 0 24 24" style={{ flexShrink:0 }}><path d="M5 13l4 4 10-11" stroke="var(--primary)" strokeWidth="3" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
                    <span style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:13.5, whiteSpace:'nowrap', color:'rgba(255,255,255,0.92)' }}>{f}</span>
                  </div>
                ))}
              </div>
              {/* plan toggle */}
              <div style={{ display:'flex', gap:10, marginBottom:14 }}>
                {[{ id:'annual', t:'Annual', p:'$59.99/yr', tag:'Save 50%' }, { id:'monthly', t:'Monthly', p:'$9.99/mo' }].map(o => (
                  <button key={o.id} onClick={() => setPlan(o.id)}
                    style={{ appearance:'none', cursor:'pointer', flex:1, textAlign:'left', borderRadius:14, padding:'11px 13px',
                      background: plan === o.id ? 'rgba(255,255,255,0.12)' : 'transparent',
                      border:`1.5px solid ${plan === o.id ? 'var(--primary)' : 'rgba(255,255,255,0.2)'}`, position:'relative' }}>
                    {o.tag && <span style={{ position:'absolute', top:-9, right:10, background:'var(--primary)', color:'#fff',
                      fontFamily:'"Hanken Grotesk",system-ui', fontWeight:800, fontSize:9.5, padding:'2px 7px', borderRadius:999 }}>{o.tag}</span>}
                    <div style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:800, fontSize:14, color:'#fff' }}>{o.t}</div>
                    <div style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:12.5, color:'rgba(255,255,255,0.7)', marginTop:1 }}>{o.p}</div>
                  </button>
                ))}
              </div>
              <button onClick={startTrial} style={{ appearance:'none', border:'none', cursor:'pointer', width:'100%', borderRadius:14, padding:'14px',
                background:'var(--primary)', color:'#fff', fontFamily:'"Hanken Grotesk",system-ui', fontWeight:800, fontSize:15.5 }}>
                {isPro ? 'Manage subscription' : 'Start 7-day free trial'}
              </button>
              <div style={{ textAlign:'center', fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:11,
                color:'rgba(255,255,255,0.55)', marginTop:9 }}>
                {isPro ? 'You’re on Pro · thank you' : `Then ${plan === 'annual' ? '$59.99/year' : '$9.99/month'} · cancel anytime`}
              </div>
            </div>
          </div>

          <Group header="Account">
            <Row icon="person" bg="oklch(0.66 0.17 38)" label="Edit profile" onClick={() => nav.go('profile-edit')} />
            <Row icon="mail" bg="oklch(0.62 0.12 250)" label="Email" value={shortEmail} onClick={() => nav.go('profile-email')} />
            <Row icon="lock" bg="oklch(0.55 0.02 60)" label="Password & security" onClick={() => nav.go('profile-password')} last />
          </Group>

          <Group header="Subscription">
            <Row icon="star" bg="var(--primary)" label="Current plan" value={planLabel} onClick={() => {}} />
            <Row icon="card" bg="oklch(0.62 0.12 250)" label="Manage billing" onClick={startTrial} />
            <Row icon="receipt" bg="oklch(0.55 0.02 60)" label="Purchase history" onClick={startTrial} />
            <Row icon="gift" bg="oklch(0.64 0.10 195)" label="Redeem a code" onClick={startTrial} last />
          </Group>

          <Group header="Learning">
            <Row icon="target" bg="oklch(0.78 0.13 72)" label="Daily goal" value={goalLabel} onClick={() => nav.go('profile-goal')} />
            <Row icon="bell" bg="oklch(0.66 0.17 38)" label="Reminders" toggle={reminders} onToggle={toggleReminders} />
            <Row icon="speaker" bg="oklch(0.62 0.12 250)" label="Sound effects" toggle={sfx} onToggle={toggleSfx} />
            <Row icon="download" bg="oklch(0.64 0.12 150)" label="Offline downloads" onClick={startTrial} last />
          </Group>

          <Group header="App">
            <Row icon="sun" bg="oklch(0.78 0.13 72)" label="Appearance" value={themeLabel} onClick={() => nav.go('profile-appearance')} />
            <Row icon="wave" bg="oklch(0.60 0.13 305)" label="Haptics" toggle={haptics} onToggle={toggleHaptics} last />
          </Group>

          <Group header="Support">
            <Row icon="help" bg="oklch(0.62 0.12 250)" label="Help center" onClick={() => {}} />
            <Row icon="message" bg="oklch(0.64 0.12 150)" label="Contact us" onClick={() => {}} />
            <Row icon="heart" bg="oklch(0.66 0.17 38)" label="Rate the app" onClick={() => {}} />
            <Row icon="doc" bg="oklch(0.55 0.02 60)" label="Terms of Service" onClick={() => {}} />
            <Row icon="shield" bg="oklch(0.64 0.10 195)" label="Privacy Policy" onClick={() => {}} last />
          </Group>

          <Group>
            <Row label="Sign out" danger onClick={signOut} last />
          </Group>

          <div style={{ textAlign:'center', fontFamily:'"JetBrains Mono",monospace', fontSize:11,
            color:'var(--muted)', paddingTop:6 }}>Russian Learning App · v1.0.0</div>
        </div>
      </div>
    );
  }

  /* ---- shared sub-page scaffolding ------------------------------ */
  function Sub({ title, nav, children, onSave, saveLabel = 'Save' }) {
    return (
      <div style={{ height:'100%', display:'flex', flexDirection:'column', background:'var(--bg)', position:'relative' }}>
        <div style={{ padding:'50px 18px 0', display:'flex', alignItems:'center', justifyContent:'space-between', gap:12 }}>
          <div style={{ fontFamily:'"Bricolage Grotesque",system-ui', fontWeight:800, fontSize:22,
            color:'var(--ink)', letterSpacing:'-0.02em' }}>{title}</div>
          <IconBtn kind="close" onClick={nav.back} />
        </div>
        <div style={{ flex:1, minHeight:0, overflowY:'auto', padding:'18px 20px 100px' }}>{children}</div>
        {onSave && (
          <div style={{ position:'absolute', left:0, right:0, bottom:0,
            padding:'12px 20px calc(20px + env(safe-area-inset-bottom))', borderTop:'1px solid var(--line)', background:'var(--bg)' }}>
            <Btn full onClick={onSave}>{saveLabel}</Btn>
          </div>
        )}
      </div>
    );
  }

  function Field({ label, value, onChange, type = 'text', placeholder, hint }) {
    return (
      <div style={{ marginBottom:16 }}>
        <label style={{ display:'block', fontFamily:'"Hanken Grotesk",system-ui', fontWeight:700, fontSize:12,
          color:'var(--muted)', padding:'0 4px 6px' }}>{label}</label>
        <input type={type} value={value} onChange={e => onChange(e.target.value)} placeholder={placeholder}
          style={{ width:'100%', boxSizing:'border-box', border:'1px solid var(--line)', borderRadius:14,
            padding:'13px 15px', background:'var(--surface)', fontFamily:'"Hanken Grotesk",system-ui',
            fontSize:16, fontWeight:600, color:'var(--ink)', outline:'none' }} />
        {hint && <div style={{ fontFamily:'"Hanken Grotesk",system-ui', fontSize:11.5, fontWeight:600,
          color:'var(--muted)', padding:'6px 4px 0' }}>{hint}</div>}
      </div>
    );
  }

  function RadioList({ options, value, onChange }) {
    return (
      <div style={{ background:'var(--surface)', border:'1px solid var(--line)', borderRadius:18, overflow:'hidden' }}>
        {options.map((o, i) => (
          <div key={o.id || o} onClick={() => onChange(o.id || o)}
            style={{ display:'flex', alignItems:'center', gap:10, padding:'14px', cursor:'pointer', position:'relative' }}>
            <div style={{ flex:1 }}>
              <div style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:700, fontSize:15.5, color:'var(--ink)' }}>{o.label || o}</div>
              {o.sub && <div style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:12.5, color:'var(--muted)', marginTop:1 }}>{o.sub}</div>}
            </div>
            {value === (o.id || o) && (
              <svg width="18" height="18" viewBox="0 0 24 24"><path d="M5 13l4 4 10-11" stroke="var(--primary)" strokeWidth="2.6" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
            )}
            {i < options.length - 1 && <div style={{ position:'absolute', left:14, right:0, bottom:0, height:1, background:'var(--line)' }} />}
          </div>
        ))}
      </div>
    );
  }

  /* ---- Edit profile --------------------------------------------- */
  function ProfileEdit({ nav }) {
    const L = window.APP.learner;
    const [first, setFirst] = useState((L.fullName || '').split(' ')[0] || '');
    const [last, setLast] = useState((L.fullName || '').split(' ').slice(1).join(' '));
    const [username, setUsername] = useState('');
    const [busy, setBusy] = useState(false);

    useEffect(() => {
      let live = true;
      (async () => {
        const id = await uid();
        if (!id || !sb()) return;
        const { data, error } = await sb().from('profiles').select('username').eq('id', id).maybeSingle();
        if (error) { console.error('[auth:profile] username read', error.message); return; }
        if (live && data && data.username) setUsername(data.username);
      })();
      return () => { live = false; };
    }, []);

    const save = async () => {
      const id = await uid();
      if (!id || !sb()) { nav.back(); return; }
      setBusy(true);
      const display_name = [first.trim(), last.trim()].filter(Boolean).join(' ') || first.trim() || 'Learner';
      const patch = { display_name, updated_at: new Date().toISOString() };
      const u = username.trim();
      if (u) patch.username = u;
      const { error } = await sb().from('profiles').update(patch).eq('id', id);
      setBusy(false);
      if (error) {
        alert(error.message && error.message.toLowerCase().includes('duplicate')
          ? 'That username is taken — try another.'
          : 'Could not save: ' + error.message);
        return;
      }
      if (nav.rehydrate) await nav.rehydrate();
      nav.back();
    };

    return (
      <Sub title="Edit profile" nav={nav} onSave={save} saveLabel={busy ? 'Saving…' : 'Save'}>
        <div style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:10, padding:'2px 0 22px' }}>
          <div style={{ width:84, height:84, borderRadius:999, background:'var(--primary)',
            display:'flex', alignItems:'center', justifyContent:'center', boxShadow:'0 10px 24px -10px var(--primary)' }}>
            <span style={{ fontFamily:'"Bricolage Grotesque",system-ui', fontWeight:800, fontSize:36, color:'#fff' }}>{(first[0] || 'L').toUpperCase()}</span>
          </div>
          <button style={{ appearance:'none', border:'none', background:'transparent', cursor:'pointer',
            fontFamily:'"Hanken Grotesk",system-ui', fontWeight:800, fontSize:13.5, color:'var(--primary-deep)' }}>Change photo</button>
        </div>
        <Field label="First name" value={first} onChange={setFirst} />
        <Field label="Last name" value={last} onChange={setLast} />
        <Field label="Username" value={username} onChange={setUsername} hint="This is how other learners see you." />
      </Sub>
    );
  }

  /* ---- Email ----------------------------------------------------- */
  function ProfileEmail({ nav }) {
    const L = window.APP.learner;
    const [email, setEmail] = useState(L.email || '');
    const [verified, setVerified] = useState(false);
    const [busy, setBusy] = useState(false);

    useEffect(() => {
      let live = true;
      (async () => {
        if (!sb()) return;
        const { data } = await sb().auth.getUser();
        if (live && data && data.user) setVerified(!!data.user.email_confirmed_at);
      })();
      return () => { live = false; };
    }, []);

    const save = async () => {
      if (!sb()) { nav.back(); return; }
      const e = email.trim();
      if (!e) { alert('Please enter an email address.'); return; }
      if (e === (L.email || '')) { nav.back(); return; }
      setBusy(true);
      const { error } = await sb().auth.updateUser({ email: e });
      setBusy(false);
      if (error) { alert('Could not update email: ' + error.message); return; }
      alert('Check your new inbox to confirm the change. Your email updates once confirmed.');
      nav.back();
    };

    return (
      <Sub title="Email" nav={nav} onSave={save} saveLabel={busy ? 'Updating…' : 'Update email'}>
        <div style={{ background:'var(--primary-wash)', borderRadius:14, padding:'13px 15px', marginBottom:18,
          fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:13, color:'var(--primary-deep)', lineHeight:1.4 }}>
          Your email is used to sign in and to recover your account.
        </div>
        <Field label="Email address" value={email} onChange={setEmail} type="email" />
        {verified ? (
          <div style={{ display:'flex', alignItems:'center', gap:8, padding:'2px 4px' }}>
            <div style={{ width:18, height:18, borderRadius:999, background:'oklch(0.60 0.13 150)',
              display:'flex', alignItems:'center', justifyContent:'center' }}>
              <svg width="11" height="11" viewBox="0 0 24 24"><path d="M5 13l4 4 10-11" stroke="#fff" strokeWidth="3" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
            </div>
            <span style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:700, fontSize:12.5, color:'oklch(0.50 0.12 150)' }}>Verified</span>
          </div>
        ) : (
          <div style={{ display:'flex', alignItems:'center', gap:8, padding:'2px 4px' }}>
            <span style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:700, fontSize:12.5, color:'var(--muted)' }}>Not yet confirmed</span>
          </div>
        )}
      </Sub>
    );
  }

  /* ---- Password & security -------------------------------------- */
  function ProfilePassword({ nav }) {
    const [cur, setCur] = useState('');
    const [nw, setNw] = useState('');
    const [conf, setConf] = useState('');
    const [twofa, setTwofa] = useState(false); // stub for v1 (Supabase MFA deferred)
    const [busy, setBusy] = useState(false);

    const save = async () => {
      if (!sb()) { nav.back(); return; }
      if (nw.length < 6) { alert('New password must be at least 6 characters.'); return; }
      if (nw !== conf) { alert('New passwords don’t match.'); return; }
      setBusy(true);
      const { error } = await sb().auth.updateUser({ password: nw });
      setBusy(false);
      if (error) { alert('Could not update password: ' + error.message); return; }
      alert('Password updated.');
      nav.back();
    };

    return (
      <Sub title="Password & security" nav={nav} onSave={save} saveLabel={busy ? 'Updating…' : 'Update password'}>
        <Field label="Current password" value={cur} onChange={setCur} type="password" placeholder="••••••••" />
        <Field label="New password" value={nw} onChange={setNw} type="password" placeholder="••••••••" hint="At least 8 characters, with a number." />
        <Field label="Confirm new password" value={conf} onChange={setConf} type="password" placeholder="••••••••" />
        <div style={{ fontFamily:'"JetBrains Mono",monospace', fontSize:10.5, fontWeight:600, letterSpacing:'0.12em',
          textTransform:'uppercase', color:'var(--muted)', padding:'8px 6px 8px' }}>Extra security</div>
        <div style={{ background:'var(--surface)', border:'1px solid var(--line)', borderRadius:18 }}>
          <Row icon="shield" bg="oklch(0.64 0.10 195)" label="Two-factor authentication" toggle={twofa} onToggle={() => setTwofa(v => !v)} last />
        </div>
      </Sub>
    );
  }

  /* ---- Appearance ------------------------------------------------ */
  function ProfileAppearance({ nav }) {
    const [val, setVal] = useState(getPref('appearance', 'Light')); // localStorage = offline cache
    useEffect(() => {
      let live = true;
      (async () => {
        const id = await uid(); if (!id || !sb()) return;
        const { data } = await sb().from('user_settings').select('theme').eq('user_id', id).maybeSingle();
        if (live && data && data.theme) { const lbl = THEME_LABEL[data.theme] || 'Light'; setVal(lbl); setPref('appearance', lbl); }
      })();
      return () => { live = false; };
    }, []);
    const choose = async (v) => {
      setVal(v); setPref('appearance', v); // optimistic + offline cache
      const id = await uid(); if (!id || !sb()) return;
      const { error } = await sb().from('user_settings').update({ theme: LABEL_THEME[v] || 'light', updated_at: new Date().toISOString() }).eq('user_id', id);
      if (error) alert('Could not save appearance: ' + error.message);
    };
    return (
      <Sub title="Appearance" nav={nav}>
        <RadioList value={val} onChange={choose}
          options={[{ id:'Light', label:'Light' }, { id:'Dark', label:'Dark' }, { id:'System', label:'System', sub:'Match your device' }]} />
        <div style={{ fontFamily:'"Hanken Grotesk",system-ui', fontSize:12, fontWeight:600, color:'var(--muted)',
          padding:'12px 6px' }}>Changes apply across the whole app.</div>
      </Sub>
    );
  }

  /* ---- Daily goal ------------------------------------------------ */
  function ProfileGoal({ nav }) {
    const [val, setVal] = useState(getPref('goal', '10 min')); // localStorage = offline cache
    useEffect(() => {
      let live = true;
      (async () => {
        const id = await uid(); if (!id || !sb()) return;
        const { data } = await sb().from('user_settings').select('daily_goal_minutes').eq('user_id', id).maybeSingle();
        if (live && data && data.daily_goal_minutes) { const lbl = GOAL_LABEL[data.daily_goal_minutes] || '10 min'; setVal(lbl); setPref('goal', lbl); }
      })();
      return () => { live = false; };
    }, []);
    const choose = async (v) => {
      setVal(v); setPref('goal', v); // optimistic + offline cache
      const id = await uid(); if (!id || !sb()) return;
      const mins = LABEL_GOAL[v] || 10;
      const { error } = await sb().from('user_settings').update({ daily_goal_minutes: mins, updated_at: new Date().toISOString() }).eq('user_id', id);
      if (error) { alert('Could not save goal: ' + error.message); return; }
      if (nav.rehydrate) await nav.rehydrate(); // ring uses dayGoalMin from learner
    };
    return (
      <Sub title="Daily goal" nav={nav}>
        <RadioList value={val} onChange={choose}
          options={[
            { id:'5 min', label:'Casual', sub:'5 min / day' },
            { id:'10 min', label:'Regular', sub:'10 min / day' },
            { id:'15 min', label:'Serious', sub:'15 min / day' },
            { id:'30 min', label:'Intense', sub:'30 min / day' },
          ]} />
      </Sub>
    );
  }

  Object.assign(window, { Profile, ProfileEdit, ProfileEmail, ProfilePassword, ProfileAppearance, ProfileGoal });
})();
