/* ============================================================
   AcademicView.jsx — วิทยฐานะครู (ระบบ ว.PA / ว.9-2564 / ว.4-2564)
   • ครูกรอกข้อมูลของตนเอง — วิทยฐานะปัจจุบัน · PA 3 รอบ · เงื่อนไขลดระยะเวลา
   • Animated stepper แสดงความคืบหน้าตามเกณฑ์จริงของ ก.ค.ศ.
   ============================================================ */

// วิทยฐานะสายครู (ว.9/2564) เส้นทาง 4-4-4-4
const TEACHER_RANKS = [
  {id:'kp',  short:'ครูผู้ช่วย',  full:'ครูผู้ช่วย',            level:0, color:'#94a3b8', passPct:0,  needsAcademicWork:false},
  {id:'kh1', short:'คศ.1',        full:'ครู (คศ.1)',            level:1, color:'#22c55e', passPct:0,  needsAcademicWork:false},
  {id:'kh2', short:'ชนก. (คศ.2)', full:'ครูชำนาญการ (คศ.2)',    level:2, color:'#0ea5e9', passPct:65, needsAcademicWork:false},
  {id:'kh3', short:'ชนพ. (คศ.3)', full:'ครูชำนาญการพิเศษ (คศ.3)', level:3, color:'#8b5cf6', passPct:70, needsAcademicWork:false},
  {id:'kh4', short:'ชช. (คศ.4)',  full:'ครูเชี่ยวชาญ (คศ.4)',   level:4, color:'#ec4899', passPct:75, needsAcademicWork:true},
  {id:'kh5', short:'ชชพ. (คศ.5)', full:'ครูเชี่ยวชาญพิเศษ (คศ.5)', level:5, color:'#f59e0b', passPct:80, needsAcademicWork:true},
];
// วิทยฐานะสายผู้บริหาร (ว.10/2564) — ผอ./รอง ผอ.
const ADMIN_RANKS = [
  {id:'ap0', short:'ยังไม่มี',    full:'ยังไม่มีวิทยฐานะ',                   level:1, color:'#94a3b8', passPct:0,  needsAcademicWork:false},
  {id:'ap2', short:'ชนก. (คศ.2)', full:'ชำนาญการ (คศ.2)',                    level:2, color:'#0ea5e9', passPct:65, needsAcademicWork:false},
  {id:'ap3', short:'ชนพ. (คศ.3)', full:'ชำนาญการพิเศษ (คศ.3)',               level:3, color:'#8b5cf6', passPct:70, needsAcademicWork:false},
  {id:'ap4', short:'ชช. (คศ.4)',  full:'เชี่ยวชาญ (คศ.4)',                   level:4, color:'#ec4899', passPct:75, needsAcademicWork:true},
  {id:'ap5', short:'ชชพ. (คศ.5)', full:'เชี่ยวชาญพิเศษ (คศ.5)',              level:5, color:'#f59e0b', passPct:80, needsAcademicWork:true, needsExpansion:true},
];
// backward-compat alias
const ACADEMIC_RANKS = TEACHER_RANKS;
// ค้นหา rank โดยไม่สนใจว่าเป็นสายไหน (IDs ไม่ซ้ำระหว่างสาย: kp/kh* vs ap*)
const rankById = id => TEACHER_RANKS.find(r=>r.id===id) || ADMIN_RANKS.find(r=>r.id===id) || TEACHER_RANKS[0];
const ranksFor = (isExec)=> isExec ? ADMIN_RANKS : TEACHER_RANKS;
// ตรวจว่าตำแหน่ง approver = ผู้บริหารสถานศึกษาหรือไม่
const isExecutiveRole = role => ['director','deputy_academic','deputy_personnel'].includes(role);

// 5 ขั้นตอนขอวิทยฐานะสายครู (ว.9/2564)
const REQUEST_STEPS_TEACHER = [
  {id:1, label:'ตรวจคุณสมบัติ',       sub:'ครบระยะถือครอง · ผ่าน PA 3 รอบ ≥70% · ไม่ถูกวินัย',       icon:'checkCircle'},
  {id:2, label:'เตรียมผลงาน 3 ด้าน',   sub:'การจัดการเรียนรู้ · ส่งเสริมสนับสนุน · ผลลัพธ์ผู้เรียน',    icon:'clipboard'},
  {id:3, label:'ยื่นคำขอ (DPA)',      sub:'ยื่นผ่านระบบ DPA → ต้นสังกัด → ก.ค.ศ.',                  icon:'send'},
  {id:4, label:'คณะกรรมการประเมิน',    sub:'3 กรรมการ (ผู้ทรงคุณวุฒิภายนอก) · ตัดสิน ≥เกณฑ์ %',       icon:'hourglass'},
  {id:5, label:'อ.ก.ค.ศ. อนุมัติ',    sub:'ประกาศผล · คำสั่งเลื่อนวิทยฐานะ',                       icon:'award'},
];
// 5 ขั้นตอนขอวิทยฐานะสายผู้บริหาร (ว.10/2564)
const REQUEST_STEPS_EXEC = [
  {id:1, label:'ตรวจคุณสมบัติ',       sub:'ครบระยะถือครอง · ผ่าน PA 2 ปีการศึกษาต่อเนื่อง · ไม่ถูกวินัย',   icon:'checkCircle'},
  {id:2, label:'เตรียมผลงาน 3 ด้าน',   sub:'บริหารวิชาการ · จัดการสถานศึกษา · ผลงานวิจัย/นวัตกรรม',         icon:'clipboard'},
  {id:3, label:'ยื่นคำขอ (DPA)',      sub:'ยื่นผ่านระบบ DPA → เขตพื้นที่ → ก.ค.ศ.',                       icon:'send'},
  {id:4, label:'คณะกรรมการประเมิน',    sub:'3 กรรมการ · ตัดสิน ≥เกณฑ์ % + ประเมินผลลัพธ์เชิงประจักษ์',       icon:'hourglass'},
  {id:5, label:'อ.ก.ค.ศ. อนุมัติ',    sub:'ประกาศผล · คำสั่งเลื่อนวิทยฐานะผู้บริหาร',                    icon:'award'},
];
const stepsFor = isExec => isExec ? REQUEST_STEPS_EXEC : REQUEST_STEPS_TEACHER;
const REQUEST_STEPS = REQUEST_STEPS_TEACHER;   // backward-compat

// เงื่อนไขลดระยะเวลา (ว.4/2564) — 5 ข้อ · เข้า 1 ข้อ → ลดเป็น 3 ปี
const REDUCE_CONDITIONS = [
  {id:'lang',    label:'ทักษะภาษาต่างประเทศ',            sub:'CEFR B1 ขึ้นไป · หรือคะแนน TOEIC/TOEFL/IELTS ตามเกณฑ์'},
  {id:'special', label:'ปฏิบัติงานในพื้นที่พิเศษ',        sub:'เขตพัฒนาพิเศษ · ชายแดน · ทุรกันดาร'},
  {id:'degree',  label:'วุฒิ ป.โท/ป.เอก ตรงสายงาน',       sub:'สำเร็จการศึกษาระดับสูงกว่า ป.ตรี ในสาขาที่สอน'},
  {id:'cq',      label:'ผ่านการประเมินกรอบคุณวุฒิวิชาชีพ', sub:'ผ่านกรอบคุณวุฒิวิชาชีพครูจากคุรุสภา'},
  {id:'salary',  label:'ผลประเมินเลื่อนเงินเดือนดีเด่น',   sub:'ระดับดีเด่น 4 รอบต่อเนื่อง (2 ปี)'},
];

