/* ============================================================
   LeaveView.jsx — มุมครูที่ลา: แจ้งลา + เลือกครูสอนแทน
   ============================================================ */

function SubPicker({schedules, date, period, className, excludeId, value, onPick}){
  const [open, setOpen] = React.useState(false);
  const sel = value ? teacherById(value) : null;
  const ranked = rankSubstitutes(schedules, date, period, className, excludeId);
  const free = ranked.filter(r=>r.free);
  const busy = ranked.filter(r=>!r.free);
  const selRow = ranked.find(r=>r.teacher.id===value);

  const Row = ({r})=>(
    <button className={`subrow ${value===r.teacher.id?'on':''}`} onClick={()=>{onPick(r.teacher.id);setOpen(false);}}>
      <Avatar t={r.teacher} size="sm"/>
      <div className="nm">
        <div className="n1">{fullTitle(r.teacher)} {r.teachesClass && <span title="เคยสอนห้องนี้" style={{color:'var(--amber)'}}>★</span>}</div>
        <div className="n2">{r.teacher.primary}{r.teachesClass?` · เคยสอน ${className}`:''}</div>
      </div>
      {r.free
        ? <span className="free-note"><Icon name="check" size={13}/>ว่าง</span>
        : <span className="busy-note" title={r.busy?(r.busy.className||r.busy.activity):''}><Icon name="clock" size={13}/>{r.busy?(r.busy.className||r.busy.activity||'มีคาบ'):'มีคาบ'}</span>}
    </button>
  );

  return (
    <div>
      {!open && (
        <button className={`subrow ${sel?'on':''}`} onClick={()=>setOpen(true)}>
          {sel ? <Avatar t={sel} size="sm"/> : <span style={{width:34,height:34,borderRadius:'50%',background:'var(--brand-50)',display:'flex',alignItems:'center',justifyContent:'center',color:'var(--brand-400)'}}><Icon name="user" size={17}/></span>}
          <div className="nm">
            <div className="n1">{sel ? fullTitle(sel) : 'เลือกครูสอนแทน'}</div>
            <div className="n2">{sel
              ? `${sel.primary}${selRow?(selRow.free?' · ว่างคาบนี้':' · มีคาบสอนคาบนี้'):''}${selRow&&selRow.teachesClass?' · เคยสอนห้องนี้':''}`
              : `ระบบแนะนำครูที่ว่างคาบนี้ + เคยสอน ${className} ก่อน`}</div>
          </div>
          <Icon name="chevronRight" size={16} style={{color:'var(--ink-3)'}}/>
        </button>
      )}
      {open && (
        <div className="card" style={{borderColor:'var(--brand-100)',boxShadow:'var(--shadow-md)'}}>
          <div style={{padding:'10px 14px',display:'flex',alignItems:'center',gap:8,borderBottom:'1px solid var(--line-2)'}}>
            <Icon name="users" size={16} style={{color:'var(--brand-600)'}}/>
            <b style={{fontSize:13}}>เลือกครูสอนแทน — คาบ {period} · {className}</b>
            <button style={{marginLeft:'auto',background:'none',border:'none',color:'var(--ink-3)'}} onClick={()=>setOpen(false)}><Icon name="x" size={18}/></button>
          </div>
          <div style={{maxHeight:300,overflowY:'auto',padding:10,display:'flex',flexDirection:'column',gap:7}}>
            <div className="tiny" style={{padding:'2px 4px',color:'var(--green)',fontWeight:600,display:'flex',alignItems:'center',gap:5}}><Icon name="checkCircle" size={13}/> ว่างคาบนี้ ({free.length} ท่าน) — ★ = เคยสอนห้องนี้</div>
            {free.map(r=><Row key={r.teacher.id} r={r}/>)}
            <div className="tiny" style={{padding:'8px 4px 2px',color:'var(--amber)',fontWeight:600,display:'flex',alignItems:'center',gap:5,borderTop:'1px dashed var(--line)',marginTop:4}}><Icon name="clock" size={13}/> มีคาบสอนคาบนี้ ({busy.length} ท่าน)</div>
            {busy.map(r=><Row key={r.teacher.id} r={r}/>)}
          </div>
        </div>
      )}
    </div>
  );
}

