/* ============================================================
   data.jsx — ข้อมูล + ตัวช่วย (ใช้ตารางสอนจริงจาก school_data.js)
   ============================================================ */

const DAYS = ['อาทิตย์','จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์','เสาร์'];
const WEEKDAYS = ['จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์'];
const THAI_MONTHS = ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.','ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'];
const BASE_DATE = '2026-06-02';

const PERIODS = (window.PERIOD_TIMES || []).map((t,i)=>({p:i+1, t}));

const REASONS = [
  {id:'kit', label:'ลากิจ',    verb:'ลากิจ',     desc:'ธุระส่วนตัวจำเป็น',  tag:'rt-kit',  icon:'briefcase'},
  {id:'sick',label:'ลาป่วย',   verb:'ลาป่วย',    desc:'เจ็บป่วย/พบแพทย์',   tag:'rt-sick', icon:'thermometer'},
  {id:'gov', label:'ไปราชการ', verb:'ไปราชการ',  desc:'อบรม/ประชุม/นิเทศ',  tag:'rt-gov',  icon:'flag'},
  {id:'early',label:'ขอออกก่อนเวลา', verb:'ขอออกก่อนเวลา', desc:'ออกระหว่างวัน', tag:'rt-early', icon:'clock'},
];

// ---------- ผู้อนุมัติการลา (3 ขั้น) ----------
const APPROVERS = [
  {id:'deputy_academic',  role:'deputy_academic',  username:'wichakan', defaultPassword:'1234', title:'รองผู้อำนวยการกลุ่มบริหารงานวิชาการ', short:'รองฯ วิชาการ', step:'เห็นควรอนุญาต', color:'#1d6f8a', init:'ว'},
  {id:'deputy_personnel', role:'deputy_personnel', username:'bukkon',   defaultPassword:'1234', title:'รองผู้อำนวยการกลุ่มบริหารงานบุคคล', short:'รองฯ บุคคล', step:'เห็นควรอนุญาต', color:'#6b41ad', init:'บ'},
  {id:'director',         role:'director',         username:'director', defaultPassword:'1234', title:'ผู้อำนวยการโรงเรียน', short:'ผู้อำนวยการ', step:'อนุญาต', color:'#b45309', init:'ผ'},
];
const APPROVAL_CHAIN = ['deputy_academic','deputy_personnel','director'];
const APPROVER_BY_ID = Object.fromEntries(APPROVERS.map(a=>[a.id,a]));
const APPROVER_BY_ROLE = Object.fromEntries(APPROVERS.map(a=>[a.role,a]));
const APPROVER_ROLES = APPROVERS.map(a=>a.role);
const isApproverRole = r => APPROVER_ROLES.includes(r);
// บทบาทผู้อนุมัติผูกกับบัญชีครูจริง: role -> teacherId
const DEFAULT_APPROVER_ROLES = {director:'t1', deputy_personnel:'t2', deputy_academic:'t3'};
function roleOfTeacher(approverRoles, teacherId){
  if(!approverRoles || !teacherId) return null;
  return Object.keys(approverRoles).find(role=>approverRoles[role]===teacherId) || null;
}

// ---------- ภาคเรียน ----------
const SEMESTERS = [
  {id:'1/2569', label:'ภาคเรียนที่ 1 / 2569', start:'2026-05-16', end:'2026-10-10'},
  {id:'2/2569', label:'ภาคเรียนที่ 2 / 2569', start:'2026-10-11', end:'2027-03-31'},
];
const semesterOf = iso => SEMESTERS.find(s=> iso>=s.start && iso<=s.end) || null;

const TEACHERS = (window.SCHOOL_TEACHERS || []).map(t=>({...t}));
const ADMIN = window.ADMIN_ACCOUNT || {username:'admin', password:'admin1234', name:'งานวิชาการ / ผู้บริหาร'};
const ADMIN_TEACHERS = TEACHERS.filter(t=>t.primary==='งานบริหาร/อื่น ๆ');

const teacherById = id => TEACHERS.find(t=>t.id===id);
const fullTitle  = t => t ? `ครู${t.short}` : '—';
const formalName = t => t ? `${t.pre}${t.name}` : '—';

// ---------- กลุ่มสาระ / ประธานกลุ่มสาระ ----------
const membersOfGroup = group => TEACHERS.filter(t=>t.primary===group && t.primary!=='งานบริหาร/อื่น ๆ');
const chairGroupOf = (chairs, teacherId) => {
  if(!chairs) return null;
  const g = Object.keys(chairs).find(grp=>chairs[grp]===teacherId);
  return g || null;
};
const isChairOfAny = (chairs, teacherId) => !!chairGroupOf(chairs, teacherId);

