// app.jsx — root: role gate, server-backed state, router, theme wiring
const { useState, useEffect, useMemo, useCallback } = React;

// ── date helpers ─────────────────────────────────────────────
const WK = ['日', '一', '二', '三', '四', '五', '六'];
function greetWord(h) { return h < 11 ? '早上好' : h < 14 ? '中午好' : h < 18 ? '下午好' : '晚上好'; }
function toMD(iso) { const [, m, d] = iso.split('-'); return `${+m}/${+d}`; } // 'YYYY-MM-DD' -> 'M/D'
function dateStrOf(iso) {
  const [y, m, d] = iso.split('-').map(Number);
  const wk = new Date(y, m - 1, d).getDay();
  return `${m}月${d}日 星期${WK[wk]}`;
}
function weekLossOf(series) {
  if (!series.length) return 0;
  const last = series[series.length - 1];
  const ref = series.length >= 7 ? series[series.length - 7] : series[0];
  return +(ref - last).toFixed(1);
}

// ── role gate ────────────────────────────────────────────────
function RoleGate({ state, onPick }) {
  const T = useTheme();
  const [role, setRole] = useState(null);
  const [name, setName] = useState('');
  const pick = (r) => { setRole(r); setName(state[r].name || ''); };
  const confirm = () => { if (role) onPick(role, name.trim()); };

  const card = (r, c, d) => {
    const u = state[r];
    const cur = u.series.length ? u.series[u.series.length - 1] : null;
    const active = role === r;
    return (
      <button key={r} onClick={() => pick(r)} style={{
        flex: 1, border: active ? `2px solid ${c}` : `1.5px solid ${T.line}`,
        background: active ? (r === 'A' ? T.As : T.Bs) : T.card, borderRadius: T.r, padding: '20px 14px',
        cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10,
        boxShadow: active ? T.shadow : 'none', transition: 'all .2s',
      }}>
        <div style={{ width: 60, height: 60, borderRadius: '50%', background: `linear-gradient(145deg, ${c}, ${d})`, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontFamily: T.NUM, fontWeight: 800, fontSize: 26 }}>
          {(u.name || r).slice(0, 1).toUpperCase()}
        </div>
        <div style={{ fontSize: 15, fontWeight: 700, color: T.ink }}>{u.name || `用户 ${r}`}</div>
        <div style={{ fontFamily: T.NUM, fontSize: 12.5, color: T.sub }}>{cur != null ? `${cur}kg · 目标 ${u.goal}kg` : '还没有记录'}</div>
      </button>
    );
  };

  return (
    <div style={{ minHeight: '100dvh', background: T.bg, display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: '32px 24px', fontFamily: T.FONT, color: T.ink }}>
      <div style={{ textAlign: 'center', marginBottom: 28 }}>
        <div style={{ fontSize: 30, marginBottom: 8 }}>🏃‍♀️🏃‍♂️</div>
        <div style={{ fontSize: 24, fontWeight: 800 }}>双人减肥记录</div>
        <div style={{ fontSize: 14, color: T.sub, marginTop: 6 }}>选一个角色进入，和 TA 互相监督</div>
      </div>
      <div style={{ display: 'flex', gap: 14, marginBottom: 20 }}>
        {card('A', T.Ac, T.Ad)}
        {card('B', T.Bc, T.Bd)}
      </div>
      {role && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12, animation: 'fadeUp .3s' }}>
          <input value={name} onChange={(e) => setName(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && confirm()}
            placeholder="输入你的昵称（可留空）" maxLength={12}
            style={{ height: 50, borderRadius: T.rBtn, border: `1.5px solid ${T.line}`, background: T.card, padding: '0 18px', fontFamily: T.FONT, fontSize: 16, color: T.ink, outline: 'none' }} />
          <button onClick={confirm} style={{ height: 52, border: 'none', borderRadius: T.rBtn, cursor: 'pointer', background: `linear-gradient(135deg, ${role === 'A' ? T.Ac : T.Bc}, ${role === 'A' ? T.Ad : T.Bd})`, color: '#fff', fontFamily: T.FONT, fontSize: 16, fontWeight: 700 }}>
            进入
          </button>
        </div>
      )}
      <div style={{ textAlign: 'center', fontSize: 11.5, color: T.faint, marginTop: 24 }}>无需登录 · 数据保存在服务器</div>
    </div>
  );
}

