// proto_theme.jsx — theme system (tweak-driven) + ThemeContext + shared components
const ThemeContext = React.createContext(null);
const useTheme = () => React.useContext(ThemeContext);

// palette presets: each gives A & B base hue/chroma
const PALETTES = {
  '暖橙珊瑚': { aH: 45, aC: 0.165, bH: 12, bC: 0.135 },
  '清新绿':   { aH: 152, aC: 0.13, bH: 195, bC: 0.10 },
  '天空蓝':   { aH: 245, aC: 0.13, bH: 285, bC: 0.11 },
  '粉紫':     { aH: 350, aC: 0.13, bH: 300, bC: 0.12 },
  '莫兰迪':   { aH: 35, aC: 0.055, bH: 250, bC: 0.05 },
};
const FONTS = {
  '圆润': { ui: "system-ui, -apple-system, 'PingFang SC', 'Microsoft YaHei', 'Noto Sans SC', sans-serif", num: "'Baloo 2', system-ui, -apple-system, 'PingFang SC', sans-serif" },
  '经典': { ui: "'PingFang SC', -apple-system, system-ui, sans-serif", num: "'PingFang SC', -apple-system, system-ui" },
  '雅致': { ui: "'Noto Serif SC', Georgia, serif", num: "'Fraunces', 'Noto Serif SC', Georgia, serif" },
};

function makeTheme({ palette = '暖橙珊瑚', font = '圆润', radius = 24, dark = false } = {}) {
  const p = PALETTES[palette] || PALETTES['暖橙珊瑚'];
  const f = FONTS[font] || FONTS['圆润'];
  const ok = (l, c, h) => `oklch(${l} ${c} ${h})`;
  const person = (H, C) => dark ? {
    color: ok(0.70, C, H), deep: ok(0.78, C * 0.9, H), soft: ok(0.32, C * 0.4, H),
  } : {
    color: ok(0.685, C, H), deep: ok(0.575, C * 0.97, H - 3), soft: ok(0.945, Math.min(C * 0.36, 0.05), H + 13),
  };
  const A = person(p.aH, p.aC), B = person(p.bH, p.bC);
  const base = dark ? {
    bg: ok(0.205, 0.012, p.aH), bg2: ok(0.255, 0.014, p.aH), card: ok(0.255, 0.012, p.aH),
    ink: ok(0.955, 0.008, p.aH), sub: ok(0.74, 0.018, p.aH), faint: ok(0.56, 0.02, p.aH),
    line: ok(0.33, 0.012, p.aH), shadow: '0 1px 2px rgba(0,0,0,0.3), 0 8px 26px rgba(0,0,0,0.35)',
    good: ok(0.74, 0.13, 152), goodS: ok(0.32, 0.06, 152), star: ok(0.82, 0.13, 85),
    deviceBg: '#0b0b0d',
  } : {
    bg: ok(0.985, 0.012, p.aH > 200 ? 70 : p.aH), bg2: ok(0.965, 0.016, p.aH > 200 ? 62 : p.aH), card: '#ffffff',
    ink: ok(0.32, 0.026, 50), sub: ok(0.555, 0.028, 52), faint: ok(0.72, 0.018, 60),
    line: ok(0.915, 0.014, 65), shadow: '0 1px 2px rgba(40,20,10,0.04), 0 6px 22px rgba(60,30,10,0.05)',
    good: ok(0.63, 0.13, 152), goodS: ok(0.95, 0.04, 152), star: ok(0.78, 0.13, 80),
    deviceBg: '#f3efe9',
  };
  return {
    ...base, A: { name: 'A', ...A }, B: { name: 'B', ...B },
    Ac: A.color, Ad: A.deep, As: A.soft, Bc: B.color, Bd: B.deep, Bs: B.soft,
    r: radius, rBtn: Math.max(12, radius * 0.62), rSm: Math.max(10, radius * 0.5),
    FONT: f.ui, NUM: f.num, dark,
  };
}

// ── App data/state context ───────────────────────────────────
const AppContext = React.createContext(null);
const useApp = () => React.useContext(AppContext);

