/* ============================================================
   app.jsx — ระบบจัดการสอนแทน (login + 4 มุมมอง + LINE)
   ============================================================ */
const {useState, useEffect} = React;
const LS_KEY = 'ntk_substitute_v2';

const nowTime = ()=>{ const t=new Date(); return String(t.getHours()).padStart(2,'0')+':'+String(t.getMinutes()).padStart(2,'0'); };
const timeOf = iso => iso && iso.length>=16 ? iso.slice(11,16) : nowTime();
let _nseq = 0;
const nId = ()=> 'n'+Date.now()+'_'+(++_nseq);

function seedNotifications(seed){
  const out=[];
  seed.forEach(a=>{
    out.push({id:nId(), toTeacherId:a.substituteId, type:'request', text:buildRequestMsg(a), time:timeOf(a.createdAt), assignmentId:a.id});
  });
  // คำขออนุญาตลาตัวอย่าง: กลุ่ม gA รอรองฯ วิชาการพิจารณา
  const gA = seed.filter(a=>a.groupId==='gA');
  if(gA.length) out.push({id:nId(), toTeacherId:DEFAULT_APPROVER_ROLES['deputy_academic'], type:'approval', text:buildApprovalMsg(gA,'deputy_academic'), time:'09:20', groupId:'gA'});
  return out;
}
function seedApprovals(seed){
  const ap = {};
  if(seed.some(a=>a.groupId==='gA')){
    ap['gA'] = { requestedAt:'2026-06-01T09:20', current:0,
      chain:APPROVAL_CHAIN.map(r=>({role:r,status:'pending',at:null,note:''})), final:'pending' };
  }
  return ap;
}
const defaultSchedules = ()=> Object.fromEntries(TEACHERS.map(t=>[t.id, t.schedule]));
const defaultDuties = ()=> Object.fromEntries(TEACHERS.map(t=>[t.id, (t.duties||[]).slice()]));

function loadState(){
  try{ const raw=localStorage.getItem(LS_KEY); if(raw){ const s=JSON.parse(raw); if(s&&s.assignments) return s; } }catch(e){}
  return { session:null, view:'leave', assignments:SEED.slice(), notifications:seedNotifications(SEED), seen:[], schedules:defaultSchedules(), duties:defaultDuties(), credentials:defaultCredentials(), extraTeachers:[], teacherEdits:{}, lineLinks:{}, chairs:{}, approvals:seedApprovals(SEED), approverRoles:{...DEFAULT_APPROVER_ROLES} };
}