function App() {
  const [role, setRole] = useState(() => localStorage.getItem('wt_role') || null);
  const [state, setState] = useState(null);
  const [err, setErr] = useState(null);
  const [tab, setTab] = useState('home');
  const [checkinOpen, setCheckinOpen] = useState(false);
  const [goalOpen, setGoalOpen] = useState(false);
  const [toast, setToast] = useState('');

  const refresh = useCallback(async () => {
    try { setState(await Api.get()); } catch (e) { setErr(e.message); }
  }, []);
  useEffect(() => { refresh(); }, [refresh]);

  const settings = state ? state.settings : { palette: '暖橙珊瑚', font: '圆润', radius: 24, dark: false };
  const theme = useMemo(() => makeTheme(settings), [settings.palette, settings.font, settings.radius, settings.dark]);

  const fire = useCallback((m) => { setToast(m); clearTimeout(window.__pt); window.__pt = setTimeout(() => setToast(''), 1900); }, []);

  // ── loading / error / gate ──
  if (err && !state) return <div style={{ padding: 40, fontFamily: 'system-ui', color: '#b00' }}>加载失败：{err}<br/>请确认后端已启动（node server.js）。</div>;
  if (!state) return <div style={{ padding: 40, fontFamily: 'system-ui', color: '#888' }}>加载中…</div>;

  if (!role) {
    return (
      <ThemeContext.Provider value={theme}>
        <RoleGate state={state} onPick={async (r, name) => {
          localStorage.setItem('wt_role', r);
          if (name) { try { setState(await Api.profile(r, name)); } catch (e) {} }
          setRole(r);
        }} />
      </ThemeContext.Provider>
    );
  }

  // ── perspective mapping: me -> 'A' slot, partner -> 'B' slot ──
  const partnerRole = role === 'A' ? 'B' : 'A';
  const meRaw = state[role], paRaw = state[partnerRole];
  const curOf = (u) => (u.series.length ? u.series[u.series.length - 1] : u.start);
  const me = {
    name: 'A', displayName: meRaw.name || '我', hasData: meRaw.series.length > 0,
    start: meRaw.start, cur: curOf(meRaw), goal: meRaw.goal, goal_min: meRaw.goal,
    series: meRaw.series, days: meRaw.days.map(toMD), streak: meRaw.streak, checkedToday: meRaw.checkedToday,
    weekLoss: weekLossOf(meRaw.series),
  };
  const partner = {
    name: 'B', displayName: paRaw.name || '队友', hasData: paRaw.series.length > 0,
    start: paRaw.start, cur: curOf(paRaw), goal: paRaw.goal,
    series: paRaw.series, days: paRaw.days.map(toMD), streak: paRaw.streak, checkedToday: paRaw.checkedToday,
    weekLoss: weekLossOf(paRaw.series),
  };
  const liked = !!state.reactions[partnerRole].likedBy;
  const now = new Date();

  // ── actions ──
  const doCheckin = async (val) => {
    const was = me.checkedToday;
    const ns = await Api.checkin(role, val); setState(ns);
    const st = ns[role].streak;
    fire(was ? '已更新今天的体重 ✓' : `打卡成功，连续 ${st} 天 🔥`);
  };
  const setGoalA = async (v) => { setState(await Api.goal(role, v)); fire(`目标已更新为 ${v}kg 🎯`); };
  const like = async () => { const r = await Api.like(role); setState(r); if (r.liked) fire(`给 ${partner.displayName} 点了个赞 ❤️`); };
  const poke = () => fire(partner.checkedToday ? `已夸 ${partner.displayName}，继续加油 👍` : `已戳一下 ${partner.displayName}，催 TA 打卡 👀`);
  const sendMessage = async (text) => { setState(await Api.message(role, text)); fire('留言已送达 💬'); };
  const updateSettings = async (patch) => { setState(await Api.settings({ ...settings, ...patch })); };
  const changeName = async (name) => { setState(await Api.profile(role, name)); fire('昵称已更新 ✓'); };
  const switchRole = () => { localStorage.removeItem('wt_role'); setRole(null); setTab('home'); };

  const badges = [
    { icon: '🎯', name: '首次打卡', got: me.series.length > 0 },
    { icon: '🔥', name: '连续7天', got: me.streak >= 7 },
    { icon: '⭐', name: '减5kg', got: (me.start - me.cur) >= 5 },
    { icon: '🏆', name: '达成目标', got: me.cur <= me.goal },
  ];

  const appValue = {
    role,
    A: me, B: partner,
    names: { A: me.displayName, B: partner.displayName },
    goal: { A: me.goal, B: partner.goal },
    checkedToday: me.checkedToday, liked, messages: state.messages, badges, settings,
    greet: greetWord(now.getHours()), dateStr: dateStrOf(state.today),
    fire, openCheckin: () => setCheckinOpen(true), openGoal: () => setGoalOpen(true),
    doCheckin, setGoalA, like, poke, sendMessage, updateSettings, changeName, switchRole,
  };

  const SCREENS = { home: HomeScreen, trend: TrendScreen, eye: SuperviseScreen, me: MeScreen };
  const Current = SCREENS[tab] || HomeScreen;

  return (
    <ThemeContext.Provider value={theme}>
      <AppContext.Provider value={appValue}>
        <div style={{ height: '100dvh', display: 'flex', flexDirection: 'column', background: theme.bg, fontFamily: theme.FONT, color: theme.ink, position: 'relative', overflow: 'hidden', maxWidth: 480, margin: '0 auto', boxShadow: '0 0 40px rgba(0,0,0,0.06)' }}>
          <div key={tab} style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
            <Current />
          </div>
          <TabBar active={tab} onNav={setTab} onPlus={() => setCheckinOpen(true)} />
          <CheckinSheet open={checkinOpen} onClose={() => setCheckinOpen(false)} />
          <GoalSheet open={goalOpen} onClose={() => setGoalOpen(false)} />
          <Toast show={!!toast}>{toast}</Toast>
        </div>
      </AppContext.Provider>
    </ThemeContext.Provider>
  );
}

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