/* ---------- เลือกวัน/คาบกลับมาสอนชดเชย — อิงตารางครูสอนแทนในห้องนั้น ---------- */
function MakeupPicker({schedules, substituteId, className, leaveDate, value, onChange}){
  if(!substituteId){
    return <div className="hint" style={{marginTop:2}}>เลือกครูสอนแทนก่อน ระบบจะแนะนำวัน/คาบชดเชยที่ตรงกับตารางของครูสอนแทนในชั้น {className} (เพื่อไม่กระทบตารางเรียนของนักเรียน)</div>;
  }
  const sub = teacherById(substituteId);
  const subSched = schedules[substituteId] || (sub||{}).schedule;
  const slots = slotsTeachingClass(subSched, className);

  if(slots.length===0){
    return (
      <div>
        <div className="note-box" style={{marginBottom:11,background:'var(--amber-bg)',borderColor:'var(--amber-line)',color:'var(--amber)'}}>
          <Icon name="info" size={17} style={{flex:'none'}}/>
          <div>{sub?sub.short:'ครูสอนแทน'} ไม่มีคาบสอนชั้น {className} ในตารางสอน — โปรดเลือกวัน/คาบชดเชยเอง (ระวังไม่ให้ชนคาบเรียนของนักเรียน)</div>
        </div>
        <div style={{display:'grid',gridTemplateColumns:'1.3fr .9fr',gap:12}}>
          <div className="field mb0"><label>วันที่กลับมาสอนชดเชย</label>
            <input type="date" className="inp" value={value.makeupDate||''} onChange={e=>onChange({makeupDate:e.target.value, makeupDay:e.target.value?weekdayName(e.target.value):''})}/></div>
          <div className="field mb0"><label>คาบที่ชดเชย</label>
            <select className="sel" value={value.makeupPeriod||''} onChange={e=>onChange({makeupPeriod:+e.target.value})}>
              <option value="">— เลือก —</option>
              {PERIODS.map(p=><option key={p.p} value={p.p}>คาบ {p.p}</option>)}
            </select></div>
        </div>
      </div>
    );
  }

  return (
    <div>
      <label className="mk-label">วัน/คาบที่จะมาสอนชดเชย
        <span className="mk-sublabel">— เลือกคาบที่ {sub?sub.short:'ครูสอนแทน'} สอนชั้น {className} อยู่แล้ว ครูที่ลาจะมาสอนแทนในคาบนั้น (นักเรียนเรียนตามปกติ ไม่กระทบตาราง)</span>
      </label>
      <div className="mk-opts">
        {slots.map(s=>{
          const on = value.makeupDay===s.day && value.makeupPeriod===s.period;
          const iso = nextDateForWeekday(s.day, leaveDate);
          return (
            <button key={s.day+'-'+s.period} type="button" className={`mk-opt ${on?'on':''}`}
              onClick={()=>onChange({makeupDay:s.day, makeupPeriod:s.period, makeupDate:iso})}>
              <span className="mk-rad">{on && <Icon name="check" size={13}/>}</span>
              <span className="mk-day">{s.day}</span>
              <span className="mk-per">คาบ {s.period}</span>
              <span className="mk-time num">{s.time}</span>
              <span className="mk-subj">{s.subject}</span>
            </button>
          );
        })}
      </div>
      {value.makeupDay && value.makeupDate && (
        <div className="hint" style={{marginTop:9}}>กลับมาสอนชดเชย <b>{formatThaiDate(value.makeupDate,true)}</b> คาบ {value.makeupPeriod} · สอนแทน {sub?sub.short:'ครูสอนแทน'} ในชั้น {className}</div>
      )}
    </div>
  );
}