// รายชื่อชั้นเรียนทั้งหมด (จากตารางสอนจริง)
const ALL_CLASSES = (()=>{
  const set = new Set();
  TEACHERS.forEach(t=>WEEKDAYS.forEach(d=>(t.schedule[d]||[]).forEach(s=>{ if(s&&s.className) set.add(s.className); })));
  return [...set].sort((a,b)=>a.localeCompare(b,'th',{numeric:true}));
})();
const SUBJECT_GROUPS = ['ภาษาไทย','คณิตศาสตร์','วิทยาศาสตร์และเทคโนโลยี','สังคมศึกษาฯ','ภาษาต่างประเทศ','สุขศึกษาและพลศึกษา','ศิลปะ','การงานอาชีพ','การค้นคว้าอิสระ(IS)','รายวิชาเพิ่มเติม'];

// ---------- auth ----------
function defaultCredentials(){
  const c = {admin:{username:ADMIN.username, password:ADMIN.password}};
  TEACHERS.forEach(t=>{ c[t.id]={username:t.username, password:t.password}; });
  return c;
}
function authenticate(creds, username, password){
  const u = (username||'').trim().toLowerCase();
  if(creds.admin && u===creds.admin.username.toLowerCase() && password===creds.admin.password) return {role:'admin'};
  const entry = Object.entries(creds).find(([id,c])=> id!=='admin' && c.username.toLowerCase()===u && c.password===password);
  if(entry) return {role:'teacher', teacherId:entry[0]};
  return null;
}
function usernameTaken(creds, username, exceptId){
  const u = (username||'').trim().toLowerCase();
  return Object.entries(creds).some(([id,c])=> id!==exceptId && c.username.toLowerCase()===u);
}

// ---------- date helpers ----------
const weekdayName = iso => DAYS[new Date(iso+'T00:00:00').getDay()];
const isWeekday = iso => WEEKDAYS.includes(weekdayName(iso));
function formatThaiDate(iso, withDay){
  if(!iso) return '—';
  const d = new Date(iso+'T00:00:00');
  const dd = String(d.getDate()).padStart(2,'0');
  const mm = String(d.getMonth()+1).padStart(2,'0');
  const yy = d.getFullYear()+543;
  return (withDay?`${DAYS[d.getDay()]}ที่ `:'')+`${dd}/${mm}/${yy}`;
}
function nextWeekdayISO(n){
  const d = new Date(BASE_DATE+'T00:00:00'); let c=0;
  while(true){ d.setDate(d.getDate()+1); if(WEEKDAYS.includes(DAYS[d.getDay()])){ if(++c===n) break; } }
  return d.toISOString().slice(0,10);
}

// ---------- schedule helpers (รับ schedule object เป็น argument) ----------
function classesOnDay(schedule, iso){
  if(!schedule || !isWeekday(iso)) return [];
  const arr = schedule[weekdayName(iso)] || [];
  return arr.map((s,i)=> (s&&s.code) ? {period:i+1, time:PERIODS[i]?.t, ...s} : null).filter(Boolean);
}
function activitiesOnDay(schedule, iso){
  if(!schedule || !isWeekday(iso)) return [];
  const arr = schedule[weekdayName(iso)] || [];
  return arr.map((s,i)=> (s&&s.activity) ? {period:i+1, time:PERIODS[i]?.t, activity:s.activity} : null).filter(Boolean);
}
function isFreeIn(schedule, iso, period){
  if(!schedule || !isWeekday(iso)) return true;
  const w = weekdayName(iso);
  return !(schedule[w] && schedule[w][period-1]);
}
function busyWith(schedule, iso, period){
  if(!schedule || !isWeekday(iso)) return null;
  const w = weekdayName(iso);
  return (schedule[w] && schedule[w][period-1]) || null;
}
function teachesClass(schedule, cls){
  if(!schedule||!cls) return false;
  return WEEKDAYS.some(d=>(schedule[d]||[]).some(s=>s&&s.className===cls));
}

// หาคาบสอนชดเชยที่ตรงกับตารางของครูสอนแทนในห้องเดียวกัน (ไม่กระทบตารางนักเรียน)
// คืน list {iso, period, time, day, slot} จากวันถัดไปของ fromIso เป็นต้นไป จนถึง maxDays วันทำการ
function findMakeupSlots(subSchedule, fromIso, cls, maxDays){
  const out = [];
  if(!subSchedule || !cls) return out;
  const limit = maxDays || 30;
  const d = new Date(fromIso+'T00:00:00');
  for(let i=0; i<limit; i++){
    d.setDate(d.getDate()+1);
    const iso = d.toISOString().slice(0,10);
    if(!isWeekday(iso)) continue;
    const w = weekdayName(iso);
    const row = subSchedule[w] || [];
    row.forEach((s,idx)=>{
      if(s && s.className===cls){
        out.push({iso, period:idx+1, time:PERIODS[idx]?.t, day:w, slot:s});
      }
    });
  }
  return out;
}