function App(){
  const init = loadState();
  (init.extraTeachers||[]).forEach(registerTeacher);
  Object.entries(init.teacherEdits||{}).forEach(([id,patch])=>applyTeacherEdit(teacherById(id), patch));
  const [session, setSession] = useState(init.session);
  const [view, setView] = useState(init.view);
  const [assignments, setAssignments] = useState(init.assignments);
  const [notifications, setNotifications] = useState(init.notifications);
  const [seen, setSeen] = useState(init.seen||[]);
  const [schedules, setSchedules] = useState(init.schedules || defaultSchedules());
  const [duties, setDuties] = useState(init.duties || defaultDuties());
  const [credentials, setCredentials] = useState(init.credentials || defaultCredentials());
  const [extraTeachers, setExtraTeachers] = useState(init.extraTeachers || []);
  const [teacherEdits, setTeacherEdits] = useState(init.teacherEdits || {});
  const [lineLinks, setLineLinks] = useState(init.lineLinks || {});
  const [chairs, setChairs] = useState(init.chairs || {});
  const [approvals, setApprovals] = useState(init.approvals || {});
  const [approverRoles, setApproverRoles] = useState(init.approverRoles || {...DEFAULT_APPROVER_ROLES});
  const [acct, setAcct] = useState(false);
  const [linking, setLinking] = useState(false);
  const [lineOpen, setLineOpen] = useState(false);
  const [toast, setToast] = useState(null);

  useEffect(()=>{ localStorage.setItem(LS_KEY, JSON.stringify({session,view,assignments,notifications,seen,schedules,duties,credentials,extraTeachers,teacherEdits,lineLinks,chairs,approvals,approverRoles})); },[session,view,assignments,notifications,seen,schedules,duties,credentials,extraTeachers,teacherEdits,lineLinks,chairs,approvals,approverRoles]);
  useEffect(()=>{ if(!toast) return; const t=setTimeout(()=>setToast(null),3400); return ()=>clearTimeout(t); },[toast]);

  const fireToast = (msg, icon)=> setToast({msg, icon});
  const pushNote = (note)=> setNotifications(ns=>[...ns,{id:nId(),time:nowTime(),...note}]);
  const updateAssign = (id,patch)=> setAssignments(arr=>arr.map(a=>a.id===id?{...a,...patch}:a));

  // ---- login ----
  if(!session){
    return <LoginView credentials={credentials} approverRoles={approverRoles} onLogin={(res)=>{ setSession(res); setView(res.role==='admin'?'admin':'leave'); }}/>;
  }
  const role = session.role;
  const isAdmin = role==='admin';
  const isTeacher = role==='teacher';
  const meT = isTeacher ? teacherById(session.teacherId) : null;
  const myApproverRole = meT ? roleOfTeacher(approverRoles, meT.id) : null;
  const isApprover = !!myApproverRole;
  const approver = isApprover ? {...APPROVER_BY_ROLE[myApproverRole], role:myApproverRole, teacher:meT} : null;
  const accountId = isTeacher ? (meT && meT.id) : 'admin';
  const myMsgs = isTeacher ? notifications.filter(n=>n.toTeacherId===accountId) : [];
  const unread = myMsgs.filter(n=>!seen.includes(n.id)).length;
  const pendingForMe = meT ? assignments.filter(a=>a.substituteId===meT.id && a.status==='pending').length : 0;
  // approver: จำนวนคำขอรอพิจารณา
  let pendingApprovals = 0;
  if(isApprover){
    const grp = groupAssignments(assignments);
    pendingApprovals = Object.keys(grp).filter(gid=>{ const ap=approvals[gid]; return ap && ap.final==='pending' && APPROVAL_CHAIN[ap.current]===myApproverRole; }).length;
  }

  // ---- actions ----
  const handleSubmit = (list)=>{
    setAssignments(a=>[...a,...list]);
    list.forEach(a=> pushNote({toTeacherId:a.substituteId, type:'request', text:buildRequestMsg(a), assignmentId:a.id}));
    const names=[...new Set(list.map(a=>fullTitle(teacherById(a.substituteId))))].join(', ');
    fireToast(`ส่งคำขอและแจ้งเตือน LINE ไปยัง ${names} แล้ว`, 'send');
  };
  const handleAck = (a)=>{ const upd={...a,status:'acknowledged',decidedAt:new Date().toISOString().slice(0,16)};
    updateAssign(a.id,{status:'acknowledged',decidedAt:upd.decidedAt});
    fireToast(`รับทราบการสอนแทนเรียบร้อยแล้ว · สถานะอัปเดตในระบบแล้ว`,'checkCircle'); };
  const handleReject = (a,reason)=>{ const upd={...a,status:'rejected',rejectReason:reason,decidedAt:new Date().toISOString().slice(0,16)};
    updateAssign(a.id,{status:'rejected',rejectReason:reason,decidedAt:upd.decidedAt});
    fireToast(`บันทึกการปฏิเสธแล้ว · สถานะอัปเดตในระบบแล้ว`,'xCircle'); };

  // schedule editing
  const setCell = (day,period,slot)=> setSchedules(s=>{ const me=session.teacherId; const sch=JSON.parse(JSON.stringify(s[me]||{})); if(!sch[day]) sch[day]=Array(8).fill(null); sch[day][period-1]=slot; return {...s,[me]:sch}; });
  const addDuty = (d)=> setDuties(D=>({...D,[session.teacherId]:[...(D[session.teacherId]||[]),d]}));
  const removeDuty = (i)=> setDuties(D=>({...D,[session.teacherId]:(D[session.teacherId]||[]).filter((_,j)=>j!==i)}));

  const openLine = ()=>{ setLineOpen(true); setSeen(myMsgs.map(n=>n.id)); };
  const logout = ()=>{ setSession(null); setLineOpen(false); };
  const saveAccount = (id, val)=>{ setCredentials(c=>({...c,[id]:val})); setAcct(false); fireToast('เปลี่ยนรหัสผ่านเรียบร้อย · ใช้รหัสใหม่ในการเข้าระบบครั้งต่อไป','checkCircle'); };
  const handleAddTeacher = ({pre,name,primary})=>{
    const username = nextUsername(credentials);
    const t = makeTeacher({pre,name,primary}, username);
    registerTeacher(t);
    setExtraTeachers(arr=>[...arr,t]);
    setCredentials(c=>({...c,[t.id]:{username, password:'1234'}}));
    setSchedules(s=>({...s,[t.id]:t.schedule}));
    setDuties(D=>({...D,[t.id]:[]}));
    fireToast(`เพิ่ม ${formalName(t)} แล้ว · ชื่อผู้ใช้ ${username} รหัสผ่านเริ่มต้น 1234`, 'checkCircle');
  };
  const handleEditTeacher = (id, patch)=>{
    applyTeacherEdit(teacherById(id), patch);
    setTeacherEdits(e=>({...e,[id]:{...(e[id]||{}),...patch}}));
    fireToast(`บันทึกข้อมูล ${formalName(teacherById(id))} เรียบร้อย`, 'checkCircle');
  };
  const handleResetPassword = (id, newPass)=>{
    setCredentials(c=>({...c,[id]:{...c[id], password:newPass}}));
  };
  const handleLinkLine = (teacherId, lineName, pwd)=>{
    const cred = credentials[teacherId];
    if(!cred || pwd !== cred.password){ fireToast('รหัสผ่านบัญชีไม่ถูกต้อง — เชื่อมไม่สำเร็จ','xCircle'); return; }
    const lineUserId = 'U'+Array.from({length:16},()=>Math.floor(Math.random()*16).toString(16)).join('');
    setLineLinks(l=>({...l,[teacherId]:{lineName, lineUserId, linkedAt:new Date().toISOString().slice(0,16)}}));
    setLinking(false);
    fireToast(`เชื่อมบัญชี LINE ‘${lineName}’ กับ ${cred.username} สำเร็จ · รับแจ้งเตือนได้แล้ว`,'checkCircle');
  };
  const handleUnlinkLine = (teacherId)=>{ setLineLinks(l=>{ const c={...l}; delete c[teacherId]; return c; }); fireToast('ยกเลิกการเชื่อมบัญชี LINE แล้ว','info'); };
  const handleSetChair = (group, teacherId)=>{
    setChairs(c=>{ const n={...c}; if(teacherId) n[group]=teacherId; else delete n[group]; return n; });
    if(teacherId) fireToast(`แต่งตั้ง ${fullTitle(teacherById(teacherId))} เป็นประธานกลุ่มสาระ${group}`,'checkCircle');
    else fireToast(`ยกเลิกประธานกลุ่มสาระ${group}แล้ว`,'info');
  };

  // ---- ขออนุญาตลา (workflow 3 ขั้น) ----
  const approverTeacherId = r => approverRoles[r] || null;
  const requestApproval = (groupId)=>{
    const group = assignments.filter(a=>a.groupId===groupId);
    if(!group.length) return;
    setApprovals(ap=>({...ap,[groupId]:{
      requestedAt:new Date().toISOString().slice(0,16),
      current:0,
      chain:APPROVAL_CHAIN.map(r=>({role:r,status:'pending',at:null,note:''})),
      final:'pending',
    }}));
    const tid = approverTeacherId('deputy_academic');
    if(tid) pushNote({toTeacherId:tid, type:'approval', text:buildApprovalMsg(group,'deputy_academic'), groupId});
    fireToast('ส่งคำขออนุญาตลาไปยังรองฯ วิชาการแล้ว · แจ้งเตือนทาง LINE','send');
  };
  const decideApproval = (groupId, decision, note)=>{
    const group = assignments.filter(a=>a.groupId===groupId);
    const ap = approvals[groupId];
    if(!ap) return;
    const curIdx = ap.current, curRole = APPROVAL_CHAIN[curIdx];
    setApprovals(prev=>{
      const a = {...prev[groupId]};
      a.chain = a.chain.map((s,i)=> i===curIdx ? {...s,status:decision,at:new Date().toISOString().slice(0,16),note:note||''} : s);
      if(decision==='rejected') a.final='rejected';
      else if(curIdx >= APPROVAL_CHAIN.length-1) a.final='approved';
      else a.current = curIdx+1;
      return {...prev,[groupId]:a};
    });
    if(decision==='rejected'){
      pushNote({toTeacherId:group[0].leaveTeacherId, type:'approval_result', text:buildApprovalResultMsg(group,false,curRole,note), groupId});
      fireToast('บันทึกผล “ไม่อนุญาต” แล้ว · แจ้งครูทาง LINE','xCircle');
    } else if(curIdx >= APPROVAL_CHAIN.length-1){
      pushNote({toTeacherId:group[0].leaveTeacherId, type:'approval_result', text:buildApprovalResultMsg(group,true), groupId});
      fireToast('อนุญาตการลาเรียบร้อย · แจ้งผลให้ครูทาง LINE','checkCircle');
    } else {
      const nextRole = APPROVAL_CHAIN[curIdx+1];
      const tid = approverTeacherId(nextRole);
      if(tid) pushNote({toTeacherId:tid, type:'approval', text:buildApprovalMsg(group,nextRole), groupId});
      fireToast(`เห็นควรอนุญาตแล้ว · ส่งต่อ ${APPROVER_BY_ROLE[nextRole].short} ทาง LINE`,'checkCircle');
    }
  };
  const handleSetApprover = (r, teacherId)=>{
    setApproverRoles(prev=>{
      const n={...prev};
      if(teacherId) Object.keys(n).forEach(rr=>{ if(n[rr]===teacherId) delete n[rr]; });
      if(teacherId) n[r]=teacherId; else delete n[r];
      return n;
    });
    if(teacherId) fireToast(`แต่งตั้ง ${fullTitle(teacherById(teacherId))} เป็น ${APPROVER_BY_ROLE[r].title}`,'checkCircle');
    else fireToast(`ยกเลิกตำแหน่ง ${APPROVER_BY_ROLE[r].short} แล้ว`,'info');
  };

  const resetDemo = ()=>{ if(!confirm('ล้างข้อมูลทั้งหมดและกลับสู่ค่าเริ่มต้น?')) return;
    localStorage.removeItem(LS_KEY);
    setAssignments(SEED.slice()); setNotifications(seedNotifications(SEED)); setSeen([]);
    setSchedules(defaultSchedules()); setDuties(defaultDuties()); setCredentials(defaultCredentials()); setExtraTeachers([]); setTeacherEdits({}); setLineLinks({}); setChairs({}); setApprovals(seedApprovals(SEED)); setApproverRoles({...DEFAULT_APPROVER_ROLES}); pruneExtraTeachers(); fireToast('รีเซ็ตข้อมูลแล้ว','info'); };

  const myChairGroup = meT ? chairGroupOf(chairs, meT.id) : null;

  const meLinked = meT ? lineLinks[meT.id] : null;
  const lineLinkedForView = !!meLinked;
  const lineAccount = meT ? {id:meT.id, name:fullTitle(meT), sub: myApproverRole?APPROVER_BY_ROLE[myApproverRole].short:meT.primary, username:meT.username} : null;
  const TABS = isAdmin
    ? [{id:'admin',label:'ภาพรวมการจัดสอนแทน',icon:'shield'},{id:'dashboard',label:'แดชบอร์ดการลา',icon:'layers'},{id:'users',label:'จัดการผู้ใช้งาน',icon:'users'}]
    : [
        ...(myApproverRole ? [
          {id:'approve',label:'พิจารณาอนุญาตการลา',icon:'shield', badge:pendingApprovals},
          {id:'dashboard',label:'แดชบอร์ดการลา',icon:'layers'},
        ] : []),
        {id:'schedule',label:'ภาระงานสอนของฉัน',icon:'clipboard'},
        {id:'leave',   label:'แจ้งลา / ขอเปลี่ยนคาบ',icon:'calendar'},
        {id:'sub',     label:'รายการสอนแทนของฉัน',icon:'inbox', badge:pendingForMe},
        ...(myChairGroup ? [{id:'chair', label:'ประธานกลุ่มสาระ', icon:'shield'}] : []),
      ];
  // ถ้า view ปัจจุบันไม่มีในแท็บของบทบาทนี้ ให้ไปแท็บแรก
  const activeView = TABS.some(t=>t.id===view) ? view : (TABS[0] && TABS[0].id);

  return (
    <div className="app">
      <header className="appbar">
        <div className="appbar-in">
          <div className="brand">
            <div className="crest"><img src="logo.png" alt="ตราโรงเรียน"/></div>
            <div className="brand-txt">
              <div className="t1">ระบบจัดการสอนแทน</div>
              <div className="t2">โรงเรียนหนองตาคงพิทยาคาร</div>
            </div>
          </div>
          <span className="spacer"/>
          {(isTeacher||isApprover) && (
            <button className="line-btn" onClick={openLine}>
              <Icon name="bell" size={16}/> LINE {unread>0 && lineLinkedForView && <span className="dot num">{unread}</span>}
            </button>
          )}
          <div className="user-chip">
            {isAdmin ? <span className="av av-sm" style={{background:'var(--brand-500)'}}><Icon name="shield" size={15}/></span>
              : <Avatar t={meT} size="sm"/>}
            <div>
              <div className="ui">{isAdmin?'งานวิชาการ / ผู้บริหาร': formalName(meT)}</div>
              <div className="ur">{isAdmin?'ผู้ดูแลภาพรวม': myApproverRole?APPROVER_BY_ROLE[myApproverRole].title : `ครูผู้สอน · ${meT.primary}`}</div>
            </div>
            <button className="logout-btn" title="ตั้งค่าบัญชี / เปลี่ยนรหัสผ่าน" onClick={()=>setAcct(true)}><Icon name="edit" size={15}/></button>
            <button className="logout-btn" title="ออกจากระบบ" onClick={logout}><Icon name="arrowLeft" size={16}/></button>
          </div>
        </div>
      </header>

      <div className="tabs-wrap">
        <div className="tabs">
          {TABS.map(t=>(
            <button key={t.id} className={`tab ${activeView===t.id?'active':''}`} onClick={()=>setView(t.id)}>
              <Icon name={t.icon} size={17}/>{t.label}{t.badge>0 && <span className="pill num">{t.badge}</span>}
            </button>
          ))}
        </div>
      </div>

      <main className="main">
        <div className="container">
          {isTeacher && !meLinked && (
            <div className="line-banner">
              <span className="lb-ic"><Icon name="swap" size={19}/></span>
              <div className="lb-t"><b>ยังไม่ได้เชื่อมบัญชี LINE</b><div>เชื่อมบัญชี LINE ของคุณกับระบบ เพื่อรับการแจ้งเตือนเมื่อมีครูขอให้สอนแทน</div></div>
              <Btn variant="green" icon="swap" onClick={()=>setLinking(true)}>เชื่อมบัญชี LINE</Btn>
            </div>
          )}
          {isTeacher && meLinked && (
            <div className="flex ac gap10 wrap" style={{marginBottom:16}}>
              <span className="line-link-status"><span className="ds"></span>เชื่อม LINE แล้ว · {meLinked.lineName}</span>
              <button className="tiny" style={{background:'none',border:'none',color:'var(--ink-3)',textDecoration:'underline',cursor:'pointer'}} onClick={()=>handleUnlinkLine(meT.id)}>ยกเลิกการเชื่อม</button>
            </div>
          )}
          {isTeacher && activeView==='schedule' && <ScheduleView me={meT} schedule={schedules[meT.id]||meT.schedule} duties={duties[meT.id]||[]} onUpdateCell={setCell} onDeleteCell={(d,p)=>setCell(d,p,null)} onAddDuty={addDuty} onRemoveDuty={removeDuty}/>}
          {isTeacher && activeView==='leave' && <LeaveView me={meT} assignments={assignments} schedules={schedules} approvals={approvals} onSubmit={handleSubmit} onRequestApproval={requestApproval}/>}
          {isTeacher && activeView==='sub' && <SubstituteView me={meT} assignments={assignments} onAcknowledge={handleAck} onReject={handleReject}/>}
          {isTeacher && activeView==='chair' && myChairGroup && <ChairView chair={meT} group={myChairGroup} members={membersOfGroup(myChairGroup)} assignments={assignments} schedules={schedules} lineLinks={lineLinks} onSubmit={handleSubmit}/>}
          {isApprover && activeView==='approve' && <ApproverView approver={approver} assignments={assignments} approvals={approvals} onDecide={decideApproval}/>}
          {(isAdmin||isApprover) && activeView==='dashboard' && <DashboardView assignments={assignments} approvals={approvals}/>}
          {isAdmin && activeView==='admin' && <AdminView assignments={assignments} onEditAssignment={updateAssign} onDeleteAssignment={(id)=>setAssignments(arr=>arr.filter(a=>a.id!==id))}/>}
          {isAdmin && activeView==='users' && <AdminUsers credentials={credentials} chairs={chairs} lineLinks={lineLinks} approverRoles={approverRoles} onAddTeacher={handleAddTeacher} onEditTeacher={handleEditTeacher} onResetPassword={handleResetPassword} onSetChair={handleSetChair} onSetApprover={handleSetApprover}/>}

          <div className="flex ac jc gap8" style={{marginTop:36,paddingTop:18,borderTop:'1px dashed var(--line)'}}>
            <span className="tiny">ต้นแบบระบบ — โรงเรียนหนองตาคงพิทยาคาร · ข้อมูลตารางสอน 1/2569</span>
            <span className="tiny">·</span>
            <button className="tiny" style={{background:'none',border:'none',color:'var(--brand-600)',textDecoration:'underline',cursor:'pointer'}} onClick={resetDemo}>รีเซ็ตข้อมูล</button>
          </div>
        </div>
      </main>

      {lineOpen && lineAccount && <LinePhone account={lineAccount} linked={lineLinkedForView} lineName={meLinked?meLinked.lineName:(approver?approver.short:'')} onLink={()=>{setLineOpen(false);setLinking(true);}} notifications={notifications} onClose={()=>setLineOpen(false)} onOpenLink={(n)=>{setLineOpen(false);setView(n.type==='approval'?'approve':'sub');}}/>}
      {linking && meT && <LineLinkModal me={meT} onLink={handleLinkLine} onClose={()=>setLinking(false)}/>}
      {acct && <AccountModal accountId={isAdmin?'admin':session.teacherId} label={isAdmin?'งานวิชาการ / ผู้บริหาร':formalName(meT)} credentials={credentials} onSave={saveAccount} onClose={()=>setAcct(false)}/>}
      {toast && <Toast msg={toast.msg} icon={toast.icon}/>}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