function LeaveForm({me, schedules, chairs, onSubmit, onCancel}){
  const [reason, setReason] = React.useState('kit');
  const [startDate, setStartDate] = React.useState(nextWeekdayISO(1));
  const [endDate, setEndDate] = React.useState(nextWeekdayISO(1));
  const [rows, setRows] = React.useState({});
  const mySched = schedules[me.id] || me.schedule;
  const chairId = chairs ? chairs[me.primary] : null;
  const chair = chairId ? teacherById(chairId) : null;
  const iAmChair = chair && chair.id===me.id;  // ประธานมอบให้ตัวเองไม่ได้
  const canDelegate = !!chair && !iAmChair;

  const invalidRange = !!(startDate && endDate && endDate < startDate);
  const totalDays = (startDate && endDate && !invalidRange) ? Math.round((new Date(endDate)-new Date(startDate))/86400000)+1 : 0;
  // วันทำการ (จันทร์–ศุกร์) ในช่วงที่เลือก
  const days = React.useMemo(()=>{
    const out=[]; if(!startDate||!endDate||invalidRange) return out;
    const d=new Date(startDate+'T00:00:00'), end=new Date(endDate+'T00:00:00'); let g=0;
    while(d<=end && g<90){ const wd=d.getDay(); if(wd>=1&&wd<=5) out.push(`${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`); d.setDate(d.getDate()+1); g++; }
    return out;
  },[startDate,endDate,invalidRange]);
  // คาบสอน + ภาระงานอื่น แยกตามวัน
  const dayBlocks = React.useMemo(()=> days.map(dt=>({
    date: dt, classes: classesOnDay(mySched, dt), acts: activitiesOnDay(mySched, dt),
  })), [days, mySched]);
  const rowKey = (dt,p)=> dt+'#'+p;

  React.useEffect(()=>{
    const init = {};
    dayBlocks.forEach(b=> b.classes.forEach(c=>{ init[rowKey(b.date,c.period)] = {include:true, substituteId:'', makeupDate:nextWeekdayISO(8), makeupPeriod:c.period}; }));
    setRows(init);
  // eslint-disable-next-line
  },[startDate,endDate]);

  const upd = (key, patch)=> setRows(r=>({...r,[key]:{...r[key],...patch}}));
  // เลือกครูสอนแทน — แนะนำคาบชดเชยแรกที่ตรงกับตารางครูสอนแทนในห้องนี้อัตโนมัติ
  const pickSub = (dt, c, id)=>{
    const patch = {substituteId:id};
    const subSched = schedules[id] || (teacherById(id)||{}).schedule;
    const slots = slotsTeachingClass(subSched, c.className);
    if(slots.length){ const f=slots[0]; patch.makeupDay=f.day; patch.makeupPeriod=f.period; patch.makeupDate=nextDateForWeekday(f.day, dt); }
    upd(rowKey(dt,c.period), patch);
  };
  // คาบที่เลือกทั้งหมด (ทุกวันในช่วงลา)
  const includedSlots = [];
  dayBlocks.forEach(b=> b.classes.forEach(c=>{ const r=rows[rowKey(b.date,c.period)]; if(r&&r.include) includedSlots.push({date:b.date,c,r}); }));
  const totalClasses = dayBlocks.reduce((n,b)=>n+b.classes.length,0);
  const ready = includedSlots.length>0 && !invalidRange && includedSlots.every(({r})=>{ if(r.delegate) return canDelegate; return r.substituteId && r.makeupDate && r.makeupPeriod; });

  const submit = ()=>{
    const gid = 'g'+Date.now();
    const list = includedSlots.map(({date, c, r})=>{
      const base = {
        id:newId(), groupId:gid, leaveTeacherId:me.id, reason, date, leaveStart:startDate, leaveEnd:endDate,
        period:c.period, code:c.code, subject:c.subject, className:c.className,
        rejectReason:'', createdAt:new Date().toISOString().slice(0,16), decidedAt:null,
      };
      if(r.delegate){
        return {...base, substituteId:'', makeupDate:'', makeupPeriod:null,
          status:'awaiting_chair', delegatedToChair:true, chairGroup:me.primary, arrangedByChairId:null};
      }
      return {...base, substituteId:r.substituteId, makeupDate:r.makeupDate, makeupPeriod:+r.makeupPeriod, status:'pending'};
    });
    onSubmit(list);
  };

  return (
    <div className="list-gap">
      <Card>
        <CardHead icon="edit" title="แบบฟอร์มแจ้งลา / ขอเปลี่ยนคาบสอน" sub={`ผู้แจ้ง: ${formalName(me)} (${me.primary})`}/>
        <div className="card-pad">
          <div className="field">
            <label>เหตุผลการลา</label>
            <div className="chips">
              {REASONS.map(r=>(
                <button key={r.id} className={`chip-r ${reason===r.id?'on':''}`} onClick={()=>setReason(r.id)}>
                  <span className="ic" style={{color:reason===r.id?'var(--brand-600)':'var(--ink-3)'}}><Icon name={r.icon} size={20}/></span>
                  <span className="ttl">{r.label}</span><span className="ds">{r.desc}</span>
                </button>
              ))}
            </div>
          </div>
          <div className="field mb0">
            <label>วันที่ลา (เลือกช่วงวันเริ่มต้น – สิ้นสุด)</label>
            <div style={{display:'flex',gap:14,alignItems:'flex-end',flexWrap:'wrap'}}>
              <div><div className="tiny" style={{marginBottom:4}}>ตั้งแต่วันที่</div>
                <input type="date" className="inp" value={startDate} onChange={e=>{const v=e.target.value;setStartDate(v); if(!endDate||endDate<v) setEndDate(v);}} style={{maxWidth:190}}/></div>
              <div><div className="tiny" style={{marginBottom:4}}>ถึงวันที่</div>
                <input type="date" className="inp" value={endDate} min={startDate} onChange={e=>setEndDate(e.target.value)} style={{maxWidth:190}}/></div>
              <div className="leave-daycount"><Icon name="calendar" size={15}/> <b className="num">{days.length}</b> วันทำการ{totalDays>days.length && <span className="tiny" style={{marginLeft:5}}>(รวมวันหยุด {totalDays} วัน)</span>}</div>
            </div>
            {invalidRange
              ? <div className="hint" style={{color:'var(--red)'}}>วันสิ้นสุดต้องไม่ก่อนวันเริ่มต้น</div>
              : <div className="hint">{days.length>0 ? <>ช่วงลา {formatThaiDate(startDate)} – {formatThaiDate(endDate)} · ระบบดึงคาบสอนของท่านทุกวันทำการในช่วงนี้ เพื่อจัดครูสอนแทนให้ครบ</> : 'ไม่มีวันทำการ (จันทร์–ศุกร์) ในช่วงที่เลือก'}</div>}
          </div>
        </div>
      </Card>

      <Card>
        <CardHead icon="calendar" title="คาบสอนของท่านในช่วงวันลา" sub="เลือกคาบที่ต้องหาครูสอนแทนในแต่ละวัน แล้วกำหนดครู + วัน/คาบที่จะมาสอนชดเชย"/>
        <div className="card-pad">
          {invalidRange && <Empty icon="calendar" title="ช่วงวันไม่ถูกต้อง" desc="วันสิ้นสุดต้องไม่ก่อนวันเริ่มต้น"/>}
          {!invalidRange && days.length===0 && <Empty icon="calendar" title="ไม่มีวันทำการ" desc="ช่วงที่เลือกไม่มีวันจันทร์–ศุกร์"/>}
          {!invalidRange && days.length>0 && totalClasses===0 && <Empty icon="calendar" title="ไม่มีคาบสอนในช่วงนี้" desc="ท่านไม่มีคาบสอนตามตารางในช่วงวันที่เลือก"/>}

          {dayBlocks.map(b=>{
            if(b.classes.length===0 && b.acts.length===0) return null;
            return (
              <div key={b.date} className="leave-day-block">
                {days.length>1 && (
                  <div className="leave-day-head"><Icon name="calendar" size={15}/> {formatThaiDate(b.date,true)} <span className="tiny">· {b.classes.length} คาบ</span></div>
                )}
                <div className="list-gap">
                  {b.classes.map(c=>{
                    const key = rowKey(b.date, c.period);
                    const r = rows[key] || {};
                    return (
                      <div key={key} className="card" style={{borderColor:r.include?'var(--brand-100)':'var(--line)',background:r.include?'#fff':'var(--bg-2)'}}>
                        <div style={{padding:'13px 15px',display:'flex',alignItems:'center',gap:13}}>
                          <div style={{width:46,height:46,flex:'none',borderRadius:11,background:r.include?'var(--brand-700)':'var(--ink-3)',color:'#fff',display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center',lineHeight:1}}>
                            <b className="num" style={{fontSize:19}}>{c.period}</b><span style={{fontSize:9.5,opacity:.85}}>คาบ</span>
                          </div>
                          <div className="grow" style={{minWidth:0}}>
                            <div style={{fontWeight:600}}>{c.subject} <span className="num" style={{color:'var(--brand-600)',fontWeight:500,fontSize:13}}>{c.code}</span></div>
                            <div style={{fontSize:12.5,color:'var(--ink-2)',display:'flex',gap:10,flexWrap:'wrap'}}><span style={{color:'var(--brand-600)',fontWeight:500}}>ชั้น {c.className}</span>{c.room&&<span style={{color:'var(--ink-3)'}}>ห้อง {c.room}</span>}<span style={{color:'var(--ink-3)'}}>{c.time}</span></div>
                          </div>
                          <label style={{display:'flex',alignItems:'center',gap:7,fontSize:12.5,color:'var(--ink-2)',cursor:'pointer',whiteSpace:'nowrap'}}>
                            <input type="checkbox" checked={!!r.include} onChange={e=>upd(key,{include:e.target.checked})} style={{width:17,height:17,accentColor:'var(--brand-600)'}}/>
                            หาครูสอนแทน
                          </label>
                        </div>
                        {r.include && (
                          <div style={{padding:'0 15px 15px',borderTop:'1px solid var(--line-2)',paddingTop:14}}>
                            <div className="seg seg-full" style={{marginBottom:14}}>
                              <button className={!r.delegate?'on':''} onClick={()=>upd(key,{delegate:false})}>เลือกครูสอนแทนเอง</button>
                              <button className={r.delegate?'on':''} disabled={!canDelegate} onClick={()=>canDelegate&&upd(key,{delegate:true})} title={!canDelegate?'ยังไม่มีประธานกลุ่มสาระ':''}>
                                <Icon name="shield" size={13} style={{marginRight:5,verticalAlign:'-2px'}}/>ให้ประธานกลุ่มสาระจัดให้
                              </button>
                            </div>
                            {!r.delegate ? (
                              <>
                                <div className="field" style={{marginBottom:14}}>
                                  <label>ครูที่จะสอนแทน</label>
                                  <SubPicker schedules={schedules} date={b.date} period={c.period} className={c.className} excludeId={me.id} value={r.substituteId} onPick={id=>pickSub(b.date, c, id)}/>
                                </div>
                                <MakeupPicker schedules={schedules} substituteId={r.substituteId} className={c.className} leaveDate={b.date} value={r} onChange={patch=>upd(key,patch)}/>
                              </>
                            ) : (
                              <div className="note-box" style={{background:'#efe7fb',borderColor:'#d8c6f2',color:'#5b3793'}}>
                                <Icon name="shield" size={18} style={{flex:'none'}}/>
                                <div>มอบหมายให้ <b>ประธานกลุ่มสาระ{me.primary}</b>{chair?` (${fullTitle(chair)})`:''} เป็นผู้จัดหาครูสอนแทนและกำหนดคาบชดเชยให้ · ระบบจะส่งแจ้งเตือนให้ประธานเข้ามาดำเนินการ และแจ้งผลกลับให้ท่านทราบเมื่อจัดเรียบร้อย</div>
                              </div>
                            )}
                          </div>
                        )}
                      </div>
                    );
                  })}
                </div>
                {b.acts.length>0 && (
                  <div className="note-box mt8" style={{background:'var(--amber-bg)',borderColor:'var(--amber-line)',color:'var(--amber)'}}>
                    <Icon name="info" size={18} style={{flex:'none'}}/>
                    <div>วันนี้ท่านมีภาระงานอื่นด้วย: {b.acts.map(a=>`คาบ ${a.period} ${a.activity}`).join(', ')} (ไม่ต้องหาครูสอนแทน)</div>
                  </div>
                )}
              </div>
            );
          })}

          {includedSlots.length>0 && (()=>{
            const nDeleg = includedSlots.filter(s=>s.r.delegate).length;
            const nSelf = includedSlots.length - nDeleg;
            return (
              <div className="note-box mt16">
                <Icon name="send" size={18} style={{flex:'none'}}/>
                <div>รวมทั้งหมด <b>{includedSlots.length} คาบ</b>{days.length>1 && <> ใน {days.length} วันทำการ</>} · เมื่อกดส่งคำขอ ระบบจะแจ้งเตือนผ่าน <b>เบราว์เซอร์ (Web Push)</b> อัตโนมัติ{nSelf>0 && <> — ไปยังครูสอนแทน {nSelf} คาบ</>}{nDeleg>0 && <> — และไปยัง <b>ประธานกลุ่มสาระ</b> ให้จัดครูสอนแทน {nDeleg} คาบ</>}</div>
              </div>
            );
          })()}

          <div className="flex gap10 mt16" style={{justifyContent:'flex-end'}}>
            <Btn variant="ghost" onClick={onCancel}>ยกเลิก</Btn>
            <Btn variant="primary" icon="send" disabled={!ready} onClick={submit}>ส่งคำขอ &amp; แจ้งเตือน</Btn>
          </div>
          {!ready && includedSlots.length>0 && <div className="tiny right mt8">กรุณาเลือกครูสอนแทนและกำหนดวัน/คาบชดเชยให้ครบทุกคาบที่เลือก</div>}
        </div>
      </Card>
    </div>
  );
}

function LeaveGroupCard({group, approval, onResend, onRequestApproval, onOpenDoc}){
  const first = group[0];
  const allSubsReady = group.every(a=>a.status==='acknowledged');
  return (
    <Card>
      <div style={{padding:'15px 18px',display:'flex',alignItems:'center',gap:12,borderBottom:'1px solid var(--line-2)',flexWrap:'wrap'}}>
        <Icon name="calendar" size={18} style={{color:'var(--brand-600)'}}/>
        <b style={{fontFamily:'Kanit'}}>{first.leaveStart && first.leaveEnd && first.leaveStart!==first.leaveEnd
          ? <>{formatThaiDate(first.leaveStart)} – {formatThaiDate(first.leaveEnd)}</>
          : formatThaiDate(first.date,true)}</b>
        <ReasonTag reason={first.reason}/>
        <span className="grow"/>
        <span className="tiny">{group.length} คาบ</span>
        <Btn size="sm" variant="ghost" icon="clipboard" onClick={()=>onOpenDoc(group)}>ใบลา</Btn>
      </div>
      <div style={{padding:'6px 18px 14px'}}>
        {group.map(a=>{
          const sub = teacherById(a.substituteId);
          return (
            <div key={a.id} className="kv" style={{alignItems:'center'}}>
              <div className="flex ac gap10" style={{minWidth:0}}>
                <span className="num" style={{width:30,height:30,borderRadius:8,background:'var(--brand-50)',color:'var(--brand-700)',display:'flex',alignItems:'center',justifyContent:'center',fontWeight:600,flex:'none'}}>{a.period}</span>
                <div style={{minWidth:0}}>
                  <div style={{fontWeight:500,fontSize:13.5}}>{first.leaveStart!==first.leaveEnd && <span className="num" style={{color:'var(--brand-600)',fontWeight:600,marginRight:6}}>{formatThaiDate(a.date)}</span>}{a.subject} · ชั้น {a.className}</div>
                  <div className="tiny">{a.status==='awaiting_chair'
                    ? <>รอ <b style={{color:'#6b41ad'}}>ประธานกลุ่มสาระ{a.chairGroup||''}</b> จัดครูสอนแทน</>
                    : <>สอนแทนโดย {sub?fullTitle(sub):'—'} · ชดเชย {formatThaiDate(a.makeupDate)} คาบ {a.makeupPeriod}</>}</div>
                </div>
              </div>
              <div className="flex ac gap8"><StatusBadge status={a.status}/>{a.status==='rejected' && <Btn size="sm" variant="ghost" icon="swap" onClick={()=>onResend(a)}>หาครูใหม่</Btn>}</div>
            </div>
          );
        })}
        {group.some(a=>a.status==='rejected') && (
          <div className="note-box mt12" style={{background:'var(--red-bg)',borderColor:'var(--red-line)',color:'var(--red)'}}>
            <Icon name="info" size={17} style={{flex:'none'}}/>
            <div>มีคาบที่ครูสอนแทนปฏิเสธ: “{group.find(a=>a.status==='rejected').rejectReason}” — กรุณาเลือกครูสอนแทนท่านใหม่</div>
          </div>
        )}

        {/* ขออนุญาตลา */}
        <div className="divider"></div>
        {!approval ? (
          <div className="flex ac jb wrap gap12">
            <div style={{minWidth:0}}>
              <div style={{fontWeight:600,fontSize:13.5}}>ขั้นขออนุญาตการลา</div>
              <div className="tiny">ส่งคำขอไปยัง รองฯ วิชาการ → รองฯ บุคคล → ผู้อำนวยการ (แจ้งเตือนผ่าน LINE + เบราว์เซอร์)</div>
            </div>
            <Btn variant="primary" icon="send" onClick={()=>onRequestApproval(first.groupId)}>ขออนุญาตลา</Btn>
          </div>
        ) : (
          <div className="appr-box">
            <div className="ab-hd"><Icon name="layers" size={14}/> สถานะการขออนุญาตลา</div>
            <ApprovalStepper approval={approval}/>
            <div className="appr-final">
              {approval.final==='approved' && <span className="badge b-ack"><Icon name="checkCircle" size={13}/> ผู้อำนวยการอนุญาตแล้ว</span>}
              {approval.final==='rejected' && <span className="badge b-reject"><Icon name="xCircle" size={13}/> ไม่ได้รับการอนุมัติ</span>}
              {approval.final==='pending' && <span className="badge b-pending"><span className="b-dot"/> อยู่ระหว่างพิจารณาของ {APPROVER_BY_ROLE[APPROVAL_CHAIN[approval.current]].short}</span>}
              {approval.chain.filter(s=>s.note).map((s,i)=>(
                <div key={i} className="tiny" style={{marginTop:5}}><b style={{color:'var(--ink-2)'}}>{APPROVER_BY_ROLE[s.role].short}:</b> “{s.note}”</div>
              ))}
            </div>
          </div>
        )}
      </div>
    </Card>
  );
}

function LeaveView({me, assignments, schedules, approvals, chairs, approverRoles, onSubmit, onRequestApproval}){
  const [mode, setMode] = React.useState('list');
  const [docGroup, setDocGroup] = React.useState(null);
  const mine = assignments.filter(a=>a.leaveTeacherId===me.id);
  const groups = {};
  mine.forEach(a=>{ (groups[a.groupId]=groups[a.groupId]||[]).push(a); });
  const groupList = Object.values(groups).sort((a,b)=> (b[0].createdAt||'').localeCompare(a[0].createdAt||''));

  if(mode==='form') return <LeaveForm me={me} schedules={schedules} chairs={chairs} onSubmit={(list)=>{onSubmit(list);setMode('list');}} onCancel={()=>setMode('list')}/>;

  return (
    <div>
      <div className="flex ac jb wrap gap12" style={{marginBottom:18}}>
        <div>
          <h1 style={{fontSize:22,color:'var(--brand-900)'}}>การลาของฉัน</h1>
          <p style={{margin:'4px 0 0',color:'var(--ink-2)',fontSize:14}}>{formalName(me)} · {me.primary}</p>
        </div>
        <Btn variant="primary" icon="plus" onClick={()=>setMode('form')}>แจ้งลา / ขอเปลี่ยนคาบสอน</Btn>
      </div>
      {groupList.length===0
        ? <Card><Empty icon="clipboard" title="ยังไม่มีรายการแจ้งลา" desc="กดปุ่ม “แจ้งลา / ขอเปลี่ยนคาบสอน” เพื่อเริ่ม"/></Card>
        : <div className="list-gap">{groupList.map((g,i)=><LeaveGroupCard key={i} group={g} approval={approvals[g[0].groupId]} onResend={()=>setMode('form')} onRequestApproval={onRequestApproval} onOpenDoc={setDocGroup}/>)}</div>}
      {docGroup && <LeaveFormDoc group={docGroup} approval={approvals[docGroup[0].groupId]} approverRoles={approverRoles} me={me} assignments={assignments} onClose={()=>setDocGroup(null)}/>}
    </div>
  );
}

Object.assign(window, { LeaveView, LeaveForm, SubPicker, MakeupPicker, LeaveGroupCard });