// 3 ด้านของการประเมิน วPA (สายครู · ว.9/2564)
const PA_COMPONENTS_TEACHER = [
  {id:'learn',   label:'ด้านการจัดการเรียนรู้',    weight:60, sub:'แผนการจัดการเรียนรู้ + วิดีโอบันทึกการสอน (15–20 นาที)', icon:'book'},
  {id:'support', label:'ด้านการส่งเสริมสนับสนุน',  weight:20, sub:'วิดีโอสภาพปัญหา ที่มา แรงบันดาลใจในการพัฒนา (5–10 นาที)', icon:'users'},
  {id:'result',  label:'ด้านผลลัพธ์ผู้เรียน',      weight:20, sub:'หลักฐานผลงาน/พฤติกรรม/ผลสัมฤทธิ์ของผู้เรียน',         icon:'award'},
];
// 3 ด้านของการประเมิน วPA (สายผู้บริหาร · ว.10/2564)
const PA_COMPONENTS_EXEC = [
  {id:'academic', label:'การบริหารวิชาการ',             weight:40, sub:'กลยุทธ์พัฒนาคุณภาพวิชาการ · นวัตกรรมการบริหาร · แผนพัฒนาโรงเรียน', icon:'book'},
  {id:'manage',   label:'การบริหารจัดการสถานศึกษา',      weight:20, sub:'ผลลัพธ์คุณภาพผู้เรียน/สถานศึกษา · ประสิทธิภาพงานสนับสนุน', icon:'shield'},
  {id:'research', label:'ผลงานทางวิชาการ (วิจัย/นวัตกรรม)', weight:40, sub:'งานวิจัย R&D 4 ขั้นตอน + นวัตกรรมการบริหาร (คศ.4 ขึ้นไป)', icon:'award'},
];
const paComponentsFor = isExec => isExec ? PA_COMPONENTS_EXEC : PA_COMPONENTS_TEACHER;
// backward-compat
const PA_COMPONENTS = PA_COMPONENTS_TEACHER;

// การเก็บข้อมูล — localStorage (ต่อคน)
function useAcademicRecord(teacherId, isExec){
  const key = 'ntk_academic_v2_'+teacherId;
  const [rec, setRec] = React.useState(()=>{
    try{
      const raw=localStorage.getItem(key);
      if(raw){
        const saved = JSON.parse(raw);
        // ถ้าบทบาทเปลี่ยน (ครู ↔ ผู้บริหาร) ให้ merge default ของบทบาทใหม่
        if(saved.isExec !== !!isExec) return {..._defaultRec(isExec), ...saved, isExec:!!isExec, components:_defaultRec(isExec).components, currentRankId:isExec?'ap0':'kp', targetRankId:isExec?'ap2':'kh1'};
        return {..._defaultRec(isExec), ...saved};
      }
    }catch(e){}
    return _defaultRec(isExec);
  });
  const update = patch=> setRec(r=>{ const n={...r,...patch}; try{localStorage.setItem(key, JSON.stringify(n));}catch(e){} return n; });
  return [rec, update];
}
function _defaultRec(isExec){
  return {
    currentRankId: isExec ? 'ap0' : 'kp',
    targetRankId:  isExec ? 'ap2' : 'kh1',
    qualifyDate:'',
    targetSubmitDate:'',
    submittedAt:'', approvedAt:'',
    disciplineClean:true,
    paRounds: isExec
      ? [ {round:1, date:'', score:'', evaluator:'', pass:false},
          {round:2, date:'', score:'', evaluator:'', pass:false} ]  // ว.10 = อย่างน้อย 2 ปีการศึกษา
      : [ {round:1, date:'', score:'', evaluator:'', pass:false},
          {round:2, date:'', score:'', evaluator:'', pass:false},
          {round:3, date:'', score:'', evaluator:'', pass:false} ], // ว.9 = 3 รอบ
    reduceConditions:{lang:false, special:false, degree:false, cq:false, salary:false},
    components: isExec
      ? { academic:{planned:false, evidence:false, video:false, note:''},
          manage:  {outcome:false, evidence:false, note:''},
          research:{research:false, innovation:false, published:false, note:''} }
      : { learn:  {plan:false, video:false, note:''},
          support:{video:false, note:''},
          result: {evidence:false, note:''} },
    academicWork:{ title:'', published:false, publishVenue:'', publishDate:'',
                   expansion:false, expansionNote:'', critique:false },
    step:1, status:'in_progress', notes:'',
    isExec: !!isExec,
  };
}

// ── helpers ──
function yearsBetween(iso, todayIso){
  if(!iso) return 0;
  try{
    const a = new Date(iso+'T00:00:00'); const b = new Date((todayIso||new Date().toISOString().slice(0,10))+'T00:00:00');
    return (b - a) / (365.25 * 86400 * 1000);
  }catch{ return 0; }
}
function thaiDateFull(iso){
  if(!iso) return '';
  try{ const d = new Date(iso+'T00:00:00'); return `${d.getDate()} ${THAI_MONTHS[d.getMonth()]} ${d.getFullYear()+543}`; }catch{ return iso; }
}

// ── eligibility check ──
function checkEligibility(rec){
  const isExec = !!rec.isExec;
  const tgt = rankById(rec.targetRankId);
  const passPct = tgt.passPct || 70;
  const anyReduce = Object.values(rec.reduceConditions||{}).some(Boolean);
  const minYears = anyReduce ? 3 : 4;
  const years = yearsBetween(rec.qualifyDate);
  const paPass = (rec.paRounds||[]).filter(r=> Number(r.score)>=70).length;
  const paNeeded = isExec ? 2 : 3;
  const compFilled = _compScore(rec, isExec);
  const w = rec.academicWork||{};
  // ผลงานทางวิชาการ — สายผู้บริหาร ต้องมี R&D · ผอ.เชี่ยวชาญพิเศษ (ap5) ต้องมีการขยายผล+บทวิจารณ์เพิ่ม
  let workOk = true, workNeed = false;
  if(tgt.needsAcademicWork){
    workNeed = true;
    workOk = !!w.title && !!w.published;
    if(isExec && tgt.needsExpansion){ workOk = workOk && !!w.expansion && !!w.critique; }
  }
  return {
    tgt, passPct, anyReduce, minYears, isExec,
    tenure: { ok: years>=minYears, years, minYears },
    pa:     { ok: paPass>=paNeeded, count: paPass, need: paNeeded },
    discipline: { ok: !!rec.disciplineClean },
    components: { ok: compFilled>=3, count: compFilled, need: 3 },
    academicWork: { ok: workOk, need: workNeed, needsExpansion: isExec && tgt.needsExpansion },
  };
}
function _compScore(rec, isExec){
  const c = rec.components||{};
  let s = 0;
  if(isExec){
    if(c.academic?.planned && c.academic?.evidence) s++;
    if(c.manage?.outcome && c.manage?.evidence) s++;
    if(c.research?.research || c.research?.innovation) s++;
  } else {
    if(c.learn?.plan && c.learn?.video) s++;
    if(c.support?.video) s++;
    if(c.result?.evidence) s++;
  }
  return s;
}

// ── คำนวณ step อัตโนมัติ ──
function computeStep(rec, elig){
  if(rec.approvedAt) return 5;
  if(rec.submittedAt) return 4;
  if(elig.components.ok) return 3;
  if(elig.tenure.ok && elig.pa.ok && elig.discipline.ok) return 2;
  return 1;
}
function computeProgressPct(rec, elig){
  const isExec = !!rec.isExec;
  const parts = [
    elig.tenure.ok ? 1 : Math.min(1, elig.tenure.years / elig.tenure.minYears),
    elig.pa.ok ? 1 : elig.pa.count/elig.pa.need,
    elig.discipline.ok ? 1 : 0,
    Math.min(1, _compScore(rec, isExec)/3),
    elig.academicWork.need ? (elig.academicWork.ok ? 1 : 0) : 1,
    rec.submittedAt ? 1 : 0,
  ];
  return Math.round(parts.reduce((s,x)=>s+x,0) / parts.length * 100);
}

