// 智能填报顺序检查页 — Wave 15-B
// Route: /#/gaokao/fill-check
// Users enter up to 30 slots (school + major + score) → validator runs → issues shown.
// No new API endpoints. Uses window.PBFillValidator (lib/gaokao-fill-validator.js).

const GaokaoFillCheckPage = () => {
  const lang = useLang ? useLang() : 'zh';
  const t = (useT ? useT() : null) || {};
  const fc = (t.gk || {}).fillCheck || {};

  // QA 2026-06-11 项2 — HI 组代号名册（官方投档数据），window 级缓存避免重复 fetch
  const _loadHiGroupRoster = async () => {
    if (window.__PB_HI_GROUP_ROSTER !== undefined) return window.__PB_HI_GROUP_ROSTER;
    try {
      const r = await fetch('/data/admissions/HI/2025-3plus3.json');
      if (!r.ok) { window.__PB_HI_GROUP_ROSTER = null; return null; }
      const d = await r.json();
      const set = new Set();
      for (const s of (d.schools || [])) {
        for (const g of (s.groups || [])) {
          if (g && g.groupCode) set.add(String(g.groupCode));
        }
      }
      window.__PB_HI_GROUP_ROSTER = set.size ? set : null;
    } catch (_e) {
      window.__PB_HI_GROUP_ROSTER = null;
    }
    return window.__PB_HI_GROUP_ROSTER;
  };

  // ── State ──────────────────────────────────────────────────────────────────

  const EMPTY_SLOT = () => ({
    schoolCode: '',
    // QA 2026-06-11 项2 — 海南投档单位是院校专业组（6 位 = 院校代号 + 组号）
    groupCode: '',
    schoolName: '',
    majorCategory: '',
    score: '',
    rank: '',
    tier: '',
    subjects: '',
  });

  const [userScore,    setUserScore]    = React.useState('');
  const [userRank,     setUserRank]     = React.useState('');
  const [province,     setProvince]     = React.useState('GD');
  const [userSubjects, setUserSubjects] = React.useState('');
  const [slots,        setSlots]        = React.useState(() => Array.from({ length: 5 }, EMPTY_SLOT));
  const [result,       setResult]       = React.useState(null);
  const [csvError,     setCsvError]     = React.useState('');
  const [submitted,    setSubmitted]    = React.useState(false);
  const [balance,      setBalance]      = React.useState(null);
  const [originalSlots, setOriginalSlots] = React.useState(null);
  const [optSummary,   setOptSummary]  = React.useState(null);

  // ── Slot helpers ──────────────────────────────────────────────────────────

  const updateSlot = (idx, field, value) => {
    setSlots((prev) => {
      const next = [...prev];
      next[idx] = { ...next[idx], [field]: value };
      return next;
    });
    setResult(null);
    setBalance(null);
  };

  const addSlot = () => {
    if (slots.length >= 30) return;
    setSlots((prev) => [...prev, EMPTY_SLOT()]);
  };

  const removeSlot = (idx) => {
    setSlots((prev) => prev.filter((_, i) => i !== idx));
    setResult(null);
    setBalance(null);
  };

  // ── CSV import ─────────────────────────────────────────────────────────────
  // Expected CSV: schoolCode,schoolName,majorCategory,score,rank,tier,subjects
  // First row can be a header (auto-detected by non-numeric score field).

  const handleCsvImport = (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    setCsvError('');
    const reader = new FileReader();
    reader.onload = (ev) => {
      try {
        const lines = (ev.target.result || '').split(/\r?\n/).filter((l) => l.trim());
        const parsed = [];
        for (const line of lines) {
          const cols = line.split(',').map((c) => c.trim());
          if (cols.length < 2) continue;
          // Skip header row
          if (isNaN(Number(cols[3])) && parsed.length === 0) continue;
          parsed.push({
            schoolCode:    cols[0] || '',
            schoolName:    cols[1] || '',
            majorCategory: cols[2] || '',
            score:         cols[3] || '',
            rank:          cols[4] || '',
            tier:          cols[5] || '',
            subjects:      cols[6] || '',
            // QA 2026-06-11 项2 — 第 8 列（可选）：海南专业组代号；老 7 列文件兼容
            groupCode:     cols[7] || '',
          });
          if (parsed.length >= 30) break;
        }
        if (parsed.length === 0) {
          setCsvError(lang === 'zh' ? 'CSV 无有效数据行' : 'No valid rows found in CSV');
          return;
        }
        setSlots(parsed);
        setResult(null);
      } catch (err) {
        setCsvError(lang === 'zh' ? `CSV 解析失败: ${err.message}` : `CSV parse error: ${err.message}`);
      }
    };
    reader.readAsText(file);
    // Reset input so same file can be re-imported
    e.target.value = '';
  };

  // ── Validate ───────────────────────────────────────────────────────────────

  const handleSubmit = async (e) => {
    e && e.preventDefault();
    const validator = window.PBFillValidator;
    if (!validator) {
      setResult({ issues: [], summary: lang === 'zh' ? '检查器未加载，请刷新页面。' : 'Validator not loaded. Please refresh.', score: 0 });
      setSubmitted(true);
      return;
    }

    // Normalize slots: filter truly empty rows, convert score/rank to numbers
    const normalizedSlots = slots
      .filter((s) => s.schoolCode || s.schoolName)
      .map((s) => ({
        ...s,
        score: s.score !== '' ? Number(s.score) : undefined,
        rank:  s.rank  !== '' ? Number(s.rank)  : undefined,
      }));

    const numericScore = userScore !== '' ? Number(userScore) : undefined;
    const numericRank  = userRank  !== '' ? Number(userRank)  : undefined;

    // QA 2026-06-11 项2 — HI 组代号存在性核对名册（lib 保持 no-fetch，
    // 由页面 fetch 官方投档数据构建；失败时仅做格式/前缀校验）。
    let hiGroupRoster;
    if (province === 'HI') {
      hiGroupRoster = await _loadHiGroupRoster();
    }

    const res = validator.validateFillOrder({
      slots: normalizedSlots,
      userScore:    numericScore,
      userRank:     numericRank,
      province,
      userSubjects: userSubjects || undefined,
      hiGroupRoster: hiGroupRoster || undefined,
    });
    setResult(res);

    // Compute balance (冲稳保) — needs computeBalance exported from validator
    if (validator.computeBalance) {
      const bal = validator.computeBalance(normalizedSlots, numericScore);
      setBalance(bal);
    } else {
      setBalance(null);
    }
    setSubmitted(true);
  };

  // ── Slot optimizer ────────────────────────────────────────────────────────

  const handleOptimize = () => {
    const optimizer = window.PBSlotOptimizer;
    if (!optimizer) return;

    const numericScore = userScore !== '' ? Number(userScore) : undefined;

    // Build enriched slots for optimizer (add prob + plan + bucket from current display)
    const enriched = slots.map((s) => {
      const slotScore = s.score !== '' ? Number(s.score) : undefined;
      let prob = 0.5; // default midpoint
      if (typeof slotScore === 'number' && numericScore != null) {
        const delta = numericScore - slotScore;
        if (delta > 30)       prob = 0.92;
        else if (delta > 15)  prob = 0.80;
        else if (delta > 5)   prob = 0.60;
        else if (delta > -10) prob = 0.35;
        else                  prob = 0.08;
      }
      const bucket = (typeof slotScore === 'number' && numericScore != null)
        ? (slotScore - numericScore > 20 ? 'reach' : slotScore - numericScore > -10 ? 'match' : 'safety')
        : 'match';
      const plan = s.plan != null ? Number(s.plan) : 10;
      return { ...s, prob, bucket, plan };
    });

    // Save original for revert
    setOriginalSlots([...slots]);

    const optimized = optimizer.optimizeSlotOrder(enriched, { preserveIndex: false });
    const comparison = optimizer.formatComparison(enriched, optimized);

    // Strip the enriched fields that aren't in the original slot shape
    const cleanedSlots = optimized.map((s) => {
      const { prob: _p, bucket: _b, plan: _pl, ...rest } = s;
      return rest;
    });

    setSlots(cleanedSlots);
    setOptSummary(comparison);
    setResult(null);
    setSubmitted(false);
    setBalance(null);
  };

  const handleRevert = () => {
    if (originalSlots) {
      setSlots(originalSlots);
      setOriginalSlots(null);
      setOptSummary(null);
    }
  };

  // ── Score color ────────────────────────────────────────────────────────────

  const scoreColor = (s) => {
    if (s >= 80) return '#16a34a';
    if (s >= 60) return '#d97706';
    return '#dc2626';
  };

  const severityStyle = (sev) => {
    if (sev === 'error')   return { bg: '#fee2e2', color: '#991b1b', border: '#fca5a5', label: lang === 'zh' ? '严重' : 'Error' };
    if (sev === 'warning') return { bg: '#fef3c7', color: '#92400e', border: '#fcd34d', label: lang === 'zh' ? '警告' : 'Warning' };
    return { bg: '#eff6ff', color: '#1e40af', border: '#93c5fd', label: lang === 'zh' ? '建议' : 'Info' };
  };

  // ── PROVINCE list ──────────────────────────────────────────────────────────
  const PROVINCES = [
    { code: 'GD', label: '广东' }, { code: 'BJ', label: '北京' },
    { code: 'SD', label: '山东' }, { code: 'HI', label: '海南' },
    { code: 'SH', label: '上海' }, { code: 'TJ', label: '天津' },
    { code: 'HB', label: '河北' }, { code: 'ZJ', label: '浙江' },
    { code: 'JS', label: '江苏' }, { code: 'FJ', label: '福建' },
  ];

  const TIER_OPTIONS = [
    { value: '', label: lang === 'zh' ? '选择层次' : 'Select tier' },
    { value: '985', label: '985' },
    { value: '211', label: '211' },
    { value: '双一流', label: '双一流' },
    { value: 'public', label: lang === 'zh' ? '普通本科' : 'Public' },
    { value: 'private', label: lang === 'zh' ? '民办本科' : 'Private' },
  ];

  // ── Render ─────────────────────────────────────────────────────────────────

  // i18n optimizer keys
  const opt = (t.gk || {}).optimizer || {};

  const labelStyle = {
    fontSize: 11,
    fontWeight: 600,
    color: 'var(--pb-fg-muted)',
    textTransform: 'uppercase',
    letterSpacing: '0.05em',
    marginBottom: 4,
    display: 'block',
  };

  const inputStyle = {
    width: '100%',
    padding: '6px 10px',
    fontSize: 13,
    border: '1px solid var(--pb-border)',
    borderRadius: 6,
    background: 'var(--pb-paper)',
    color: 'var(--pb-fg)',
    boxSizing: 'border-box',
  };

  return (
    <div className="pb-scroll" data-testid="fill-check-page">
      <PBNav active="gaokao" />

      {/* Page header */}
      <section style={{ padding: '48px 48px 32px', background: 'var(--pb-paper)', borderBottom: '1px solid var(--pb-border)' }}>
        <div style={{ maxWidth: 960, margin: '0 auto' }}>
          <div className="pb-eyebrow" style={{ marginBottom: 12 }}>
            {lang === 'zh' ? '智能填报顺序检查' : 'Fill Order Check'}
          </div>
          <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', flexWrap: 'wrap', gap: 16 }}>
            <h1 style={{ fontFamily: 'var(--pb-serif)', fontSize: 32, fontWeight: 600, margin: 0 }}>
              {lang === 'zh' ? '志愿顺序检查 · 30 槽梯度分析' : 'Volunteer Order Check · 30-Slot Analysis'}
            </h1>
            <button
              className="pb-btn pb-btn-link pb-btn-sm"
              onClick={() => typeof navigateTo === 'function' && navigateTo('/gaokao')}
              style={{ alignSelf: 'flex-end' }}
            >
              {lang === 'zh' ? '← 返回测算页' : '← Back'}
            </button>
          </div>
          <p style={{ marginTop: 12, fontSize: 14, color: 'var(--pb-fg-muted)', lineHeight: 1.7 }}>
            {lang === 'zh'
              ? '输入您已拟定的志愿顺序，系统自动检查梯度合理性、冲稳保比例、专业匹配等 12 项规则，并给出改进建议。'
              : 'Enter your planned volunteer order. The system checks gradient reasonableness, reach/match/safety ratio, major compatibility, and 12 other rules.'}
          </p>
        </div>
      </section>

      {/* Form */}
      <section style={{ padding: '32px 48px 64px', background: 'var(--pb-bg)' }}>
        <div style={{ maxWidth: 960, margin: '0 auto' }}>

          <form data-testid="fill-check-form" onSubmit={handleSubmit}>

            {/* User info row */}
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))', gap: 16, marginBottom: 28 }}>
              <div>
                <label style={labelStyle}>{lang === 'zh' ? '我的高考分数' : 'My Score'}</label>
                <input
                  type="number"
                  data-testid="user-score-input"
                  style={inputStyle}
                  placeholder="e.g. 620"
                  value={userScore}
                  onChange={(e) => setUserScore(e.target.value)}
                />
              </div>
              <div>
                <label style={labelStyle}>{lang === 'zh' ? '省排名' : 'Province Rank'}</label>
                <input
                  type="number"
                  data-testid="user-rank-input"
                  style={inputStyle}
                  placeholder="e.g. 8000"
                  value={userRank}
                  onChange={(e) => setUserRank(e.target.value)}
                />
              </div>
              <div>
                <label style={labelStyle}>{lang === 'zh' ? '省份' : 'Province'}</label>
                <select
                  data-testid="province-select"
                  className="pb-select"
                  style={{ ...inputStyle, width: '100%' }}
                  value={province}
                  onChange={(e) => setProvince(e.target.value)}
                >
                  {PROVINCES.map((p) => (
                    <option key={p.code} value={p.code}>{p.label} ({p.code})</option>
                  ))}
                </select>
              </div>
              <div>
                <label style={labelStyle}>{lang === 'zh' ? '选科代码' : 'Subjects'}</label>
                <input
                  type="text"
                  data-testid="subjects-input"
                  style={inputStyle}
                  placeholder="e.g. 456"
                  value={userSubjects}
                  onChange={(e) => setUserSubjects(e.target.value)}
                />
              </div>
            </div>

            {/* CSV Import */}
            <div style={{ marginBottom: 20, display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
              <label
                style={{
                  display: 'inline-flex', alignItems: 'center', gap: 6,
                  padding: '7px 14px', fontSize: 13, fontWeight: 500,
                  border: '1px solid var(--pb-border)', borderRadius: 6,
                  cursor: 'pointer', background: 'var(--pb-paper)', color: 'var(--pb-fg)',
                }}
              >
                <span>📂</span>
                <span>{lang === 'zh' ? 'CSV 导入' : 'Import CSV'}</span>
                <input
                  type="file"
                  accept=".csv,text/csv"
                  style={{ display: 'none' }}
                  onChange={handleCsvImport}
                  data-testid="csv-import-input"
                />
              </label>
              <span style={{ fontSize: 11, color: 'var(--pb-fg-muted)' }}>
                {lang === 'zh' ? 'CSV格式: 院校代码,院校名称,专业,分数,排名,层次,选科[,专业组代号]（海南建议填第 8 列组代号）' : 'CSV: code,name,major,score,rank,tier,subjects[,groupCode]'}
              </span>
              {csvError && (
                <span style={{ fontSize: 12, color: '#dc2626' }}>{csvError}</span>
              )}
            </div>

            {/* Slots table */}
            <div style={{ overflowX: 'auto', marginBottom: 20 }}>
              <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
                <thead>
                  <tr style={{ background: 'var(--pb-surface-alt)', borderBottom: '2px solid var(--pb-border)' }}>
                    <th style={{ padding: '8px 10px', textAlign: 'left', fontWeight: 600, color: 'var(--pb-fg-muted)', fontSize: 11, whiteSpace: 'nowrap' }}>#</th>
                    <th style={{ padding: '8px 10px', textAlign: 'left', fontWeight: 600, color: 'var(--pb-fg-muted)', fontSize: 11, minWidth: 90 }}>{lang === 'zh' ? '院校代码' : 'Code'}</th>
                    <th style={{ padding: '8px 10px', textAlign: 'left', fontWeight: 600, color: 'var(--pb-fg-muted)', fontSize: 11, minWidth: 90 }}>{lang === 'zh' ? '专业组(海南)' : 'Group (HI)'}</th>
                    <th style={{ padding: '8px 10px', textAlign: 'left', fontWeight: 600, color: 'var(--pb-fg-muted)', fontSize: 11, minWidth: 140 }}>{lang === 'zh' ? '院校名称' : 'School'}</th>
                    <th style={{ padding: '8px 10px', textAlign: 'left', fontWeight: 600, color: 'var(--pb-fg-muted)', fontSize: 11, minWidth: 120 }}>{lang === 'zh' ? '专业类别' : 'Major'}</th>
                    <th style={{ padding: '8px 10px', textAlign: 'left', fontWeight: 600, color: 'var(--pb-fg-muted)', fontSize: 11, minWidth: 70 }}>{lang === 'zh' ? '录取分' : 'Score'}</th>
                    <th style={{ padding: '8px 10px', textAlign: 'left', fontWeight: 600, color: 'var(--pb-fg-muted)', fontSize: 11, minWidth: 70 }}>{lang === 'zh' ? '排名' : 'Rank'}</th>
                    <th style={{ padding: '8px 10px', textAlign: 'left', fontWeight: 600, color: 'var(--pb-fg-muted)', fontSize: 11, minWidth: 110 }}>{lang === 'zh' ? '层次' : 'Tier'}</th>
                    <th style={{ padding: '8px 10px', width: 36 }}></th>
                  </tr>
                </thead>
                <tbody>
                  {slots.map((slot, idx) => (
                    <tr
                      key={idx}
                      style={{
                        background: idx % 2 === 0 ? 'var(--pb-paper)' : 'var(--pb-surface-alt)',
                        borderBottom: '1px solid var(--pb-border)',
                      }}
                      data-testid={`slot-row-${idx}`}
                    >
                      <td style={{ padding: '6px 10px', color: 'var(--pb-fg-muted)', fontFamily: 'var(--pb-mono)', fontSize: 12, textAlign: 'center' }}>
                        {idx + 1}
                      </td>
                      <td style={{ padding: '4px 6px' }}>
                        <input
                          type="text"
                          style={{ ...inputStyle, padding: '4px 8px' }}
                          placeholder="1001"
                          value={slot.schoolCode}
                          onChange={(e) => updateSlot(idx, 'schoolCode', e.target.value)}
                          data-testid={`slot-code-${idx}`}
                        />
                      </td>
                      <td style={{ padding: '4px 6px' }}>
                        <input
                          type="text"
                          style={{ ...inputStyle, padding: '4px 8px' }}
                          placeholder="100101"
                          value={slot.groupCode || ''}
                          onChange={(e) => updateSlot(idx, 'groupCode', e.target.value)}
                          data-testid={`slot-group-${idx}`}
                        />
                      </td>
                      <td style={{ padding: '4px 6px' }}>
                        <input
                          type="text"
                          style={{ ...inputStyle, padding: '4px 8px' }}
                          placeholder={lang === 'zh' ? '北京大学' : 'School name'}
                          value={slot.schoolName}
                          onChange={(e) => updateSlot(idx, 'schoolName', e.target.value)}
                          data-testid={`slot-name-${idx}`}
                        />
                      </td>
                      <td style={{ padding: '4px 6px' }}>
                        <input
                          type="text"
                          style={{ ...inputStyle, padding: '4px 8px' }}
                          placeholder={lang === 'zh' ? '计算机类' : 'cs'}
                          value={slot.majorCategory}
                          onChange={(e) => updateSlot(idx, 'majorCategory', e.target.value)}
                          data-testid={`slot-major-${idx}`}
                        />
                      </td>
                      <td style={{ padding: '4px 6px' }}>
                        <input
                          type="number"
                          style={{ ...inputStyle, padding: '4px 8px' }}
                          placeholder="650"
                          value={slot.score}
                          onChange={(e) => updateSlot(idx, 'score', e.target.value)}
                          data-testid={`slot-score-${idx}`}
                        />
                      </td>
                      <td style={{ padding: '4px 6px' }}>
                        <input
                          type="number"
                          style={{ ...inputStyle, padding: '4px 8px' }}
                          placeholder="5000"
                          value={slot.rank}
                          onChange={(e) => updateSlot(idx, 'rank', e.target.value)}
                          data-testid={`slot-rank-${idx}`}
                        />
                      </td>
                      <td style={{ padding: '4px 6px' }}>
                        <select
                          className="pb-select"
                          style={{ ...inputStyle, padding: '4px 8px' }}
                          value={slot.tier}
                          onChange={(e) => updateSlot(idx, 'tier', e.target.value)}
                          data-testid={`slot-tier-${idx}`}
                        >
                          {TIER_OPTIONS.map((o) => (
                            <option key={o.value} value={o.value}>{o.label}</option>
                          ))}
                        </select>
                      </td>
                      <td style={{ padding: '4px 6px', textAlign: 'center' }}>
                        {slots.length > 1 && (
                          <button
                            type="button"
                            onClick={() => removeSlot(idx)}
                            title={lang === 'zh' ? '删除' : 'Remove'}
                            data-testid={`slot-remove-${idx}`}
                            style={{
                              width: 26, height: 26, borderRadius: 13,
                              border: 'none', background: 'var(--pb-surface-alt)',
                              color: 'var(--pb-fg-muted)', cursor: 'pointer',
                              display: 'grid', placeItems: 'center', fontSize: 14,
                            }}
                          >×</button>
                        )}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>

            {/* Add slot + submit */}
            <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center', marginBottom: 32 }}>
              {slots.length < 30 && (
                <button
                  type="button"
                  className="pb-btn pb-btn-link pb-btn-sm"
                  onClick={addSlot}
                  data-testid="add-slot-btn"
                >
                  {lang === 'zh' ? '+ 添加志愿' : '+ Add Slot'}
                </button>
              )}
              <span style={{ fontSize: 12, color: 'var(--pb-fg-muted)' }}>
                {slots.length}/30 {lang === 'zh' ? '个志愿' : 'slots'}
              </span>
              <div style={{ flex: 1 }} />
              <button
                type="submit"
                className="pb-btn pb-btn-gold"
                data-testid="submit-btn"
                style={{ minWidth: 120 }}
              >
                {lang === 'zh' ? '开始检查' : 'Check Now'}
              </button>
            </div>
          </form>

          {/* ── Optimizer panel ────────────────────────────────────────────── */}
          {(() => {
            const filledCount = slots.filter((s) => s.schoolCode || s.schoolName).length;
            if (filledCount < 2) return null;
            return (
              <div style={{ marginBottom: 28 }}>
                {/* Optimization summary */}
                {optSummary && (
                  <div
                    data-testid="optimization-summary"
                    style={{
                      marginBottom: 12,
                      padding: '14px 18px',
                      background: optSummary.deltaPct > 0 ? '#f0fdf4' : '#eff6ff',
                      border: `1px solid ${optSummary.deltaPct > 0 ? '#86efac' : '#93c5fd'}`,
                      borderRadius: 8,
                      display: 'flex',
                      alignItems: 'center',
                      gap: 12,
                      flexWrap: 'wrap',
                    }}
                  >
                    <span style={{ fontSize: 18 }}>{optSummary.deltaPct > 0 ? '📈' : '✅'}</span>
                    <div style={{ flex: 1 }}>
                      <div style={{ fontWeight: 600, fontSize: 13, marginBottom: 2 }}>
                        {opt.summaryTitle || (lang === 'zh' ? '录取期望提升分析' : 'Expected Admission Analysis')}
                      </div>
                      <div style={{ fontSize: 12, color: 'var(--pb-fg-muted)' }}>
                        {optSummary.deltaPct > 0
                          ? (opt.summaryFmt
                              ? opt.summaryFmt(optSummary.beforeRate, optSummary.afterRate, optSummary.deltaPct)
                              : `原顺序录取期望 ${optSummary.beforeRate}% → 优化后 ${optSummary.afterRate}% (+${optSummary.deltaPct}%)`)
                          : (opt.summaryNoGain
                              ? opt.summaryNoGain(optSummary.beforeRate)
                              : `原顺序录取期望 ${optSummary.beforeRate}%，当前排列已是较优方案`)}
                      </div>
                    </div>
                    <button
                      type="button"
                      className="pb-btn pb-btn-link pb-btn-sm"
                      onClick={handleRevert}
                      data-testid="revert-order-btn"
                      style={{ whiteSpace: 'nowrap' }}
                    >
                      {opt.btnRevert || (lang === 'zh' ? '↩️ 还原' : '↩️ Revert')}
                    </button>
                  </div>
                )}

                {/* Optimize button */}
                <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                  <button
                    type="button"
                    className="pb-btn pb-btn-link pb-btn-sm"
                    onClick={handleOptimize}
                    data-testid="optimize-order-btn"
                    title={opt.tooltipBtn || (lang === 'zh' ? '按 prob×招生计划 贪心排序，冲/稳/保桶内重排' : 'Greedy sort by prob × plan within each tier')}
                    style={{
                      display: 'inline-flex', alignItems: 'center', gap: 6,
                      padding: '7px 14px', fontSize: 13, fontWeight: 500,
                      border: '1px solid var(--pb-border)', borderRadius: 6,
                      cursor: 'pointer', background: 'var(--pb-paper)', color: 'var(--pb-fg)',
                    }}
                  >
                    {opt.btnOptimize || (lang === 'zh' ? '🔀 优化顺序' : '🔀 Optimize Order')}
                  </button>
                  <span style={{ fontSize: 11, color: 'var(--pb-fg-muted)' }}>
                    {lang === 'zh' ? '冲/稳/保桶内按录取期望重排' : 'Re-rank within reach/match/safety tiers'}
                  </span>
                </div>
              </div>
            );
          })()}

          {/* Results */}
          {submitted && result && (
            <div data-testid="fill-check-results">
              {/* Score badge */}
              <div style={{
                display: 'flex', alignItems: 'center', gap: 20,
                padding: '20px 24px', background: 'var(--pb-paper)',
                borderRadius: 10, border: '1px solid var(--pb-border)',
                marginBottom: 20,
              }}>
                <div style={{ textAlign: 'center', minWidth: 72 }}>
                  <div style={{
                    fontSize: 40, fontWeight: 700, fontFamily: 'var(--pb-mono)',
                    color: scoreColor(result.score),
                  }}>
                    {result.score}
                  </div>
                  <div style={{ fontSize: 10, color: 'var(--pb-fg-muted)', fontWeight: 600, letterSpacing: '0.05em', marginTop: 2 }}>
                    {lang === 'zh' ? '健康分 /100' : 'Score /100'}
                  </div>
                </div>
                <div>
                  <div style={{ fontWeight: 600, fontSize: 15, marginBottom: 4 }}>
                    {lang === 'zh' ? '填报方案诊断结果' : 'Fill Order Diagnosis'}
                  </div>
                  <div style={{ fontSize: 13, color: 'var(--pb-fg-muted)', lineHeight: 1.6 }}>
                    {result.summary}
                  </div>
                </div>
              </div>

              {/* Issues list */}
              {result.issues.length === 0 ? (
                <div style={{
                  padding: '24px', textAlign: 'center', background: '#f0fdf4',
                  borderRadius: 10, border: '1px solid #86efac', fontSize: 14,
                  color: '#15803d',
                }}>
                  {lang === 'zh' ? '未发现问题，填报方案整体健康！' : 'No issues found — your fill order looks great!'}
                </div>
              ) : (
                <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                  {result.issues.map((issue, idx) => {
                    const st = severityStyle(issue.severity);
                    return (
                      <div
                        key={idx}
                        data-testid={`issue-row-${idx}`}
                        style={{
                          padding: '14px 18px',
                          background: st.bg,
                          border: `1px solid ${st.border}`,
                          borderRadius: 8,
                          color: st.color,
                        }}
                      >
                        <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
                          <span style={{
                            padding: '1px 8px', fontSize: 10, fontWeight: 700,
                            borderRadius: 4, border: `1px solid ${st.border}`,
                            background: 'rgba(255,255,255,0.6)',
                            flexShrink: 0, lineHeight: 1.8,
                          }}>
                            {st.label}
                            {issue.slotIdx >= 0 && ` · 志愿 ${issue.slotIdx + 1}`}
                          </span>
                          <div style={{ flex: 1 }}>
                            <div style={{ fontWeight: 600, fontSize: 13, lineHeight: 1.5 }}>
                              {issue.message}
                            </div>
                            {issue.suggestion && (
                              <div style={{ fontSize: 12, marginTop: 4, opacity: 0.85, lineHeight: 1.6 }}>
                                💡 {issue.suggestion}
                              </div>
                            )}
                          </div>
                        </div>
                      </div>
                    );
                  })}
                </div>
              )}

              {/* ── 并列对比 Section ──────────────────────────────────────────────── */}
              {(() => {
                const filledSlots = slots.filter((s) => s.schoolCode || s.schoolName);
                if (filledSlots.length === 0) return null;
                return (
                  <div
                    data-testid="fill-check-side-by-side"
                    style={{
                      marginTop: 28,
                      background: 'var(--pb-paper)',
                      border: '1px solid var(--pb-border)',
                      borderRadius: 10,
                      overflow: 'hidden',
                    }}
                  >
                    <div style={{
                      padding: '14px 20px',
                      background: 'var(--pb-surface-alt)',
                      borderBottom: '1px solid var(--pb-border)',
                      display: 'flex', alignItems: 'center', gap: 10,
                    }}>
                      <span style={{ fontWeight: 700, fontSize: 14 }}>
                        {fc.sideBySideTitle || (lang === 'zh' ? '并列对比 · 全部志愿概览' : 'Side-by-Side Comparison')}
                      </span>
                      <span style={{ fontSize: 11, color: 'var(--pb-fg-muted)', fontFamily: 'var(--pb-mono)' }}>
                        {filledSlots.length} {lang === 'zh' ? '个志愿' : 'slots'}
                      </span>
                    </div>
                    <div style={{ overflowX: 'auto' }}>
                      <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
                        <thead>
                          <tr style={{ background: 'var(--pb-surface-alt)', borderBottom: '1px solid var(--pb-border)' }}>
                            {['#', lang === 'zh' ? '院校名称' : 'School', lang === 'zh' ? '专业' : 'Major',
                              lang === 'zh' ? '录取概率' : 'Prob.', lang === 'zh' ? '招生计划' : 'Plan',
                              lang === 'zh' ? '学科排名' : 'Disc.Rank', lang === 'zh' ? '限制条件' : 'Restrictions',
                              lang === 'zh' ? '类型' : 'Type'].map((h) => (
                              <th key={h} style={{
                                padding: '8px 10px', textAlign: 'left', fontWeight: 600,
                                fontSize: 11, color: 'var(--pb-fg-muted)', whiteSpace: 'nowrap',
                              }}>{h}</th>
                            ))}
                          </tr>
                        </thead>
                        <tbody>
                          {filledSlots.map((slot, idx) => {
                            // Compute bucket for row coloring
                            const numScore = userScore !== '' ? Number(userScore) : undefined;
                            const bucket = (typeof slot.score === 'number' && numScore != null)
                              ? (slot.score - numScore > 20 ? 'reach' : slot.score - numScore > -10 ? 'match' : 'safety')
                              : null;
                            const bucketColor = bucket === 'reach' ? '#dc2626' : bucket === 'match' ? '#d97706' : bucket === 'safety' ? '#16a34a' : 'var(--pb-fg-muted)';
                            const bucketLabel = bucket === 'reach' ? (lang === 'zh' ? '冲' : 'R') : bucket === 'match' ? (lang === 'zh' ? '稳' : 'M') : bucket === 'safety' ? (lang === 'zh' ? '保' : 'S') : '–';
                            // Probability heuristic based on score delta
                            let prob = '–';
                            if (typeof slot.score === 'number' && numScore != null) {
                              const delta = numScore - slot.score; // positive = above cutoff
                              if (delta > 30)      prob = '>90%';
                              else if (delta > 15) prob = '70–90%';
                              else if (delta > 5)  prob = '50–70%';
                              else if (delta > -10) prob = '20–50%';
                              else                  prob = '<10%';
                            }
                            return (
                              <tr
                                key={idx}
                                style={{
                                  background: idx % 2 === 0 ? 'var(--pb-paper)' : 'var(--pb-surface-alt)',
                                  borderBottom: '1px solid var(--pb-border)',
                                }}
                                data-testid={`sbs-row-${idx}`}
                              >
                                <td style={{ padding: '6px 10px', color: 'var(--pb-fg-muted)', fontFamily: 'var(--pb-mono)', textAlign: 'center', fontSize: 11 }}>{idx + 1}</td>
                                <td style={{ padding: '6px 10px', fontWeight: 500, maxWidth: 160, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                                  {slot.schoolName || slot.schoolCode || '–'}
                                  {slot.tier && (
                                    <span style={{ marginLeft: 5, fontSize: 10, padding: '1px 5px', borderRadius: 3, background: 'var(--pb-surface-alt)', color: 'var(--pb-fg-muted)' }}>
                                      {slot.tier}
                                    </span>
                                  )}
                                </td>
                                <td style={{ padding: '6px 10px', color: 'var(--pb-fg-muted)', maxWidth: 120, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                                  {slot.majorCategory || '–'}
                                </td>
                                <td style={{ padding: '6px 10px', fontFamily: 'var(--pb-mono)', fontWeight: 600, color: bucketColor }}>
                                  {prob}
                                </td>
                                <td style={{ padding: '6px 10px', color: 'var(--pb-fg-muted)', fontFamily: 'var(--pb-mono)' }}>
                                  {slot.plan != null ? slot.plan : (slot.score != null ? slot.score : '–')}
                                </td>
                                <td style={{ padding: '6px 10px', color: 'var(--pb-fg-muted)' }}>
                                  {slot.disciplineRank || '–'}
                                </td>
                                <td style={{ padding: '6px 10px', color: 'var(--pb-fg-muted)', fontSize: 11 }}>
                                  {slot.restrictions || slot.subjects || '–'}
                                </td>
                                <td style={{ padding: '6px 10px' }}>
                                  {bucket ? (
                                    <span style={{
                                      display: 'inline-block', padding: '2px 8px', borderRadius: 4, fontSize: 11, fontWeight: 700,
                                      background: bucket === 'reach' ? '#fee2e2' : bucket === 'match' ? '#fef3c7' : '#f0fdf4',
                                      color: bucketColor,
                                    }}>
                                      {bucketLabel}
                                    </span>
                                  ) : '–'}
                                </td>
                              </tr>
                            );
                          })}
                        </tbody>
                      </table>
                    </div>
                  </div>
                );
              })()}

              {/* ── 冲稳保可视化 Section ───────────────────────────────────────── */}
              {balance && (
                <div
                  data-testid="fill-check-pie-chart"
                  style={{
                    marginTop: 28,
                    background: 'var(--pb-paper)',
                    border: '1px solid var(--pb-border)',
                    borderRadius: 10,
                    overflow: 'hidden',
                  }}
                >
                  <div style={{
                    padding: '14px 20px',
                    background: 'var(--pb-surface-alt)',
                    borderBottom: '1px solid var(--pb-border)',
                  }}>
                    <span style={{ fontWeight: 700, fontSize: 14 }}>
                      {fc.pieChartTitle || (lang === 'zh' ? '冲稳保比例可视化' : 'Reach / Match / Safety Balance')}
                    </span>
                  </div>

                  <div style={{ padding: '24px 28px', display: 'flex', gap: 40, flexWrap: 'wrap', alignItems: 'flex-start' }}>
                    {/* SVG Pie chart */}
                    {(() => {
                      const R = 70;
                      const CX = 80;
                      const CY = 80;
                      const total = balance.total || 1;
                      // Segments: reach (red), match (amber), safety (green)
                      const segments = [
                        { key: 'reach',  count: balance.reach,  pct: balance.reachPct,  color: '#ef4444', label: lang === 'zh' ? '冲刺' : 'Reach' },
                        { key: 'match',  count: balance.match,  pct: balance.matchPct,  color: '#f59e0b', label: lang === 'zh' ? '稳健' : 'Match' },
                        { key: 'safety', count: balance.safety, pct: balance.safetyPct, color: '#22c55e', label: lang === 'zh' ? '保底' : 'Safety' },
                      ];

                      // Build SVG arc paths
                      const toRad = (deg) => (deg * Math.PI) / 180;
                      const polarToCart = (cx, cy, r, angle) => ({
                        x: cx + r * Math.cos(toRad(angle - 90)),
                        y: cy + r * Math.sin(toRad(angle - 90)),
                      });
                      const arcPath = (cx, cy, r, startAngle, endAngle) => {
                        const s = polarToCart(cx, cy, r, startAngle);
                        const e = polarToCart(cx, cy, r, endAngle);
                        const largeArc = endAngle - startAngle > 180 ? 1 : 0;
                        return `M${cx},${cy} L${s.x},${s.y} A${r},${r} 0 ${largeArc} 1 ${e.x},${e.y} Z`;
                      };

                      let startAngle = 0;
                      const paths = segments.map((seg) => {
                        const sweep = (seg.count / total) * 360;
                        const endAngle = startAngle + sweep;
                        const path = sweep > 0 ? arcPath(CX, CY, R, startAngle, endAngle) : null;
                        startAngle = endAngle;
                        return { ...seg, path, sweep };
                      });

                      // Recommended reference arcs (30/50/20) — thin ring
                      const refRing = [
                        { pct: 30, color: '#ef4444' },
                        { pct: 50, color: '#f59e0b' },
                        { pct: 20, color: '#22c55e' },
                      ];
                      let refStart = 0;
                      const refPaths = refRing.map((r) => {
                        const sweep = (r.pct / 100) * 360;
                        const endAngle = refStart + sweep;
                        const p = arcPath(CX, CY, R + 8, refStart, endAngle);
                        refStart = endAngle;
                        return { ...r, path: p };
                      });

                      return (
                        <svg width={CX * 2} height={CY * 2} viewBox={`0 0 ${CX * 2} ${CY * 2}`} role="img" aria-label="冲稳保比例饼图">
                          {/* Reference ring (thin) */}
                          {refPaths.map((rp) => (
                            <path key={`ref-${rp.color}`} d={rp.path} fill={rp.color} opacity={0.12} />
                          ))}
                          {/* Main segments */}
                          {paths.map((seg) => seg.path && (
                            <path key={seg.key} d={seg.path} fill={seg.color} opacity={0.85} />
                          ))}
                          {/* Center white hole (donut) */}
                          <circle cx={CX} cy={CY} r={R * 0.55} fill="var(--pb-paper)" />
                          {/* Center label */}
                          <text x={CX} y={CY - 6} textAnchor="middle" fontSize={11} fontWeight={700} fill="var(--pb-fg)">
                            {balance.total}
                          </text>
                          <text x={CX} y={CY + 8} textAnchor="middle" fontSize={9} fill="var(--pb-fg-muted)">
                            {lang === 'zh' ? '有效志愿' : 'slots'}
                          </text>
                        </svg>
                      );
                    })()}

                    {/* Legend + numbers */}
                    <div style={{ flex: 1, minWidth: 200 }}>
                      {[
                        { key: 'reach',  label: lang === 'zh' ? '冲刺 (Reach)' : 'Reach',  count: balance.reach,  pct: balance.reachPct,  target: 30, color: '#ef4444' },
                        { key: 'match',  label: lang === 'zh' ? '稳健 (Match)' : 'Match',  count: balance.match,  pct: balance.matchPct,  target: 50, color: '#f59e0b' },
                        { key: 'safety', label: lang === 'zh' ? '保底 (Safety)' : 'Safety', count: balance.safety, pct: balance.safetyPct, target: 20, color: '#22c55e' },
                      ].map((row) => (
                        <div key={row.key} style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
                          <span style={{ width: 12, height: 12, borderRadius: '50%', background: row.color, flexShrink: 0 }} />
                          <span style={{ flex: 1, fontSize: 13 }}>{row.label}</span>
                          <span style={{ fontFamily: 'var(--pb-mono)', fontWeight: 700, fontSize: 14, color: row.color }}>{row.pct}%</span>
                          <span style={{ fontSize: 11, color: 'var(--pb-fg-muted)', fontFamily: 'var(--pb-mono)' }}>({row.count})</span>
                          <span style={{ fontSize: 11, color: 'var(--pb-fg-muted)' }}>{lang === 'zh' ? '推荐' : 'target'} {row.target}%</span>
                        </div>
                      ))}
                      {balance.unclassified > 0 && (
                        <div style={{ fontSize: 11, color: 'var(--pb-fg-muted)', marginTop: 4 }}>
                          {balance.unclassified} {lang === 'zh' ? '个志愿缺少分数数据（未分类）' : 'slots missing score data (unclassified)'}
                        </div>
                      )}
                    </div>
                  </div>

                  {/* Warnings */}
                  {balance.warnings.length > 0 && (
                    <div
                      data-testid="fill-check-balance-warning"
                      style={{
                        margin: '0 20px 20px',
                        padding: '14px 16px',
                        background: '#fef3c7',
                        border: '1px solid #fcd34d',
                        borderRadius: 8,
                        display: 'flex',
                        flexDirection: 'column',
                        gap: 6,
                      }}
                    >
                      {balance.warnings.map((w, wi) => (
                        <div key={wi} style={{ display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 13, color: '#92400e' }}>
                          <span style={{ fontWeight: 700, flexShrink: 0 }}>!</span>
                          <span>{w}</span>
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              )}

              {/* Re-check button */}
              <div style={{ marginTop: 20, textAlign: 'right' }}>
                <button
                  className="pb-btn pb-btn-link pb-btn-sm"
                  onClick={() => { setResult(null); setSubmitted(false); setBalance(null); }}
                  data-testid="recheck-btn"
                >
                  {lang === 'zh' ? '修改后重新检查' : 'Edit & Re-check'}
                </button>
              </div>
            </div>
          )}

          {/* Data note */}
          <div style={{ marginTop: 32, fontSize: 11, color: 'var(--pb-fg-muted)', lineHeight: 1.6 }}>
            {lang === 'zh'
              ? '* 检查结果为启发性建议，最终志愿填报以考生本人判断及官方规定为准。分数参考建议使用近 3 年录取数据。'
              : '* Results are heuristic suggestions. Always rely on your own judgment and official guidelines for final decisions.'}
          </div>
        </div>
      </section>

      <PBFooter />
    </div>
  );
};

// Expose to window
Object.assign(window, { GaokaoFillCheckPage });