// ── Avatar ───────────────────────────────────────────────────
function Avatar({ who, size = 44, ring = false, dim = false }) {
  const T = useTheme();
  const c = who === 'B' ? T.Bc : T.Ac, d = who === 'B' ? T.Bd : T.Ad;
  const { names } = useApp() || { names: { A: 'A', B: 'B' } };
  const label = (names[who] || who).slice(0, 1).toUpperCase();
  return (
    <div style={{
      width: size, height: size, borderRadius: '50%', flexShrink: 0,
      background: `linear-gradient(145deg, ${c}, ${d})`,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      color: '#fff', fontFamily: T.NUM, fontWeight: 700, fontSize: size * 0.44,
      boxShadow: ring ? `0 0 0 3px ${T.card}, 0 0 0 5.5px ${c}` : '0 2px 8px rgba(0,0,0,0.12)',
      opacity: dim ? 0.4 : 1,
    }}>{label}</div>
  );
}

// ── Ring ─────────────────────────────────────────────────────
function Ring({ pct, who = 'A', size = 168, stroke = 14, children }) {
  const T = useTheme();
  const color = who === 'B' ? T.Bc : T.Ac;
  const r = (size - stroke) / 2, c = 2 * Math.PI * r;
  const off = c * (1 - Math.max(0, Math.min(100, pct)) / 100);
  return (
    <div style={{ position: 'relative', width: size, height: size, flexShrink: 0 }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={T.line} strokeWidth={stroke} />
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={color} strokeWidth={stroke}
          strokeDasharray={c} strokeDashoffset={off} strokeLinecap="round"
          style={{ transition: 'stroke-dashoffset 0.9s cubic-bezier(.22,1,.36,1)' }} />
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>{children}</div>
    </div>
  );
}

// ── Sparkline ────────────────────────────────────────────────
function Sparkline({ data, who = 'A', w = 120, h = 38, fill = true }) {
  const T = useTheme();
  const color = who === 'B' ? T.Bc : T.Ac;
  if (!data || data.length < 2) {
    return <svg width={w} height={h} style={{ display: 'block' }}>
      <line x1="0" x2={w} y1={h/2} y2={h/2} stroke={T.line} strokeWidth="2" strokeDasharray="2 4" strokeLinecap="round" />
    </svg>;
  }
  const min = Math.min(...data), max = Math.max(...data), rng = (max - min) || 1;
  const pts = data.map((v, i) => [(i / (data.length - 1)) * w, h - 4 - ((v - min) / rng) * (h - 8)]);
  const d = pts.map((p, i) => `${i ? 'L' : 'M'}${p[0].toFixed(1)} ${p[1].toFixed(1)}`).join(' ');
  const id = 'sg' + Math.random().toString(36).slice(2, 7);
  return (
    <svg width={w} height={h} style={{ display: 'block' }}>
      {fill && <><defs><linearGradient id={id} x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stopColor={color} stopOpacity="0.22" /><stop offset="100%" stopColor={color} stopOpacity="0" />
      </linearGradient></defs>
      <path d={`${d} L${w} ${h} L0 ${h} Z`} fill={`url(#${id})`} /></>}
      <path d={d} fill="none" stroke={color} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
      <circle cx={pts[pts.length-1][0]} cy={pts[pts.length-1][1]} r="3.2" fill={color} stroke={T.card} strokeWidth="1.5" />
    </svg>
  );
}

// ── DualChart ────────────────────────────────────────────────
function DualChart({ a, b, days, goalA, w = 330, h = 188, showB = true }) {
  const T = useTheme();
  const padL = 6, padR = 6, padT = 12, padB = 22;
  const iw = w - padL - padR, ih = h - padT - padB;
  const aOK = a && a.length >= 2;
  const bOK = showB && b && b.length >= 2;
  if (!aOK && !bOK) {
    return (
      <div style={{ width: w, height: h, display: 'flex', alignItems: 'center', justifyContent: 'center', color: T.faint, fontSize: 13 }}>
        记录满 2 天后显示趋势曲线
      </div>
    );
  }
  const all = [...(aOK ? a : []), ...(bOK ? b : []), ...(goalA != null ? [goalA] : [])];
  let min = Math.min(...all), max = Math.max(...all);
  const pad = (max - min) * 0.12 || 1; min -= pad; max += pad;
  const rng = max - min;
  const X = (i, len) => padL + (i / (len - 1)) * iw;
  const Y = (v) => padT + (1 - (v - min) / rng) * ih;
  const path = (arr) => arr.map((v, i) => `${i ? 'L' : 'M'}${X(i, arr.length).toFixed(1)} ${Y(v).toFixed(1)}`).join(' ');
  const lastA = a[a.length-1], lastB = b[b.length-1];
  const ticks = [0, Math.floor((days.length-1)/2), days.length-1];
  const id = 'af' + Math.random().toString(36).slice(2, 6);
  return (
    <svg width={w} height={h} style={{ display: 'block', overflow: 'visible' }}>
      {[0.25, 0.5, 0.75].map((g, i) => (
        <line key={i} x1={padL} x2={w-padR} y1={padT+g*ih} y2={padT+g*ih} stroke={T.line} strokeWidth="1" strokeDasharray="2 4" />
      ))}
      {goalA != null && <>
        <line x1={padL} x2={w-padR} y1={Y(goalA)} y2={Y(goalA)} stroke={T.good} strokeWidth="1.5" strokeDasharray="5 4" opacity="0.85" />
        <text x={w-padR} y={Y(goalA)-5} textAnchor="end" fontFamily={T.NUM} fontSize="11" fontWeight="600" fill={T.good}>目标 {goalA}</text>
      </>}
      {bOK && <>
        <path d={`${path(b)} L${X(b.length-1,b.length)} ${padT+ih} L${padL} ${padT+ih} Z`} fill={T.Bc} opacity="0.05" />
        <path d={path(b)} fill="none" stroke={T.Bc} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.85" />
        <circle cx={X(b.length-1,b.length)} cy={Y(lastB)} r="4" fill={T.Bc} stroke={T.card} strokeWidth="2" />
      </>}
      <defs><linearGradient id={id} x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stopColor={T.Ac} stopOpacity="0.18" /><stop offset="100%" stopColor={T.Ac} stopOpacity="0" />
      </linearGradient></defs>
      {aOK && <>
        <path d={`${path(a)} L${X(a.length-1,a.length)} ${padT+ih} L${padL} ${padT+ih} Z`} fill={`url(#${id})`} />
        <path d={path(a)} fill="none" stroke={T.Ac} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
        <circle cx={X(a.length-1,a.length)} cy={Y(lastA)} r="4.5" fill={T.Ac} stroke={T.card} strokeWidth="2" />
      </>}
      {days.length > 1 && ticks.map((t, i) => (
        <text key={i} x={X(t, days.length)} y={h-5} textAnchor={i===0?'start':i===2?'end':'middle'} fontFamily={T.NUM} fontSize="11" fontWeight="500" fill={T.faint}>{days[t]}</text>
      ))}
    </svg>
  );
}

// ── icons ────────────────────────────────────────────────────
function Flame({ size = 16, color }) {
  const T = useTheme(); color = color || T.Ac;
  return (<svg width={size} height={size} viewBox="0 0 24 24" fill="none">
    <path d="M12 2c1 3-1 4.5-2.5 6.5C8 10.5 7 12 7 14a5 5 0 0010 0c0-2.5-1.5-4-2.5-5.5C13.2 6.6 13.8 4.5 12 2z" fill={color} />
    <path d="M12 12c.6 1.2-.2 2-.9 2.8-.5.6-.9 1.2-.9 2a1.8 1.8 0 003.6 0c0-1-.6-1.7-1.1-2.4-.4-.6-.9-1.2-.7-2.4z" fill="#fff" opacity="0.85" />
  </svg>);
}
function Heart({ size = 16, color, filled = true }) {
  const T = useTheme(); color = color || T.Bc;
  return (<svg width={size} height={size} viewBox="0 0 24 24" fill={filled ? color : 'none'} stroke={color} strokeWidth="2">
    <path d="M12 21s-7.5-4.6-10-9.3C0.3 8.4 1.8 4.5 5.3 4.5c2 0 3.3 1.2 4.7 3 1.4-1.8 2.7-3 4.7-3 3.5 0 5 3.9 3.3 7.2C19.5 16.4 12 21 12 21z" />
  </svg>);
}

// ── TabBar ───────────────────────────────────────────────────
function TabBar({ active, onNav, onPlus }) {
  const T = useTheme();
  const accent = T.Ac, faint = T.faint;
  const icons = {
    home: (a) => <path d="M3 11.5 12 4l9 7.5M5.5 9.8V20h13V9.8" stroke={a?accent:faint} strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"/>,
    trend: (a) => <path d="M4 19V5M4 19h16M8 16v-4M12 16V8M16 16v-7" stroke={a?accent:faint} strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"/>,
    eye: (a) => <><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z" stroke={a?accent:faint} strokeWidth="2" fill="none"/><circle cx="12" cy="12" r="2.5" stroke={a?accent:faint} strokeWidth="2" fill="none"/></>,
    me: (a) => <><circle cx="12" cy="8" r="3.5" stroke={a?accent:faint} strokeWidth="2" fill="none"/><path d="M5 20c0-3.5 3-6 7-6s7 2.5 7 6" stroke={a?accent:faint} strokeWidth="2" fill="none" strokeLinecap="round"/></>,
  };
  const items = [['home','首页'],['trend','趋势'],['__plus__'],['eye','监督'],['me','我的']];
  return (
    <div style={{ flexShrink: 0, display: 'flex', alignItems: 'flex-start', justifyContent: 'space-around', padding: '10px 8px 26px', background: T.dark ? 'rgba(30,28,30,0.86)' : 'rgba(255,255,255,0.92)', backdropFilter: 'blur(16px)', WebkitBackdropFilter: 'blur(16px)', borderTop: `1px solid ${T.line}`, position: 'relative' }}>
      {items.map((it) => {
        if (it[0] === '__plus__') return (
          <button key="plus" onClick={onPlus} style={{ width: 54, height: 54, borderRadius: '50%', border: 'none', marginTop: -22, background: `linear-gradient(145deg, ${T.Ac}, ${T.Ad})`, cursor: 'pointer', boxShadow: `0 6px 16px ${T.dark?'rgba(0,0,0,0.5)':'rgba(200,90,40,0.34)'}`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <svg width="26" height="26" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14" stroke="#fff" strokeWidth="2.6" strokeLinecap="round"/></svg>
          </button>
        );
        const a = active === it[0];
        return (
          <button key={it[0]} onClick={() => onNav(it[0])} style={{ background: 'none', border: 'none', cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3, width: 52, paddingTop: 2 }}>
            <svg width="24" height="24" viewBox="0 0 24 24">{icons[it[0]](a)}</svg>
            <span style={{ fontFamily: T.FONT, fontSize: 10.5, fontWeight: a ? 700 : 500, color: a ? accent : faint }}>{it[1]}</span>
          </button>
        );
      })}
    </div>
  );
}

// ── Toast ────────────────────────────────────────────────────
function Toast({ show, children }) {
  const T = useTheme();
  return (<div style={{ position: 'absolute', left: '50%', bottom: 100, transform: `translateX(-50%) translateY(${show?0:12}px)`, background: T.dark ? '#fff' : T.ink, color: T.dark ? T.ink : '#fff', padding: '11px 20px', borderRadius: 14, fontFamily: T.FONT, fontSize: 14, fontWeight: 600, whiteSpace: 'nowrap', zIndex: 200, pointerEvents: 'none', opacity: show ? 1 : 0, transition: 'all .3s cubic-bezier(.22,1,.36,1)', boxShadow: '0 8px 24px rgba(0,0,0,0.25)' }}>{children}</div>);
}

// ── Header (greeting/back) ───────────────────────────────────
function PageTitle({ title, sub, right }) {
  const T = useTheme();
  return (
    <div style={{ padding: '58px 20px 6px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexShrink: 0 }}>
      <div>
        <div style={{ fontSize: 22, fontWeight: 700, color: T.ink }}>{title}</div>
        {sub && <div style={{ fontSize: 13, color: T.sub, marginTop: 2, whiteSpace: 'nowrap' }}>{sub}</div>}
      </div>
      {right}
    </div>
  );
}

Object.assign(window, { ThemeContext, useTheme, makeTheme, PALETTES, FONTS, AppContext, useApp, Avatar, Ring, Sparkline, DualChart, Flame, Heart, TabBar, Toast, PageTitle });