// ─────────────────────────────────────────────────────────
// Animated Stepper
// ─────────────────────────────────────────────────────────
function AcademicStepper({currentStep, targetRank, steps}){
  const stepList = steps || REQUEST_STEPS;
  const pct = Math.round((currentStep-1) / (stepList.length-1) * 100);
  return (
    <div className="ac-stepper">
      <div className="ac-step-track">
        <div className="ac-step-fill" style={{width: pct+'%', background: targetRank.color}}></div>
      </div>
      <div className="ac-steps">
        {stepList.map(s=>{
          const done = s.id < currentStep;
          const active = s.id === currentStep;
          const upcoming = s.id > currentStep;
          return (
            <div key={s.id} className={`ac-step ${done?'done':''} ${active?'active':''} ${upcoming?'upcoming':''}`}>
              <div className="ac-step-dot" style={done||active?{background: targetRank.color, borderColor: targetRank.color}:null}>
                <Icon name={done?'check':s.icon} size={done?15:14}/>
                {active && <span className="ac-step-pulse" style={{borderColor: targetRank.color}}></span>}
              </div>
              <div className="ac-step-meta">
                <div className="ac-step-lbl">{s.label}</div>
                <div className="ac-step-sub">{s.sub}</div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────
// Eligibility Checklist Card (5 criteria)
// ─────────────────────────────────────────────────────────
function EligibilityCard({elig, tgt}){
  const items = [
    { ok:elig.tenure.ok, label:`ครบระยะเวลาถือครอง ${elig.minYears} ปี`,
      detail:`ปัจจุบัน ${elig.tenure.years.toFixed(1)} ปี ${elig.anyReduce?'· ใช้สิทธิ์ลดระยะเวลา ว.4/2564':''}`, icon:'clock' },
    { ok:elig.pa.ok, label:`ผลประเมิน PA ผ่านเกณฑ์ ${elig.isExec?'2 ปีการศึกษาต่อเนื่อง':'3 รอบต่อเนื่อง'}`,
      detail:`ปัจจุบัน ${elig.pa.count}/${elig.pa.need} รอบ (≥70% ต่อรอบ)`, icon:'checkCircle' },
    { ok:elig.discipline.ok, label:`ไม่ถูกดำเนินการทางวินัยใน 4 ปี`,
      detail:elig.discipline.ok?'ประวัติสะอาด':'ตรวจสอบและติดต่องานบุคคล', icon:'shield' },
    { ok:elig.components.ok, label:`เตรียมผลงานครบ 3 ด้าน`,
      detail:`ปัจจุบัน ${elig.components.count}/3 ด้าน`, icon:'clipboard' },
    ...(elig.academicWork.need ? [{ ok:elig.academicWork.ok, label:'ผลงานทางวิชาการ (ต้องมีสำหรับ '+tgt.short+')',
      detail:elig.academicWork.ok?'มีผลงาน · เผยแพร่แล้ว':'ยังไม่ครบ · ต้องมีผลงานที่เผยแพร่', icon:'book' }] : []),
  ];
  const passed = items.filter(i=>i.ok).length;
  return (
    <Card className="mt16">
      <CardHead icon="filter" title="ตรวจคุณสมบัติผู้ขอวิทยฐานะ"
        sub={`ผ่าน ${passed}/${items.length} เกณฑ์ · เกณฑ์ % ที่ต้องได้ทุกกรรมการ: ≥ ${elig.passPct}%`}/>
      <div className="card-pad">
        <div className="ac-elig">
          {items.map((it,i)=>(
            <div key={i} className={`ac-elig-item ${it.ok?'ok':'no'}`}>
              <span className={`ac-elig-ic ${it.ok?'ok':'no'}`} style={it.ok?{background:tgt.color,borderColor:tgt.color}:null}>
                <Icon name={it.ok?'check':it.icon} size={14}/>
              </span>
              <div className="ac-elig-body">
                <div className="ac-elig-lbl">{it.label}</div>
                <div className="ac-elig-sub">{it.detail}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </Card>
  );
}

// ─────────────────────────────────────────────────────────
// AcademicView — หน้าหลัก
// ─────────────────────────────────────────────────────────
function AcademicView({me, approverRole}){
  const isExec = isExecutiveRole(approverRole);
  const [rec, update] = useAcademicRecord(me.id, isExec);
  const [tab, setTab] = React.useState('overview');
  const curRank = rankById(rec.currentRankId);
  const tgtRank = rankById(rec.targetRankId);
  const elig = checkEligibility(rec);
  const autoStep = computeStep(rec, elig);
  const pct = computeProgressPct(rec, elig);
  const stepsList = stepsFor(isExec);
  const paComps = paComponentsFor(isExec);
  const rankList = ranksFor(isExec);
  const execTitle = approverRole==='director' ? 'ผู้อำนวยการโรงเรียน'
                  : approverRole==='deputy_academic' ? 'รองผู้อำนวยการฝ่ายวิชาการ'
                  : approverRole==='deputy_personnel' ? 'รองผู้อำนวยการฝ่ายบุคคล' : 'ผู้บริหารสถานศึกษา';

  React.useEffect(()=>{ if(rec.step !== autoStep) update({step: autoStep}); /* eslint-disable-next-line */ },[autoStep]);

  // ── auto-correct target rank เมื่อไม่อยู่ในลิสต์ที่ valid (สูงกว่าปัจจุบัน) ──
  React.useEffect(()=>{
    const validNext = rankList.filter(r=>r.level>curRank.level);
    if(validNext.length && !validNext.some(r=>r.id===rec.targetRankId)){
      update({targetRankId: validNext[0].id});
    }
  /* eslint-disable-next-line */ },[rec.currentRankId, isExec]);

  const canRankUp = tgtRank.level > curRank.level;

  return (
    <div>
      <div className="flex ac jb wrap gap12" style={{marginBottom:18}}>
        <div>
          <h1 style={{fontSize:22,color:'var(--brand-900)'}}>วิทยฐานะของฉัน {isExec && <span style={{fontSize:14,color:'var(--brand-600)',marginLeft:8}}>· {execTitle}</span>}</h1>
          <p style={{margin:'4px 0 0',color:'var(--ink-2)',fontSize:14}}>
            {isExec
              ? <>ระบบติดตามการขอมี/เลื่อนวิทยฐานะผู้บริหารตามหลักเกณฑ์ <b>ว.10/2564</b> และ <b>ว.4/2564</b> — ก.ค.ศ.</>
              : <>ระบบติดตามการขอมี/เลื่อนวิทยฐานะตามหลักเกณฑ์ <b>ว.9/2564</b> และ <b>ว.4/2564</b> — ก.ค.ศ.</>
            }
          </p>
        </div>
      </div>

      {/* Rank hero */}
      <div className="ac-hero">
        <div className="ac-hero-left">
          <div className="ac-hero-lbl">วิทยฐานะปัจจุบัน</div>
          <div className="ac-badge" style={{background:curRank.color+'20', color:curRank.color, borderColor:curRank.color+'55'}}>
            <Icon name="award" size={18}/> {curRank.full}
          </div>
          <div className="ac-hero-meta">
            {rec.qualifyDate ? `ได้รับเมื่อ ${thaiDateFull(rec.qualifyDate)} · ถือครองมา ${elig.tenure.years.toFixed(1)} ปี` : '— ยังไม่ระบุวันที่ได้รับ —'}
          </div>
        </div>
        <div className="ac-hero-arrow">
          <div className="ac-arrow-line"><div className="ac-arrow-fill" style={{width:pct+'%', background:tgtRank.color}}></div></div>
          <div className="ac-arrow-pct" style={{color:tgtRank.color}}>{pct}%</div>
          <Icon name="chevronRight" size={22} style={{color:tgtRank.color}}/>
        </div>
        <div className="ac-hero-right">
          <div className="ac-hero-lbl">วิทยฐานะเป้าหมาย</div>
          <div className="ac-badge ac-badge-target" style={{background:tgtRank.color+'15', color:tgtRank.color, borderColor:tgtRank.color+'55'}}>
            <Icon name="award" size={18}/> {tgtRank.full}
          </div>
          <div className="ac-hero-meta">
            {rec.targetSubmitDate ? `กำหนดยื่น ${thaiDateFull(rec.targetSubmitDate)}` : (canRankUp?`ต้องได้ ≥ ${tgtRank.passPct}% จากกรรมการทุกท่าน`:'— เลือกเป้าหมายที่สูงกว่า —')}
          </div>
        </div>
      </div>

      {!canRankUp && (
        <div className="note-box mt16" style={{background:'#fef3c7',borderColor:'#fcd34d'}}>
          <Icon name="info" size={18} style={{color:'#d97706',flex:'none'}}/>
          <div>เลือกวิทยฐานะเป้าหมายที่สูงกว่าปัจจุบัน (แท็บ "ข้อมูลผู้ขอ") เพื่อเริ่มติดตามความคืบหน้า</div>
        </div>
      )}

      {/* Sub-tabs */}
      <div className="ac-subtabs mt16">
        {[
          ['overview','ภาพรวม','layers'],
          ['qualify','ข้อมูลผู้ขอ','user'],
          ['pa', isExec ? 'PA 2 ปี' : 'PA 3 รอบ', 'checkCircle'],
          ['components','ผลงาน 3 ด้าน','clipboard'],
          ['reduce','ลดระยะเวลา','clock'],
          ...(tgtRank.needsAcademicWork ? [['work','ผลงานทางวิชาการ','book']] : []),
        ].map(([id,lbl,ic])=>(
          <button key={id} className={`ac-subtab ${tab===id?'active':''}`} onClick={()=>setTab(id)}>
            <Icon name={ic} size={14}/>{lbl}
          </button>
        ))}
      </div>

      {tab==='overview' && (<>
        <Card className="mt16">
          <CardHead icon="layers" title="ความคืบหน้าการขอวิทยฐานะ" sub={`ขั้นที่ ${rec.step} / ${stepsList.length}`}/>
          <div className="card-pad"><AcademicStepper currentStep={rec.step} targetRank={tgtRank} steps={stepsList}/></div>
        </Card>
        <EligibilityCard elig={elig} tgt={tgtRank}/>
      </>)}

      {tab==='qualify' && <QualifyForm rec={rec} update={update} curRank={curRank} tgtRank={tgtRank} rankList={rankList}/>}
      {tab==='pa' && <PARoundsCard rec={rec} update={update} tgtRank={tgtRank} isExec={isExec}/>}
      {tab==='components' && <ComponentsCard rec={rec} update={update} tgtRank={tgtRank} paComps={paComps} isExec={isExec}/>}
      {tab==='reduce' && <ReduceCard rec={rec} update={update} tgtRank={tgtRank} elig={elig}/>}
      {tab==='work' && tgtRank.needsAcademicWork && <AcademicWorkCard rec={rec} update={update} tgtRank={tgtRank} isExec={isExec}/>}

      <div className="note-box mt16">
        <Icon name="info" size={18} style={{flex:'none'}}/>
        <div>
          <div>ข้อมูลบันทึกในเครื่องของท่าน (localStorage) เท่านั้น · ยังไม่ส่งขึ้นระบบส่วนกลาง</div>
          <div style={{marginTop:6,fontSize:12.5,color:'var(--ink-3)'}}>
            {isExec
              ? <>อ้างอิง: <b>ว.10/2564</b> (การประเมินตำแหน่งและวิทยฐานะผู้บริหารสถานศึกษา) · <b>ว.4/2564</b> (การลดระยะเวลา) — สำนักงาน ก.ค.ศ.</>
              : <>อ้างอิง: <b>ว.9/2564</b> (การประเมินตำแหน่งและวิทยฐานะครู) · <b>ว.4/2564</b> (การลดระยะเวลา) — สำนักงาน ก.ค.ศ.</>
            }
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── Sub-forms ───
function QualifyForm({rec, update, curRank, tgtRank, rankList}){
  const list = rankList || ACADEMIC_RANKS;
  const [saved, setSaved] = React.useState(false);
  const [savedAt, setSavedAt] = React.useState(()=>{
    try{ return localStorage.getItem('ntk_academic_qualify_savedAt') || ''; }catch{ return ''; }
  });
  const doSave = ()=>{
    // ข้อมูลถูก sync ทันทีทุกครั้งที่แก้ (auto-save) · ปุ่มนี้ยืนยัน + timestamp
    const now = new Date().toISOString();
    try{ localStorage.setItem('ntk_academic_qualify_savedAt', now); }catch{}
    setSavedAt(now);
    setSaved(true);
    setTimeout(()=>setSaved(false), 2500);
  };
  return (
    <Card className="mt16">
      <CardHead icon="user" title="ข้อมูลผู้ขอวิทยฐานะ"
        sub={savedAt ? `บันทึกล่าสุด: ${new Date(savedAt).toLocaleString('th-TH',{dateStyle:'medium',timeStyle:'short'})}` : 'ยังไม่ได้บันทึก · ข้อมูลจะ auto-save ทุกการแก้ไข'}/>
      <div className="card-pad">
        <div className="form-grid-2">
          <div className="field">
            <label>วิทยฐานะปัจจุบัน</label>
            <select className="sel" value={rec.currentRankId} onChange={e=>update({currentRankId:e.target.value})}>
              {list.map(r=><option key={r.id} value={r.id}>{r.full}</option>)}
            </select>
          </div>
          <div className="field">
            <label>วิทยฐานะเป้าหมาย</label>
            <select className="sel" value={rec.targetRankId} onChange={e=>update({targetRankId:e.target.value})}>
              {list.filter(r=>r.level>curRank.level).map(r=><option key={r.id} value={r.id}>{r.full} · ต้องได้ ≥{r.passPct}%</option>)}
            </select>
          </div>
          <div className="field">
            <label>วันที่ได้รับวิทยฐานะปัจจุบัน <span className="tiny" style={{color:'var(--ink-3)'}}>(นับระยะถือครอง)</span></label>
            <input type="date" className="inp" value={rec.qualifyDate} onChange={e=>update({qualifyDate:e.target.value})}/>
          </div>
          <div className="field">
            <label>วันที่คาดว่าจะยื่นคำขอ</label>
            <input type="date" className="inp" value={rec.targetSubmitDate} onChange={e=>update({targetSubmitDate:e.target.value})}/>
          </div>
          <div className="field">
            <label>วันที่ยื่นคำขอจริง (ถ้ายื่นแล้ว)</label>
            <input type="date" className="inp" value={rec.submittedAt} onChange={e=>update({submittedAt:e.target.value})}/>
          </div>
          <div className="field">
            <label>วันที่ อ.ก.ค.ศ. อนุมัติ (ถ้าได้แล้ว)</label>
            <input type="date" className="inp" value={rec.approvedAt} onChange={e=>update({approvedAt:e.target.value})}/>
          </div>
        </div>
        <label className="ac-check-row mt12">
          <input type="checkbox" checked={rec.disciplineClean} onChange={e=>update({disciplineClean:e.target.checked})}/>
          <span>ไม่ถูกดำเนินการทางวินัย · ไม่ถูกลงโทษวินัยร้ายแรง ภายใน 4 ปีที่ผ่านมา</span>
        </label>
        <div className="field mt12">
          <label>บันทึกเพิ่มเติม</label>
          <textarea className="inp" rows={3} value={rec.notes} onChange={e=>update({notes:e.target.value})}
            placeholder="อาทิ ปัญหาที่พบระหว่างเตรียมเอกสาร · สิ่งที่ต้องการปรึกษาผู้บริหาร"/>
        </div>

        <div className="flex ac jb wrap gap8 mt16" style={{paddingTop:14,borderTop:'1px dashed var(--line)'}}>
          <div className="tiny" style={{color:'var(--ink-3)'}}>
            <Icon name="info" size={12} style={{verticalAlign:'-2px',marginRight:4}}/>
            ระบบบันทึกอัตโนมัติทุกการแก้ไข · กด "บันทึกข้อมูล" เพื่อยืนยันและบันทึกเวลา
          </div>
          <button className={`btn ${saved?'':'primary'}`} onClick={doSave}
            style={saved?{background:'var(--green)',color:'#fff',borderColor:'var(--green)'}:null}>
            <Icon name={saved?'checkCircle':'check'} size={16}/>
            {saved ? 'บันทึกเรียบร้อยแล้ว' : 'บันทึกข้อมูล'}
          </button>
        </div>
      </div>
    </Card>
  );
}

function PARoundsCard({rec, update, tgtRank, isExec}){
  const setRound = (i, patch)=>{
    const rounds = (rec.paRounds||[]).map((r,idx)=> idx===i ? {...r, ...patch, pass: Number(patch.score ?? r.score)>=70} : r);
    update({paRounds:rounds});
  };
  return (
    <Card className="mt16">
      <CardHead icon="checkCircle" title={`ผลการประเมิน PA ${isExec?'2 ปีการศึกษาต่อเนื่อง':'3 รอบต่อเนื่อง'}`}
        sub={`ต้องได้ ≥ 70% ในทุกรอบ (คะแนนรวม) จึงจะยื่นขอวิทยฐานะได้${isExec?' · หลักเกณฑ์ ว.10/2564':' · หลักเกณฑ์ ว.9/2564'}`}/>
      <div className="card-pad">
        <div className="ac-rounds">
          {(rec.paRounds||[]).map((r,i)=>{
            const pass = Number(r.score)>=70;
            return (
              <div key={i} className={`ac-round ${pass?'pass':(r.score?'fail':'')}`}>
                <div className="ac-round-h">
                  <span className="ac-round-num" style={pass?{background:tgtRank.color,borderColor:tgtRank.color,color:'#fff'}:null}>{r.round}</span>
                  <div style={{flex:1}}>
                    <div className="ac-round-t">รอบที่ {r.round}</div>
                    <div className="ac-round-s">{pass?'ผ่านเกณฑ์ ≥70%':(r.score?'ไม่ผ่านเกณฑ์':'ยังไม่ได้กรอก')}</div>
                  </div>
                  {pass && <span className="ac-round-tick" style={{background:tgtRank.color}}><Icon name="check" size={14}/></span>}
                </div>
                <div className="form-grid-2 mt8">
                  <div className="field"><label className="tiny">วันที่ประเมิน</label>
                    <input type="date" className="inp" value={r.date} onChange={e=>setRound(i,{date:e.target.value})}/></div>
                  <div className="field"><label className="tiny">คะแนนรวม (%)</label>
                    <input type="number" min="0" max="100" className="inp" value={r.score} onChange={e=>setRound(i,{score:e.target.value})}/></div>
                </div>
                <div className="field mt8"><label className="tiny">ผู้ประเมิน</label>
                  <input type="text" className="inp" value={r.evaluator} placeholder="ชื่อผู้ประเมิน / ตำแหน่ง"
                    onChange={e=>setRound(i,{evaluator:e.target.value})}/></div>
              </div>
            );
          })}
        </div>
      </div>
    </Card>
  );
}

function ComponentsCard({rec, update, tgtRank, paComps, isExec}){
  const list = paComps || PA_COMPONENTS;
  const c = rec.components||{};
  const setC = (id, patch)=> update({components:{...c, [id]:{...(c[id]||{}), ...patch}}});
  const isDone = (compId, val)=>{
    if(isExec){
      if(compId==='academic') return val.planned && val.evidence;
      if(compId==='manage')   return val.outcome && val.evidence;
      if(compId==='research') return val.research || val.innovation;
    }
    if(compId==='learn')   return val.plan && val.video;
    if(compId==='support') return val.video;
    if(compId==='result')  return val.evidence;
    return false;
  };
  return (
    <Card className="mt16">
      <CardHead icon="clipboard" title="ผลงาน 3 ด้านตามข้อตกลง PA"
        sub={isExec ? 'ตามหลักเกณฑ์ ก.ค.ศ. ว.10/2564 — บริหารวิชาการ 40 · จัดการสถานศึกษา 20 · ผลงานวิชาการ 40'
                    : 'ตามหลักเกณฑ์ ก.ค.ศ. ว.9/2564 — ต้องนำเสนอครบทั้ง 3 ด้าน'}/>
      <div className="card-pad">
        <div className="ac-comps">
          {list.map(comp=>{
            const val = c[comp.id] || {};
            const done = isDone(comp.id, val);
            return (
              <div key={comp.id} className={`ac-comp ${done?'done':''}`}>
                <div className="ac-comp-h">
                  <span className="ac-comp-ic" style={done?{background:tgtRank.color,color:'#fff'}:null}><Icon name={comp.icon} size={18}/></span>
                  <div style={{flex:1}}>
                    <div className="ac-comp-t">{comp.label} {comp.weight && <span className="tiny" style={{color:'var(--ink-3)',fontWeight:400,marginLeft:6}}>({comp.weight} คะแนน)</span>}</div>
                    <div className="ac-comp-s">{comp.sub}</div>
                  </div>
                  {done && <span className="ac-comp-tick" style={{background:tgtRank.color}}><Icon name="check" size={14}/></span>}
                </div>
                <div className="ac-comp-body">
                  {/* ครู */}
                  {comp.id==='learn' && <>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.plan} onChange={e=>setC('learn',{plan:e.target.checked})}/>
                      <span>แผนการจัดการเรียนรู้ (Lesson Plan) พร้อมสื่อ/นวัตกรรม</span></label>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.video} onChange={e=>setC('learn',{video:e.target.checked})}/>
                      <span>วิดีโอบันทึกการสอน 15–20 นาที · ตรงตามแผนที่ยื่น</span></label>
                  </>}
                  {comp.id==='support' && <>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.video} onChange={e=>setC('support',{video:e.target.checked})}/>
                      <span>วิดีโอสภาพปัญหา ที่มา แรงบันดาลใจ 5–10 นาที</span></label>
                  </>}
                  {comp.id==='result' && <>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.evidence} onChange={e=>setC('result',{evidence:e.target.checked})}/>
                      <span>หลักฐานผลลัพธ์ผู้เรียน (ผลงาน · ผลสัมฤทธิ์ · พฤติกรรม)</span></label>
                  </>}
                  {/* ผู้บริหาร */}
                  {comp.id==='academic' && <>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.planned} onChange={e=>setC('academic',{planned:e.target.checked})}/>
                      <span>แผนกลยุทธ์/แผนพัฒนาวิชาการโรงเรียน · นวัตกรรมการบริหาร</span></label>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.evidence} onChange={e=>setC('academic',{evidence:e.target.checked})}/>
                      <span>หลักฐานเชิงประจักษ์การพัฒนาวิชาการ · รายงานผลการดำเนินการ</span></label>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.video} onChange={e=>setC('academic',{video:e.target.checked})}/>
                      <span>วิดีทัศน์นำเสนอกลยุทธ์การพัฒนา (ไฟล์เดียว)</span></label>
                  </>}
                  {comp.id==='manage' && <>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.outcome} onChange={e=>setC('manage',{outcome:e.target.checked})}/>
                      <span>ผลลัพธ์คุณภาพผู้เรียน/สถานศึกษา · O-NET · ผลประเมินภายนอก</span></label>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.evidence} onChange={e=>setC('manage',{evidence:e.target.checked})}/>
                      <span>หลักฐานประสิทธิภาพงานบริหารทั่วไป/บุคคล/งบประมาณ</span></label>
                  </>}
                  {comp.id==='research' && <>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.research} onChange={e=>setC('research',{research:e.target.checked})}/>
                      <span>งานวิจัย R&D 4 ขั้นตอน · เผยแพร่ในวารสาร TCI</span></label>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.innovation} onChange={e=>setC('research',{innovation:e.target.checked})}/>
                      <span>นวัตกรรมการบริหารสถานศึกษา (จำเป็นสำหรับ ผอ. เชี่ยวชาญ ขึ้นไป)</span></label>
                    <label className="ac-check-row"><input type="checkbox" checked={!!val.published} onChange={e=>setC('research',{published:e.target.checked})}/>
                      <span>เผยแพร่ในวารสารวิชาการ TCI 1/2 · หรือเวทีวิชาการระดับชาติ</span></label>
                  </>}
                  <textarea className="inp mt8" rows={2} placeholder="บันทึกเพิ่มเติม / ลิงก์ไฟล์"
                    value={val.note||''} onChange={e=>setC(comp.id,{note:e.target.value})}/>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </Card>
  );
}

function ReduceCard({rec, update, tgtRank, elig}){
  const rc = rec.reduceConditions||{};
  const anyOn = Object.values(rc).some(Boolean);
  return (
    <Card className="mt16">
      <CardHead icon="clock" title="เงื่อนไขลดระยะเวลาถือครอง (ว.4/2564)"
        sub={anyOn ? `ใช้สิทธิ์ลดระยะเวลาแล้ว — ต้องถือครองเพียง 3 ปี` : `ตามปกติต้องถือครอง 4 ปี · เข้าเงื่อนไข 1 ใน 5 ข้อ → ลดเหลือ 3 ปี`}/>
      <div className="card-pad">
        <div className="ac-docs">
          {REDUCE_CONDITIONS.map(cd=>{
            const on = !!rc[cd.id];
            return (
              <label key={cd.id} className={`ac-doc ${on?'on':''}`}>
                <input type="checkbox" checked={on} onChange={e=>update({reduceConditions:{...rc, [cd.id]:e.target.checked}})}/>
                <div className="ac-doc-body">
                  <div className="ac-doc-t">{cd.label}</div>
                  <div className="ac-doc-s">{cd.sub}</div>
                </div>
                <span className={`ac-doc-tick ${on?'on':''}`} style={on?{background:tgtRank.color,borderColor:tgtRank.color}:null}><Icon name="check" size={14}/></span>
              </label>
            );
          })}
        </div>
        <div className="note-box mt12" style={{background:'#eff6ff',borderColor:'#bfdbfe'}}>
          <Icon name="info" size={16} style={{color:'var(--brand-600)',flex:'none'}}/>
          <div style={{fontSize:12.5}}>เข้าเงื่อนไขเพียง 1 ข้อก็สามารถใช้สิทธิ์ลดระยะเวลาได้ · ต้องมีเอกสารหลักฐานยืนยันในวันยื่นคำขอ</div>
        </div>
      </div>
    </Card>
  );
}

function AcademicWorkCard({rec, update, tgtRank, isExec}){
  const w = rec.academicWork||{};
  const setW = patch=> update({academicWork:{...w, ...patch}});
  const needsExpansion = isExec && tgtRank.needsExpansion;
  const subText = isExec
    ? (tgtRank.id==='ap5'
        ? 'เชี่ยวชาญพิเศษ: R&D + นวัตกรรม + ขยายผลระดับเขต/ชาติ + บทความวิจารณ์'
        : 'เชี่ยวชาญ: งานวิจัย R&D 1 เรื่อง เผยแพร่ในวารสาร TCI (ผอ. ต้องมีนวัตกรรมเพิ่ม)')
    : (tgtRank.id==='kh5' ? 'ต้องมีผลงานคุณภาพระดับสูง · ผ่านการเผยแพร่ในระดับชาติ/นานาชาติ'
                          : 'ต้องมีผลงานที่ผ่านการเผยแพร่');
  return (
    <Card className="mt16">
      <CardHead icon="book" title={`ผลงานทางวิชาการ${isExec?' (สายผู้บริหาร)':''} — สำหรับ ${tgtRank.short}`} sub={subText}/>
      <div className="card-pad">
        <div className="field">
          <label>ชื่อผลงานทางวิชาการ</label>
          <input type="text" className="inp" value={w.title||''} onChange={e=>setW({title:e.target.value})}
            placeholder={isExec?'เช่น รายงานวิจัย R&D การพัฒนารูปแบบการบริหารสถานศึกษา…':'เช่น รายงานการวิจัยในชั้นเรียน · นวัตกรรมการเรียนการสอน'}/>
        </div>
        <label className="ac-check-row mt8">
          <input type="checkbox" checked={!!w.published} onChange={e=>setW({published:e.target.checked})}/>
          <span>เผยแพร่แล้ว {isExec && '(ต้องเป็นวารสาร TCI 1/2 หรือเวทีวิชาการระดับชาติ)'}</span>
        </label>
        {w.published && (
          <div className="form-grid-2 mt8">
            <div className="field"><label>สถานที่/แหล่งเผยแพร่</label>
              <input type="text" className="inp" value={w.publishVenue||''} onChange={e=>setW({publishVenue:e.target.value})}
                placeholder={isExec?'วารสาร TCI · การประชุมวิชาการระดับชาติ':'วารสาร · การประชุมวิชาการ · เว็บไซต์'}/></div>
            <div className="field"><label>วันที่เผยแพร่</label>
              <input type="date" className="inp" value={w.publishDate||''} onChange={e=>setW({publishDate:e.target.value})}/></div>
          </div>
        )}
        {needsExpansion && (
          <div className="mt12" style={{padding:12,background:'#fef3c7',border:'1px solid #fcd34d',borderRadius:8}}>
            <b style={{color:'#92400e',fontFamily:'Kanit',fontSize:13.5}}>สำหรับวิทยฐานะเชี่ยวชาญพิเศษ (คศ.5) ต้องมีเพิ่ม:</b>
            <label className="ac-check-row mt8">
              <input type="checkbox" checked={!!w.expansion} onChange={e=>setW({expansion:e.target.checked})}/>
              <span>ขยายผลระดับเขต/ระดับชาติ (มีหลักฐานการนำไปใช้)</span>
            </label>
            {w.expansion && (
              <div className="field mt8"><label className="tiny">รายละเอียดการขยายผล</label>
                <textarea className="inp" rows={2} value={w.expansionNote||''} onChange={e=>setW({expansionNote:e.target.value})}
                  placeholder="สพม./ก.ค.ศ./สพฐ. นำไปเผยแพร่ · โรงเรียนอื่นนำไปประยุกต์ใช้ …"/></div>
            )}
            <label className="ac-check-row mt8">
              <input type="checkbox" checked={!!w.critique} onChange={e=>setW({critique:e.target.checked})}/>
              <span>บทความวิจารณ์ผลงาน (Review) จากผู้ทรงคุณวุฒิ</span>
            </label>
          </div>
        )}
      </div>
    </Card>
  );
}

// ─────────────────────────────────────────────────────────
// AdminAcademicView — Executive Dashboard วิทยฐานะ
// ─────────────────────────────────────────────────────────
function AdminAcademicView(){
  const rows = React.useMemo(()=>{
    const all = window.TEACHERS || [];
    return all.map(t=>{
      try{
        const raw = localStorage.getItem('ntk_academic_v2_'+t.id);
        const rec = raw ? JSON.parse(raw) : null;
        return {t, rec, elig: rec?checkEligibility(rec):null};
      }catch{ return {t, rec:null, elig:null}; }
    });
  },[]);
  const withData = rows.filter(r=>r.rec);
  const noData = rows.filter(r=>!r.rec);

  // ── การจำแนก ──
  const overdue = withData.filter(({rec,elig})=>{
    // คุณสมบัติครบทุกด้าน (tenure + PA + discipline) แต่ยังไม่ยื่น + เป้าหมายสูงกว่าปัจจุบัน
    if(!elig.tenure.ok || !elig.pa.ok || !elig.discipline.ok) return false;
    if(rec.submittedAt) return false;
    const cr = rankById(rec.currentRankId), tg = rankById(rec.targetRankId);
    return tg.level > cr.level;
  }).map(r=>{
    const excess = r.elig.tenure.years - r.elig.minYears;
    return {...r, overdueDays: Math.max(0, Math.floor(excess * 365.25))};
  }).sort((a,b)=>b.overdueDays - a.overdueDays);

  const preparing = withData.filter(({rec,elig})=>{
    if(rec.submittedAt || rec.approvedAt) return false;
    if(elig.tenure.ok && elig.pa.ok && elig.discipline.ok) return false;  // อยู่ในกลุ่ม overdue แล้ว
    const cr = rankById(rec.currentRankId), tg = rankById(rec.targetRankId);
    return tg.level > cr.level;
  });
  const inProgress = withData.filter(({rec})=> rec.submittedAt && !rec.approvedAt);
  const approvedThisYear = withData.filter(({rec})=>{
    if(!rec.approvedAt) return false;
    const y = new Date(rec.approvedAt).getFullYear();
    return y === new Date().getFullYear();
  });

  // Pipeline: จำนวนครูในแต่ละขั้น (1-5)
  const pipeline = [1,2,3,4,5].map(s=> withData.filter(({rec})=> rec.step===s).length);

  // Rank distribution
  const byRank = {}; ACADEMIC_RANKS.forEach(r=>{ byRank[r.id]=0; });
  withData.forEach(({rec})=>{ if(rec.currentRankId) byRank[rec.currentRankId]=(byRank[rec.currentRankId]||0)+1; });

  return (
    <div>
      <div style={{marginBottom:18}}>
        <h1 style={{fontSize:22,color:'var(--brand-900)'}}>Dashboard วิทยฐานะครูทั้งโรงเรียน</h1>
        <p style={{margin:'4px 0 0',color:'var(--ink-2)',fontSize:14}}>ภาพรวมและติดตามการขอมี/เลื่อนวิทยฐานะตามหลักเกณฑ์ <b>ว.9/2564</b> · <b>ว.4/2564</b> — สำนักงาน ก.ค.ศ.</p>
      </div>

      {/* ── KPI cards ── */}
      <div className="stats">
        <Stat k="ครูที่กรอกข้อมูล" v={withData.length} unit={`/ ${rows.length} ท่าน`} tone="blue" icon="users"/>
        <Stat k="พร้อมยื่นแต่ยังไม่ยื่น" v={overdue.length} unit="ท่าน" tone="red" icon="hourglass"/>
        <Stat k="กำลังยื่นคำขอ" v={inProgress.length} unit="ท่าน" tone="amber" icon="send"/>
        <Stat k="ได้รับปีนี้" v={approvedThisYear.length} unit="ท่าน" tone="green" icon="award"/>
      </div>

      {/* ── 🚨 Alert Banner — ครูที่ถึงกำหนดแล้วยังไม่ยื่น ── */}
      {overdue.length>0 && (
        <div className="ac-alert mt16">
          <div className="ac-alert-icon"><Icon name="hourglass" size={22}/></div>
          <div className="ac-alert-body">
            <div className="ac-alert-h">
              <span>ครู <b>{overdue.length}</b> ท่าน มีคุณสมบัติครบแล้ว แต่ยังไม่ยื่นขอวิทยฐานะ</span>
              <span className="ac-alert-pulse"></span>
            </div>
            <div className="ac-alert-list">
              {overdue.slice(0,6).map(({t,rec,elig,overdueDays})=>{
                const cr = rankById(rec.currentRankId), tg = rankById(rec.targetRankId);
                return (
                  <div key={t.id} className="ac-alert-item">
                    <Avatar t={t} size="sm"/>
                    <div style={{flex:1,minWidth:0}}>
                      <div className="ac-alert-name">{fullTitle(t)}</div>
                      <div className="ac-alert-meta">
                        {cr.short} → {tg.short} · ครบระยะ {elig.minYears} ปีแล้ว
                        {overdueDays>0 && <b style={{color:'#dc2626',marginLeft:6}}>(เกิน {overdueDays} วัน)</b>}
                      </div>
                    </div>
                  </div>
                );
              })}
              {overdue.length>6 && <div className="ac-alert-more">…และอีก {overdue.length-6} ท่าน (ดูรายละเอียดในตารางด้านล่าง)</div>}
            </div>
          </div>
        </div>
      )}

      {/* ── Pipeline: 5-step funnel ── */}
      <Card className="mt16">
        <CardHead icon="layers" title="Pipeline ขั้นตอนการขอวิทยฐานะ" sub={`ครูทั้งหมด ${withData.length} ท่าน แบ่งตามขั้นการดำเนินการ`}/>
        <div className="card-pad">
          <div className="ac-pipeline">
            {REQUEST_STEPS.map((s,i)=>{
              const count = pipeline[i];
              const pct = withData.length ? Math.round(count/withData.length*100) : 0;
              return (
                <div key={s.id} className="ac-pipe-col">
                  <div className="ac-pipe-num">{count}</div>
                  <div className="ac-pipe-bar-wrap">
                    <div className="ac-pipe-bar" style={{height: Math.max(4, pct*1.4)+'px'}}></div>
                  </div>
                  <div className="ac-pipe-lbl">
                    <div className="ac-pipe-step">ขั้น {s.id}</div>
                    <div className="ac-pipe-name">{s.label}</div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      </Card>

      {/* ── Rank distribution ── */}
      <Card className="mt16">
        <CardHead icon="award" title="สัดส่วนตามวิทยฐานะปัจจุบัน"/>
        <div className="card-pad">
          <div className="rsn-bars">
            {ACADEMIC_RANKS.map(r=>{
              const v = byRank[r.id]||0; const pct = withData.length? Math.round(v/withData.length*100):0;
              return (
                <div key={r.id} className="rsn-row">
                  <span className="reason-tag" style={{minWidth:180,background:r.color+'18',color:r.color,border:'1px solid '+r.color+'55'}}>{r.full}</span>
                  <div className="rsn-track"><div className="rsn-fill" style={{width:pct+'%', background:r.color, transition:'width 1s cubic-bezier(.4,0,.2,1)'}}></div></div>
                  <span className="num rsn-val">{v} ท่าน · {pct}%</span>
                </div>
              );
            })}
          </div>
        </div>
      </Card>

      {/* ── กลุ่มกำลังเตรียม (คุณสมบัติยังไม่ครบ) ── */}
      {preparing.length>0 && (
        <Card className="mt16">
          <CardHead icon="clipboard" title={`กำลังเตรียมคุณสมบัติ (${preparing.length} ท่าน)`} sub="ยังไม่ครบเกณฑ์บางข้อ · คลิกดูรายละเอียดในตาราง"/>
          <div className="card-pad">
            <div className="ac-prep-grid">
              {preparing.slice(0,8).map(({t,rec,elig})=>{
                const cr = rankById(rec.currentRankId), tg = rankById(rec.targetRankId);
                const pct = computeProgressPct(rec, elig);
                const missing = [];
                if(!elig.tenure.ok) missing.push(`เหลือ ${(elig.minYears-elig.tenure.years).toFixed(1)} ปี`);
                if(!elig.pa.ok) missing.push(`PA ${elig.pa.count}/3`);
                if(!elig.components.ok) missing.push(`ผลงาน ${elig.components.count}/3 ด้าน`);
                if(elig.academicWork.need && !elig.academicWork.ok) missing.push('ผลงานวิชาการ');
                return (
                  <div key={t.id} className="ac-prep-card">
                    <div className="flex ac gap8" style={{marginBottom:8}}>
                      <Avatar t={t} size="sm"/>
                      <div style={{flex:1,minWidth:0}}>
                        <div className="ac-prep-name">{fullTitle(t)}</div>
                        <div className="ac-prep-target">
                          <span className="reason-tag" style={{background:cr.color+'18',color:cr.color,border:'1px solid '+cr.color+'55'}}>{cr.short}</span>
                          <Icon name="chevronRight" size={12} style={{color:'var(--ink-3)'}}/>
                          <span className="reason-tag" style={{background:tg.color+'18',color:tg.color,border:'1px solid '+tg.color+'55'}}>{tg.short}</span>
                        </div>
                      </div>
                    </div>
                    <div className="ac-tbl-track"><div className="ac-tbl-fill" style={{width:pct+'%',background:tg.color}}></div></div>
                    <div className="ac-prep-missing">
                      {missing.map((m,i)=><span key={i} className="ac-miss-chip">{m}</span>)}
                    </div>
                  </div>
                );
              })}
            </div>
            {preparing.length>8 && <div className="tiny" style={{textAlign:'center',marginTop:8,color:'var(--ink-3)'}}>…และอีก {preparing.length-8} ท่าน</div>}
          </div>
        </Card>
      )}

      {/* ── กลุ่มกำลังยื่น ── */}
      {inProgress.length>0 && (
        <Card className="mt16">
          <CardHead icon="send" title={`กำลังอยู่ในกระบวนการยื่นคำขอ (${inProgress.length} ท่าน)`} sub="ยื่นแล้ว รอผลจากคณะกรรมการ / อ.ก.ค.ศ."/>
          <div className="card-pad">
            <div className="ac-prog-list">
              {inProgress.map(({t,rec,elig})=>{
                const cr = rankById(rec.currentRankId), tg = rankById(rec.targetRankId);
                return (
                  <div key={t.id} className="ac-prog-item">
                    <Avatar t={t} size="sm"/>
                    <div style={{flex:1}}>
                      <div className="flex ac gap8">
                        <span className="ac-prog-name">{fullTitle(t)}</span>
                        <span className="reason-tag" style={{background:cr.color+'18',color:cr.color,border:'1px solid '+cr.color+'55'}}>{cr.short}</span>
                        <Icon name="chevronRight" size={12} style={{color:'var(--ink-3)'}}/>
                        <span className="reason-tag" style={{background:tg.color+'18',color:tg.color,border:'1px solid '+tg.color+'55'}}>{tg.short}</span>
                      </div>
                      <div className="tiny" style={{color:'var(--ink-2)',marginTop:2}}>
                        ยื่นเมื่อ {thaiDateFull(rec.submittedAt)} · ขั้นที่ {rec.step}/5
                      </div>
                    </div>
                    <div style={{minWidth:140}}>
                      <div className="ac-tbl-track"><div className="ac-tbl-fill" style={{width:computeProgressPct(rec,elig)+'%',background:tg.color}}></div></div>
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        </Card>
      )}

      {/* ── ไม่กรอกข้อมูล ── */}
      {noData.length>0 && (
        <div className="note-box mt16" style={{background:'#fef2f2',borderColor:'#fecaca'}}>
          <Icon name="user" size={18} style={{color:'#dc2626',flex:'none'}}/>
          <div>
            <b>ครูที่ยังไม่กรอกข้อมูลวิทยฐานะ: {noData.length} ท่าน</b>
            <div style={{fontSize:12.5,color:'var(--ink-2)',marginTop:4}}>
              {noData.slice(0,10).map(({t})=>fullTitle(t)).join(' · ')}
              {noData.length>10 && ` …และอีก ${noData.length-10} ท่าน`}
            </div>
          </div>
        </div>
      )}

      {/* ── Detail Table ── */}
      <div className="flex ac gap8" style={{margin:'24px 0 10px'}}>
        <Icon name="users" size={17} style={{color:'var(--brand-600)',flex:'none'}}/>
        <b style={{fontFamily:'Kanit',fontSize:15,color:'var(--brand-900)',whiteSpace:'nowrap'}}>รายชื่อครูและความคืบหน้าทั้งหมด</b>
      </div>
      <div className="scroll-x-hint">← เลื่อนตารางแนวนอนเพื่อดูทุกคอลัมน์ →</div>
      <div className="tbl-wrap">
        <table className="tbl" style={{minWidth:960}}>
          <thead>
            <tr>
              <th>ครู</th><th>ปัจจุบัน</th><th>เป้าหมาย</th>
              <th style={{textAlign:'center'}}>ระยะถือครอง</th>
              <th style={{textAlign:'center'}}>PA</th>
              <th style={{textAlign:'center'}}>ผลงาน 3 ด้าน</th>
              <th style={{textAlign:'center',minWidth:160}}>ความคืบหน้า</th>
              <th>สถานะ</th>
            </tr>
          </thead>
          <tbody>
            {rows.length===0 && <tr><td colSpan={8}><Empty icon="inbox" title="ยังไม่มีข้อมูลวิทยฐานะ"/></td></tr>}
            {rows.map(({t,rec,elig})=>{
              if(!rec){
                return <tr key={t.id} style={{opacity:.55}}>
                  <td><div className="flex ac gap8"><Avatar t={t} size="sm"/><span>{fullTitle(t)}</span></div></td>
                  <td colSpan={7} className="muted">— ยังไม่ได้กรอกข้อมูล —</td>
                </tr>;
              }
              const cr = rankById(rec.currentRankId), tg = rankById(rec.targetRankId);
              const pct = computeProgressPct(rec, elig);
              // สถานะ
              let status, statusColor;
              if(rec.approvedAt){ status='✓ ได้รับแล้ว'; statusColor='var(--green)'; }
              else if(rec.submittedAt){ status='📤 กำลังยื่น'; statusColor='var(--amber)'; }
              else if(elig.tenure.ok && elig.pa.ok && elig.discipline.ok && tg.level>cr.level){
                const excess = Math.max(0, Math.floor((elig.tenure.years - elig.minYears) * 365.25));
                status = excess>0 ? `⚠️ พร้อมยื่น (เกิน ${excess} วัน)` : '⚠️ พร้อมยื่น'; statusColor='#dc2626';
              }
              else if(tg.level>cr.level){ status='🔧 กำลังเตรียม'; statusColor='var(--brand-600)'; }
              else { status='— ยังไม่กำหนด'; statusColor='var(--ink-3)'; }
              return (
                <tr key={t.id}>
                  <td><div className="flex ac gap8"><Avatar t={t} size="sm"/><span style={{fontWeight:500}}>{fullTitle(t)}</span></div></td>
                  <td><span className="reason-tag" style={{background:cr.color+'18',color:cr.color,border:'1px solid '+cr.color+'55'}}>{cr.short}</span></td>
                  <td>{tg.level>cr.level ? <span className="reason-tag" style={{background:tg.color+'18',color:tg.color,border:'1px solid '+tg.color+'55'}}>{tg.short}</span> : <span className="muted">—</span>}</td>
                  <td style={{textAlign:'center'}} className={elig.tenure.ok?'':'muted'}>
                    <b style={elig.tenure.ok?{color:'var(--green)'}:null}>{elig.tenure.years.toFixed(1)}</b>/{elig.minYears} ปี
                  </td>
                  <td style={{textAlign:'center'}} className={elig.pa.ok?'':'muted'}>
                    <b style={elig.pa.ok?{color:'var(--green)'}:null}>{elig.pa.count}</b>/3
                  </td>
                  <td style={{textAlign:'center'}} className={elig.components.ok?'':'muted'}>
                    <b style={elig.components.ok?{color:'var(--green)'}:null}>{elig.components.count}</b>/3
                  </td>
                  <td style={{minWidth:160}}>
                    <div className="ac-tbl-track"><div className="ac-tbl-fill" style={{width:pct+'%',background:tg.color}}></div></div>
                    <div className="tiny" style={{textAlign:'center',marginTop:2}}>ขั้นที่ {rec.step}/5 · {pct}%</div>
                  </td>
                  <td className="tiny" style={{color:statusColor,fontWeight:600,whiteSpace:'nowrap'}}>{status}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

window.AcademicView = AcademicView;
window.AdminAcademicView = AdminAcademicView;
window.ACADEMIC_RANKS = ACADEMIC_RANKS;
