/* global React */
// Login + Dashboard pages.

// Demo accounts: matched on the username portion before "@"
const DEMO_ACCOUNTS = {
  'admin':    { role: 'super-admin', name: '主管理员', email: 'admin@pokeking.icu' },
  'editor':   { role: 'editor',      name: '内容编辑', email: 'editor@pokeking.icu' },
  'reviewer': { role: 'reviewer',    name: '审核员',   email: 'reviewer@pokeking.icu' },
};

function LoginScreen({ onLogin }) {
  const [account, setAccount] = React.useState('admin');
  const [password, setPassword] = React.useState('');
  const [remember, setRemember] = React.useState(true);
  const [state, setState] = React.useState('idle'); // idle | submitting | error
  const [err, setErr] = React.useState('');

  const submit = async (e) => {
    e?.preventDefault?.();
    if (!account) { setErr('请输入账号'); setState('error'); return; }
    if (!password) { setErr('请输入密码'); setState('error'); return; }
    setState('submitting');
    setErr('');
    try {
      const r = await window.API.login(account.trim(), password);
      if (r?.user) {
        onLogin(r.user);
      } else {
        setState('error'); setErr('登录失败:返回数据异常');
      }
    } catch (e2) {
      setState('error');
      setErr(e2.status === 401 ? '账号或密码错误,请重试。' : `登录失败:${e2.message}`);
    }
  };

  return (
    <div className="login-wrap">
      {/* Left: art / brand panel */}
      <div className="login-art">
        <div className="hex-bg"/>
        <div className="hstack" style={{ position:'relative', gap: 10 }}>
          <window.Logo size={32}/>
          <div className="brand-text">
            <span className="name" style={{ fontSize: 16 }}>PokeKING</span>
            <span className="role">Admin Console</span>
          </div>
        </div>

        <div style={{ position:'relative', maxWidth: 520 }}>
          <div style={{ fontSize: 13, color: 'var(--text-2)', fontFamily: 'var(--font-mono)', letterSpacing: '.04em', marginBottom: 16 }}>
            INTERNAL TOOL · ADMIN ONLY
          </div>
          <h1 style={{ fontSize: 40, lineHeight: 1.1, fontWeight: 600, letterSpacing: '-.02em', marginBottom: 16 }}>
            一个面向管理员的<br/>
            数据与内容控制台。
          </h1>
          <p style={{ fontSize: 15, color: 'var(--text-2)', maxWidth: 460 }}>
            审核玩家提交、编辑阵容数据库、管理攻略与图鉴。
            所有变更先入暂存,经审计后由你按需发布到 manifest。
          </p>

          <div style={{ display:'flex', gap: 12, marginTop: 28, flexWrap:'wrap' }}>
            <div style={{ padding: '10px 14px', border:'1px solid var(--border)', borderRadius: 'var(--r-md)', background:'var(--surface)' }}>
              <div className="muted" style={{ fontSize: 11, fontFamily:'var(--font-mono)', textTransform:'uppercase', letterSpacing:'.08em' }}>当前版本</div>
              <div style={{ fontWeight: 600, marginTop: 4 }}>manifest v126</div>
            </div>
            <div style={{ padding: '10px 14px', border:'1px solid var(--border)', borderRadius: 'var(--r-md)', background:'var(--surface)' }}>
              <div className="muted" style={{ fontSize: 11, fontFamily:'var(--font-mono)', textTransform:'uppercase', letterSpacing:'.08em' }}>待审提交</div>
              <div style={{ fontWeight: 600, marginTop: 4 }}>4 条</div>
            </div>
            <div style={{ padding: '10px 14px', border:'1px solid var(--border)', borderRadius: 'var(--r-md)', background:'var(--surface)' }}>
              <div className="muted" style={{ fontSize: 11, fontFamily:'var(--font-mono)', textTransform:'uppercase', letterSpacing:'.08em' }}>暂存变更</div>
              <div style={{ fontWeight: 600, marginTop: 4 }}>5 条</div>
            </div>
          </div>
        </div>

        <div style={{ position:'relative', fontSize: 12, color: 'var(--text-3)', display:'flex', gap: 16 }}>
          <span>© 2026 PokeKING</span>
          <span>·</span>
          <span>部署于 Cloudflare Pages</span>
          <span>·</span>
          <span className="mono">build 126</span>
        </div>
      </div>

      {/* Right: form */}
      <div className="login-form-wrap">
        <form className="login-form" onSubmit={submit}>
          <div style={{ marginBottom: 28 }}>
            <h2 style={{ fontSize: 22, fontWeight: 600, letterSpacing: '-.01em' }}>登录到管理后台</h2>
            <p className="muted" style={{ marginTop: 6, fontSize: 13 }}>
              使用你的管理员账号登录。支持多角色权限。
            </p>
          </div>

          <label className="field" htmlFor="account">账号</label>
          <input id="account" type="text" placeholder="admin"
                 value={account} autoComplete="username"
                 onChange={(e) => { setAccount(e.target.value); if (state === 'error') setState('idle'); }}
                 className={`input ${state === 'error' ? 'error' : ''}`}
                 autoFocus/>

          <div className="hstack" style={{ marginTop: 14, justifyContent: 'space-between' }}>
            <label className="field" htmlFor="pw" style={{ margin: 0 }}>密码</label>
            <a className="mono" style={{ fontSize: 11, color: 'var(--text-3)' }}>忘记密码?</a>
          </div>
          <input id="pw" type="password" placeholder="••••••••••••••"
                 value={password} autoComplete="current-password"
                 onChange={(e) => { setPassword(e.target.value); if (state === 'error') setState('idle'); }}
                 className={`input ${state === 'error' ? 'error' : ''}`}
                 style={{ marginTop: 6 }}/>

          {state === 'error' && err && (
            <div style={{ marginTop: 8, color: 'var(--danger)', fontSize: 12, display:'flex', gap: 6, alignItems:'center' }}>
              <window.I.alert size={13}/> {err}
            </div>
          )}

          <label className="hstack" style={{ marginTop: 16, fontSize: 13, color: 'var(--text-2)', cursor:'pointer' }}>
            <input type="checkbox" checked={remember} onChange={(e) => setRemember(e.target.checked)}/>
            <span>30 天内保持登录</span>
          </label>

          <button type="submit" className="btn primary" disabled={state === 'submitting'}
                  style={{ width: '100%', marginTop: 24, height: 40, justifyContent: 'center' }}>
            {state === 'submitting' ? <><span className="spinner"/> 验证中</> : <>登录 <window.I.arrowR size={14}/></>}
          </button>

          {/* Future-reserved slots */}
          <div className="divider"/>
          <div className="muted" style={{ fontSize: 11, fontFamily:'var(--font-mono)', textTransform:'uppercase', letterSpacing:'.08em', marginBottom: 10 }}>即将上线</div>
          <div style={{ display:'flex', gap: 8 }}>
            <button type="button" className="btn" style={{ flex: 1, justifyContent:'center', opacity: .55 }} disabled>
              <window.I.shield size={14}/> 2FA
            </button>
            <button type="button" className="btn" style={{ flex: 1, justifyContent:'center', opacity: .55 }} disabled>
              GitHub OAuth
            </button>
          </div>

          {/* Demo hint — single line, no role-picker */}
          <div style={{
            marginTop: 18,
            fontSize: 11, color: 'var(--text-3)',
            fontFamily: 'var(--font-mono)',
            textAlign: 'center', lineHeight: 1.6,
          }}>
            演示账号: <b>admin</b> · <b>editor</b> · <b>reviewer</b><br/>
            任意密码 · 输 <b>wrong</b> 看错误态
          </div>
        </form>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────

function Dashboard({ user, role = 'super-admin', onNavigate, onOpenStaging }) {
  const isReviewer = role === 'reviewer';
  const isAdmin = role === 'super-admin';
  const name = user?.name || '管理员';
  const [pending, setPending] = React.useState([]);
  const [stats, setStats] = React.useState({ counts: { pending: 0, approved: 0, rejected: 0, merged: 0 }, today: 0, staging_pending: 0, feedback_new: 0 });

  React.useEffect(() => {
    window.API.submissions('pending', 5).then((r) => {
      if (r?.items) setPending(r.items.map(window.normalizeSubmission));
    }).catch(() => {});
    window.API.stats().then((s) => {
      if (s?.counts) setStats({ counts: s.counts, today: s.today || 0, staging_pending: s.staging_pending || 0, feedback_new: s.feedback_new || 0 });
    }).catch(() => {});
  }, []);

  const pendingCount = stats.counts.pending || 0;
  const greeting = isReviewer
    ? `${name},今天有 ${pendingCount} 条等你审核`
    : isAdmin
      ? `早安 ☕ 今天有 ${pendingCount} 条待审`
      : `${name},${stats.staging_pending} 条暂存待你处理`;

  return (
    <div>
      <div className="page-header">
        <div>
          <div className="breadcrumb"><span>工作区</span><span className="sep">/</span><span>仪表盘</span></div>
          <h1 className="page-title">{greeting}</h1>
          <div className="page-subtitle">
            {isReviewer
              ? <>你的视角是 <window.RolePill role="reviewer"/> · 仅审核 / 浏览权限</>
              : <>manifest v126 已发布 2 小时前 · 系统状态正常</>}
          </div>
        </div>
        <div className="hstack">
          {isAdmin && <window.Btn icon={<window.I.refresh size={14}/>}>立即抓取</window.Btn>}
          {!isReviewer && <window.Btn icon={<window.I.plus size={14}/>}>新建攻略</window.Btn>}
          {window.can(role, 'data', 'w') && (
            <window.Btn kind="primary" icon={<window.I.upload size={14}/>} onClick={onOpenStaging}>
              发布 staging (5)
            </window.Btn>
          )}
          {isReviewer && (
            <window.Btn kind="primary" icon={<window.I.check size={14}/>}
                        onClick={() => onNavigate('submissions')}>
              开始审核
            </window.Btn>
          )}
        </div>
      </div>

      {/* KPIs — set varies by role */}
      <div style={{ display:'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16, marginBottom: 32 }}>
        <Kpi label="待审提交" value={String(pendingCount)} foot={isReviewer ? '需要你审核' : '点击跳到审核台'} onClick={() => onNavigate('submissions')}/>
        {isReviewer ? (
          <>
            <Kpi label="本周已审" value="34" delta={{ kind: 'up', text: '上周 +6' }} foot="通过 22 · 驳回 12"/>
            <Kpi label="你的通过率" value="65%" delta={{ kind: 'flat', text: '团队平均 71%' }} foot="近 30 天"/>
            <Kpi label="平均处理时长"
                 render={() => (
                   <>
                     <div className="kpi-value">2.4<span style={{ fontSize: 14, color: 'var(--text-3)', marginLeft: 4 }}>分钟</span></div>
                     <div className="kpi-foot"><span className="delta down">↓ 上周 -0.6 分钟</span></div>
                   </>
                 )}/>
          </>
        ) : (
          <>
            <Kpi label="今日提交" value="9" delta={{ kind: 'down', text: '昨日 -3' }}
                 foot="过去 24 小时"/>
            <Kpi label="manifest 版本" value="v126" foot="2 小时前发布 · a1b2c3d" mono/>
            <Kpi label="D1 数据库占用"
                 render={() => (
                   <>
                     <div className="kpi-value">38<span style={{ fontSize: 14, color: 'var(--text-3)', marginLeft: 6 }}>/ 100 MB</span></div>
                     <div className="progress" style={{ marginTop: 8 }}>
                       <div className="fill" style={{ width: '38%' }}/>
                     </div>
                     <div className="kpi-foot">Cloudflare 免费额度 38% 已用</div>
                   </>
                 )}/>
          </>
        )}
      </div>

      {/* Middle row: pending list + activity */}
      <div style={{ display:'grid', gridTemplateColumns: '1.4fr 1fr', gap: 16 }}>
        {/* Pending */}
        <div className="card">
          <div className="card-header">
            <div className="hstack">
              <div className="card-title">待审提交</div>
              <span className="pill pending"><span className="dot"/>{pendingCount} 待处理</span>
            </div>
            <button className="btn ghost sm" onClick={() => onNavigate('submissions')}>
              查看全部 <window.I.arrowR size={12}/>
            </button>
          </div>
          {(pending.length ? pending : window.MOCK.SUBMISSIONS.filter((s) => s.status === 'pending')).slice(0, 4).map((s) => (
            <div key={s.id} style={{
              display:'flex', alignItems:'center', gap: 12,
              padding: '14px 20px',
              borderBottom: '1px solid var(--border)'
            }}>
              <span className="mono" style={{ color: 'var(--text-3)', fontSize: 12, minWidth: 36 }}>#{s.id}</span>
              <div style={{ display:'flex', gap: 4 }}>
                {s.team.slice(0, 6).map((p, i) => (
                  <window.Sprite key={i} name={p.name} color={p.color} size="sm"/>
                ))}
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 500 }}>{s.area_code} · {s.npc}</div>
                <div className="muted" style={{ fontSize: 12, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
                  {s.note || <span className="dim">无备注</span>}
                </div>
              </div>
              <div className="muted" style={{ fontSize: 12 }}>{relTime(s.created_at)}</div>
              <div className="hstack">
                <window.Btn size="sm" kind="success" icon={<window.I.check size={12}/>}
                            onClick={() => window.API.approve(s.id).then(() => window.API.submissions('pending', 5).then((r) => r?.items && setPending(r.items.map(window.normalizeSubmission))))}>通过</window.Btn>
                <window.Btn size="sm" kind="danger"  icon={<window.I.x size={12}/>}
                            onClick={() => onNavigate('submissions')}>驳回</window.Btn>
              </div>
            </div>
          ))}
        </div>

        {/* Activity timeline */}
        <div className="card">
          <div className="card-header">
            <div className="card-title">最近活动</div>
            <button className="btn ghost sm" onClick={() => onNavigate('audit')}>
              完整日志 <window.I.arrowR size={12}/>
            </button>
          </div>
          <div style={{ padding: '8px 20px 16px' }}>
            {window.MOCK.ACTIVITY.map((a, i) => (
              <div key={a.id} style={{ display:'flex', gap: 12, padding: '10px 0', position:'relative' }}>
                <div style={{ position:'relative', width: 16 }}>
                  <div style={{
                    width: 8, height: 8, borderRadius: '50%',
                    background: a.actor === 'system' ? 'var(--info)' : 'var(--indigo)',
                    marginTop: 6, marginLeft: 4
                  }}/>
                  {i < window.MOCK.ACTIVITY.length - 1 && (
                    <div style={{
                      position:'absolute', top: 16, bottom: -10, left: 7,
                      width: 1, background: 'var(--border)'
                    }}/>
                  )}
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 13 }}>
                    <span className="mono" style={{ color: 'var(--text-3)', fontSize: 11 }}>{a.actor}</span>
                    <span style={{ margin: '0 6px', color: 'var(--text-3)' }}>·</span>
                    {a.desc}
                  </div>
                  <div className="muted" style={{ fontSize: 11, marginTop: 2, fontFamily:'var(--font-mono)' }}>{a.at}</div>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* System status row — admin/editor only */}
      {!isReviewer && (
      <>
      <div className="section-head">
        <div className="h">系统状态</div>
        <button className="btn ghost sm" onClick={() => onNavigate('status')}>
          完整状态 <window.I.arrowR size={12}/>
        </button>
      </div>
      <div style={{ display:'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16 }}>
        <div className="card card-pad">
          <div className="hstack" style={{ justifyContent:'space-between' }}>
            <div className="muted" style={{ fontSize: 12 }}>最近抓取</div>
            <span className="pill approved"><span className="dot"/>成功</span>
          </div>
          <div style={{ fontSize: 18, fontWeight: 600, marginTop: 6 }}>cron-daily-12:00</div>
          <div className="muted" style={{ fontSize: 12, marginTop: 2 }}>
            +3 条 · ~1 条 · 耗时 138s · <span className="mono">a1b2c3d</span>
          </div>
        </div>
        <div className="card card-pad">
          <div className="hstack" style={{ justifyContent:'space-between' }}>
            <div className="muted" style={{ fontSize: 12 }}>Cloudflare 额度</div>
            <span className="pill"><span className="dot" style={{ background: 'var(--success)' }}/>正常</span>
          </div>
          <div style={{ display:'flex', gap: 16, marginTop: 10 }}>
            <Meter label="Requests" used={32} total={100000} unit="k"/>
            <Meter label="Workers" used={4.2} total={10} unit="M"/>
            <Meter label="D1" used={38} total={100} unit="MB"/>
          </div>
        </div>
        <div className="card card-pad">
          <div className="hstack" style={{ justifyContent:'space-between' }}>
            <div className="muted" style={{ fontSize: 12 }}>最近反馈</div>
            <span className="pill new"><span className="dot"/>2 新</span>
          </div>
          <div style={{ marginTop: 10 }}>
            {window.MOCK.FEEDBACK.slice(0, 2).map((f) => (
              <div key={f.id} style={{ padding: '6px 0', borderBottom: '1px solid var(--border)' }}>
                <div style={{ fontSize: 13, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
                  <span className="mono" style={{ color: 'var(--text-3)', fontSize: 11, marginRight: 6 }}>{f.kind}</span>
                  {f.title}
                </div>
                <div className="muted" style={{ fontSize: 11 }}>{f.at}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
      </>
      )}

      {/* Reviewer-specific section */}
      {isReviewer && (
        <>
          <div className="section-head">
            <div className="h">本周你的审核</div>
            <span className="muted" style={{ fontSize: 12 }}>过去 7 天</span>
          </div>
          <div style={{ display:'grid', gridTemplateColumns: '1.4fr 1fr', gap: 16 }}>
            <div className="card card-pad">
              <div className="card-title" style={{ marginBottom: 16 }}>每日审核分布</div>
              <ReviewerChart/>
            </div>
            <div className="card">
              <div className="card-header"><div className="card-title">驳回原因 Top 3</div></div>
              <div style={{ padding: '12px 20px' }}>
                {[
                  { reason: '阵容与现有数据重复', count: 5, pct: 38 },
                  { reason: '字段不完整 / 缺技能', count: 4, pct: 31 },
                  { reason: '配招不合理 / 与机制冲突', count: 3, pct: 23 },
                ].map((r) => (
                  <div key={r.reason} style={{ padding: '8px 0' }}>
                    <div className="hstack" style={{ justifyContent:'space-between', marginBottom: 4 }}>
                      <span style={{ fontSize: 13 }}>{r.reason}</span>
                      <span className="mono" style={{ fontSize: 12, color: 'var(--text-3)' }}>{r.count} 次</span>
                    </div>
                    <div className="progress"><div className="fill" style={{ width: `${r.pct}%` }}/></div>
                  </div>
                ))}
              </div>
            </div>
          </div>

          <div style={{
            marginTop: 24,
            padding: 16,
            background: 'var(--info-bg)',
            border: '1px solid transparent',
            borderRadius: 'var(--r-lg)',
            display: 'flex', alignItems: 'flex-start', gap: 12,
            color: 'var(--text-2)',
          }}>
            <window.I.info size={18}/>
            <div style={{ flex: 1, fontSize: 13 }}>
              <div style={{ fontWeight: 500, color: 'var(--text)', marginBottom: 4 }}>关于你的权限</div>
              你的角色 <window.RolePill role="reviewer"/> 可以审核提交、查看图鉴/攻略/反馈/日志,但不能直接编辑阵容数据。
              如需更高权限,请联系主管理员。
            </div>
          </div>
        </>
      )}
    </div>
  );
}

function Kpi({ label, value, delta, foot, render, mono, onClick }) {
  return (
    <div className="card kpi" onClick={onClick} style={{ cursor: onClick ? 'pointer' : 'default' }}>
      <div className="kpi-label">{label}</div>
      {render ? render() : (
        <>
          <div className={`kpi-value ${mono ? 'mono' : ''}`}>{value}</div>
          <div className="kpi-foot">
            {delta && <span className={`delta ${delta.kind}`}>
              {delta.kind === 'up' ? '↑ ' : delta.kind === 'down' ? '↓ ' : ''}{delta.text}
            </span>}
            {foot && <span>{foot}</span>}
          </div>
        </>
      )}
    </div>
  );
}

function Meter({ label, used, total, unit }) {
  const pct = Math.round((used / total) * 100);
  return (
    <div style={{ flex: 1 }}>
      <div style={{ fontSize: 11, color: 'var(--text-3)', display:'flex', justifyContent:'space-between' }}>
        <span>{label}</span><span className="mono">{pct}%</span>
      </div>
      <div className="progress" style={{ marginTop: 4 }}>
        <div className={`fill ${pct > 80 ? 'danger' : pct > 60 ? 'warn' : ''}`} style={{ width: `${pct}%` }}/>
      </div>
      <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: 4, fontFamily:'var(--font-mono)' }}>
        {used}{unit} / {total}{unit}
      </div>
    </div>
  );
}

function relTime(iso) {
  const now = new Date('2026-05-19T15:00:00');
  const then = new Date(iso);
  const mins = Math.round((now - then) / 60000);
  if (mins < 60) return `${mins} 分钟前`;
  if (mins < 24 * 60) return `${Math.round(mins / 60)} 小时前`;
  return `${Math.round(mins / 1440)} 天前`;
}

function ReviewerChart() {
  const days = ['周一','周二','周三','周四','周五','周六','周日'];
  const data = [
    { approve: 4, reject: 2 },
    { approve: 6, reject: 1 },
    { approve: 3, reject: 4 },
    { approve: 5, reject: 0 },
    { approve: 2, reject: 3 },
    { approve: 1, reject: 1 },
    { approve: 1, reject: 1 },
  ];
  const max = 8;
  return (
    <div>
      <div style={{ display:'flex', alignItems:'flex-end', gap: 10, height: 140 }}>
        {data.map((d, i) => (
          <div key={i} style={{ flex: 1, display:'flex', flexDirection:'column', justifyContent:'flex-end', alignItems:'center', height:'100%' }}>
            <div style={{ width: '100%', display:'flex', flexDirection:'column-reverse', gap: 1, height: '100%', justifyContent:'flex-end' }}>
              <div style={{
                height: `${(d.approve / max) * 100}%`,
                background: 'var(--success)',
                borderRadius: '3px 3px 0 0',
              }} title={`通过 ${d.approve}`}/>
              <div style={{
                height: `${(d.reject / max) * 100}%`,
                background: 'var(--danger)',
                opacity: .8,
              }} title={`驳回 ${d.reject}`}/>
            </div>
            <div className="mono" style={{ fontSize: 10, color: 'var(--text-3)', marginTop: 6 }}>{days[i]}</div>
          </div>
        ))}
      </div>
      <div className="hstack" style={{ marginTop: 12, fontSize: 11, gap: 14, color: 'var(--text-2)' }}>
        <span><span style={{ display:'inline-block', width: 10, height: 10, borderRadius: 2, background:'var(--success)', verticalAlign:'middle', marginRight: 4 }}/>通过 22</span>
        <span><span style={{ display:'inline-block', width: 10, height: 10, borderRadius: 2, background:'var(--danger)', opacity:.8, verticalAlign:'middle', marginRight: 4 }}/>驳回 12</span>
        <span style={{ marginLeft: 'auto', color: 'var(--text-3)' }}>团队平均: 通过 28 · 驳回 7</span>
      </div>
    </div>
  );
}

Object.assign(window, { LoginScreen, Dashboard, relTime, DEMO_ACCOUNTS });