// จัดอันดับครูสอนแทน: (1) ว่าง+เคยสอนห้องนี้ (2) ว่าง (3) ติดสอน — ผู้บริหารอยู่ท้ายกลุ่ม
function rankSubstitutes(schedules, iso, period, cls, excludeId){
  const rows = TEACHERS.filter(t=>t.id!==excludeId).map(t=>{
    const sch = schedules[t.id] || t.schedule;
    const free = isFreeIn(sch, iso, period);
    const tcls = teachesClass(sch, cls);
    const busy = busyWith(sch, iso, period);
    const isAdmin = t.primary==='งานบริหาร/อื่น ๆ';
    let rank = free ? (tcls?0:1) : (tcls?2:3);
    if(isAdmin) rank += 0.4;
    return {teacher:t, free, teachesClass:tcls, busy, isAdmin, rank};
  });
  rows.sort((a,b)=> a.rank-b.rank || a.teacher.short.localeCompare(b.teacher.short,'th'));
  return rows;
}

// ---------- LINE message builders ----------
const SYSTEM_LINK = 'https://ntk-substitute.school/รับทราบ';
function buildRequestMsg(a){
  const lt=teacherById(a.leaveTeacherId), sub=teacherById(a.substituteId), r=REASONS.find(x=>x.id===a.reason);
  return `เนื่องจาก ${fullTitle(lt)} มีความจำเป็นต้อง${r.verb} ในวัน${formatThaiDate(a.date,true)} `+
    `จึงขอเปลี่ยนคาบสอนกับ ${fullTitle(sub)} ในคาบเรียนที่ ${a.period} ชั้น ${a.className} `+
    `และจะมาทำการสอนชดเชย ในวันที่ ${formatThaiDate(a.makeupDate)} คาบที่ ${a.makeupPeriod} `+
    `ขอให้คุณครูเข้าไปกดรับทราบใน ${SYSTEM_LINK}`;
}
function buildConfirmMsg(a){
  const sub=teacherById(a.substituteId);
  return `${fullTitle(sub)} ได้กดรับทราบการสอนแทนเรียบร้อยแล้ว ✓ คาบที่ ${a.period} ชั้น ${a.className} วัน${formatThaiDate(a.date,true)} ขอบคุณค่ะ/ครับ`;
}
function buildRejectMsg(a){
  const sub=teacherById(a.substituteId);
  return `${fullTitle(sub)} ไม่สามารถรับสอนแทนได้ คาบที่ ${a.period} ชั้น ${a.className} วัน${formatThaiDate(a.date,true)} เนื่องจาก “${a.rejectReason||'-'}” กรุณาเลือกครูสอนแทนท่านใหม่ในระบบ`;
}

// ---------- ข้อความขออนุญาตลา (ส่งถึงผู้อนุมัติแต่ละขั้น) ----------
function summarizeGroup(group){
  const periods = group.map(a=>a.period).sort((x,y)=>x-y).join(', ');
  const classes = [...new Set(group.map(a=>a.className))].join(', ');
  return {periods, classes};
}
function buildApprovalMsg(group, role){
  const lt = teacherById(group[0].leaveTeacherId);
  const r = REASONS.find(x=>x.id===group[0].reason);
  const {periods, classes} = summarizeGroup(group);
  const ap = APPROVER_BY_ROLE[role];
  const act = role==='director' ? 'โปรดพิจารณาอนุญาต' : 'โปรดพิจารณาให้ความเห็นชอบ (เห็นควรอนุญาต)';
  return `เรียน ${ap.title}\n${fullTitle(lt)} (${lt.primary}) ขออนุญาต${r.verb} ในวัน${formatThaiDate(group[0].date,true)} คาบที่ ${periods} ชั้น ${classes} โดยได้จัดครูสอนแทนเรียบร้อยแล้ว จึงขอความกรุณา${act} โดยเข้าไปดำเนินการในระบบ ${SYSTEM_LINK}`;
}
function buildApprovalResultMsg(group, approved, byRole, note){
  const r = REASONS.find(x=>x.id===group[0].reason);
  if(approved){
    return `การขออนุญาต${r.verb} ในวัน${formatThaiDate(group[0].date,true)} ของท่าน “ได้รับการอนุญาต” จากผู้อำนวยการโรงเรียนเรียบร้อยแล้ว`;
  }
  const who = APPROVER_BY_ROLE[byRole] ? APPROVER_BY_ROLE[byRole].title : 'ผู้พิจารณา';
  return `การขออนุญาต${r.verb} ในวัน${formatThaiDate(group[0].date,true)} ของท่าน “ไม่ได้รับการอนุมัติ” โดย ${who}${note?` เนื่องจาก “${note}”`:''} กรุณาติดต่อฝ่ายบริหาร`;
}

let _seq = 900;
const newId = ()=> 'a'+(++_seq);
const SEED = window.SEED_ASSIGNMENTS || [];

// ---------- เพิ่มผู้ใช้ใหม่ (เฉพาะ admin) ----------
const ORIGINAL_TEACHER_IDS = new Set(TEACHERS.map(t=>t.id));
const ADD_PALETTE = ['#1f4ba0','#2563c9','#6b41ad','#0d7a64','#b45309','#b5403a','#3a5fb0','#477e3f','#9a4e8e','#1d6f8a','#7a5a1f','#34598a','#8a4b2d','#5b6f1f','#2d6a8a','#7a2d5a'];
function emptySchedule(){ const s={}; WEEKDAYS.forEach(d=>s[d]=Array(8).fill(null)); return s; }
function nextUsername(creds){
  let max=0;
  const scan = u => { const m=/^kru(\d+)$/.exec(u||''); if(m) max=Math.max(max,+m[1]); };
  if(creds) Object.values(creds).forEach(c=>scan(c.username));
  TEACHERS.forEach(t=>scan(t.username));
  return 'kru'+String(max+1).padStart(2,'0');
}
function makeTeacher({pre, name, primary}, username){
  const nm = (name||'').trim();
  const short = nm.split(' ')[0] || nm;
  return {
    id:'x'+Date.now(), username, password:'1234', pre, name:nm, short,
    init:short.slice(0,1), color:ADD_PALETTE[TEACHERS.length % ADD_PALETTE.length],
    primary, subjects:[primary], schedule:emptySchedule(), duties:[],
  };
}
function registerTeacher(t){ if(t && !TEACHERS.some(x=>x.id===t.id)) TEACHERS.push(t); }
function pruneExtraTeachers(){ for(let i=TEACHERS.length-1;i>=0;i--) if(!ORIGINAL_TEACHER_IDS.has(TEACHERS[i].id)) TEACHERS.splice(i,1); }

// แก้ไขข้อมูลครู (เฉพาะ admin) — คืนค่า patch ที่ normalize แล้ว เพื่อเก็บ persist
function applyTeacherEdit(t, patch){
  if(!t) return;
  if(patch.pre!==undefined) t.pre = patch.pre;
  if(patch.name!==undefined){
    const nm = (patch.name||'').trim();
    t.name = nm;
    t.short = nm.split(' ')[0] || nm;
    t.init = t.short.slice(0,1);
  }
  if(patch.primary!==undefined){
    t.primary = patch.primary;
    if(!t.subjects || !t.subjects.length) t.subjects = [patch.primary];
    else t.subjects = [patch.primary, ...t.subjects.filter(s=>s!==patch.primary)];
  }
}

Object.assign(window, {
  DAYS, WEEKDAYS, THAI_MONTHS, BASE_DATE, PERIODS, REASONS, TEACHERS, ADMIN, ADMIN_TEACHERS,
  APPROVERS, APPROVAL_CHAIN, APPROVER_BY_ID, APPROVER_BY_ROLE, APPROVER_ROLES, isApproverRole,
  DEFAULT_APPROVER_ROLES, roleOfTeacher,
  SEMESTERS, semesterOf,
  ALL_CLASSES, SUBJECT_GROUPS, teacherById, fullTitle, formalName, authenticate, defaultCredentials, usernameTaken,
  membersOfGroup, chairGroupOf, isChairOfAny,
  weekdayName, isWeekday, formatThaiDate, nextWeekdayISO,
  classesOnDay, activitiesOnDay, isFreeIn, busyWith, teachesClass, rankSubstitutes, findMakeupSlots,
  buildRequestMsg, buildConfirmMsg, buildRejectMsg, buildApprovalMsg, buildApprovalResultMsg, summarizeGroup,
  SYSTEM_LINK, newId, SEED,
  emptySchedule, nextUsername, makeTeacher, registerTeacher, pruneExtraTeachers, applyTeacherEdit, ORIGINAL_TEACHER_IDS,
});
