/* global React, I, UI */
// =============== ลงเวลา (ใหม่): ทีละคน → บันทึกพับเก็บ + ละเว้นสาย + ลาเช้า/บ่าย + เวลากำหนดเอง ===============
// และแท็บ การมาสาย/ขาดงาน แบบรายงาน (ไม่หักเงิน) + พิมพ์ใบเตือน
const { useState: useStatePT, useEffect: useEffectPT, useMemo: useMemoPT } = React;

const PT_MONTHS_TH = ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."];
function ptMonthLabel(ym) { const [y, m] = ym.split("-").map(Number); return `${PT_MONTHS_TH[m - 1]} ${y + 543}`; }
function ptFmtThai(iso) { const [y, m, d] = iso.split("-").map(Number); return `${d} ${PT_MONTHS_TH[m - 1]} ${y + 543}`; }
function ptIsoOf(t) { return t.iso || (window.DocDates ? window.DocDates.toISO(t.date) : null) || ""; }
function ptLastDay(ym) { const [y, m] = ym.split("-").map(Number); return new Date(y, m, 0).getDate(); }

function ptLoadPolicy() {
  try {
    return JSON.parse(localStorage.getItem("sss-time-policy") || "null") || {
      defaultIn: "08:30", breakStart: "12:00", breakEnd: "13:00", defaultOut: "17:30",
      standardHours: 8, otMultiplier: 1.5, lateGraceMin: 5, lateDeductPerMin: 5
    };
  } catch { return {}; }
}

const PT_STATUSES = [
  { key: "ทำงาน", emoji: "💼" },
  { key: "OT", emoji: "⏰" },
  { key: "ลาเช้า", emoji: "🌅" },
  { key: "ลาบ่าย", emoji: "🌇" },
  { key: "กำหนดเอง", emoji: "✏️" },
  { key: "วันหยุด", emoji: "🏖️" },
  { key: "ลา", emoji: "🌴" },
  { key: "ขาด", emoji: "❌" },
  { key: "นอกสถานที่", emoji: "🚗" },
  { key: "ไม่พบข้อมูล", emoji: "❓" }
];
const PT_HALF_LEAVE = { "ลาเช้า": true, "ลาบ่าย": true };
const PT_NO_TIME = { "วันหยุด": true, "ลา": true, "ขาด": true, "นอกสถานที่": true, "ไม่พบข้อมูล": true };

// effective late = ละเว้นแล้วเป็น 0
function ptLate(r) { return r.excuseLate ? 0 : (r.late || 0); }

// ---------- สรุปของพนักงานในเดือน ----------
function ptSummarize(rows) {
  const s = { days: 0, hours: 0, ot: 0, leave: 0, absent: 0, lateCount: 0, lateMin: 0, lateExcused: 0, lateRows: [], absentRows: [] };
  rows.forEach(r => {
    if (r.status === "ทำงาน" || r.status === "OT" || r.status === "กำหนดเอง" || r.status === "นอกสถานที่") s.days += 1;
    if (PT_HALF_LEAVE[r.status]) { s.days += 0.5; s.leave += 0.5; }
    if (r.status === "ลา") s.leave += 1;
    if (r.status === "ขาด") { s.absent += 1; s.absentRows.push(r); }
    s.hours += r.work || 0;
    s.ot += r.ot || 0;
    const late = ptLate(r);
    if (late > 0) { s.lateCount += 1; s.lateMin += late; s.lateRows.push(r); }
    if (r.excuseLate && (r.late || 0) > 0) s.lateExcused += 1;
  });
  return s;
}

// =============== แท็บลงเวลา ===============
function PayrollTimeTab({ timeRecs, setTimeRecs, month }) {
  const D = window.SSSData;
  const { Btn, Badge, Card } = window.UI;
  const [policy, setPolicy] = useStatePT(ptLoadPolicy);
  const [showPolicy, setShowPolicy] = useStatePT(false);
  useEffectPT(() => { localStorage.setItem("sss-time-policy", JSON.stringify(policy)); }, [policy]);

  const [empId, setEmpId] = useStatePT("");
  const [startDate, setStartDate] = useStatePT(month + "-01");
  const [endDate, setEndDate] = useStatePT(month + "-" + String(ptLastDay(month)).padStart(2, "0"));
  const [schedule, setSchedule] = useStatePT([]);
  const [expanded, setExpanded] = useStatePT(null); // empId ที่กางดูรายละเอียด

  useEffectPT(() => {
    setStartDate(month + "-01");
    setEndDate(month + "-" + String(ptLastDay(month)).padStart(2, "0"));
  }, [month]);

  const emp = D.Employees.find(e => e.id === empId);
  const toMin = (t) => { if (!t) return 0; const [h, m] = t.split(":").map(Number); return h * 60 + m; };
  const breakMin = () => toMin(policy.breakEnd) - toMin(policy.breakStart);

  // คำนวนตามประเภทวัน
  const calcRow = (status, inT, outT) => {
    if (PT_NO_TIME[status]) return { work: status === "นอกสถานที่" ? policy.standardHours : 0, ot: 0, late: 0 };
    if (!inT || !outT) return { work: 0, ot: 0, late: 0 };
    const total = Math.max(0, toMin(outT) - toMin(inT));
    if (status === "ลาเช้า" || status === "ลาบ่าย" || status === "กำหนดเอง") {
      // ไม่มีพัก ไม่มี OT · ลาบ่ายคิดสายตามปกติ (มาช่วงเช้า)
      let late = 0;
      if (status === "ลาบ่าย") {
        const raw = Math.max(0, toMin(inT) - toMin(policy.defaultIn));
        late = raw > policy.lateGraceMin ? raw : 0;
      }
      return { work: Math.round(total / 60 * 100) / 100, ot: 0, late };
    }
    // ทำงาน / OT ปกติ
    const rawLate = Math.max(0, toMin(inT) - toMin(policy.defaultIn));
    const late = rawLate > policy.lateGraceMin ? rawLate : 0;
    const hrs = Math.max(0, total - breakMin()) / 60;
    const work = Math.min(hrs, policy.standardHours);
    const ot = Math.max(0, hrs - policy.standardHours);
    return { work: Math.round(work * 100) / 100, ot: Math.round(ot * 100) / 100, late };
  };

  const generateSchedule = () => {
    if (!empId) { window.toast && window.toast("เลือกพนักงานก่อน"); return; }
    if (!startDate || !endDate || endDate < startDate) { window.toast && window.toast("เลือกช่วงวันที่ให้ถูกต้อง"); return; }
    // ✅ สร้างรวดเดียวทั้งบริษัท — พนักงานทุกคน วันทำงานตามนโยบาย (เสาร์-อาทิตย์เป็นวันหยุด)
    if (empId === "__ALL__") {
      const merged = [...timeRecs];
      const targets = D.Employees.filter(e => e.id !== "EMP-001");
      targets.forEach(tgt => {
        const cur2 = new Date(startDate + "T00:00:00"); const end2 = new Date(endDate + "T00:00:00");
        while (cur2 <= end2) {
          const dow = cur2.getDay();
          const iso = `${cur2.getFullYear()}-${String(cur2.getMonth() + 1).padStart(2, "0")}-${String(cur2.getDate()).padStart(2, "0")}`;
          if (!merged.some(t => ptIsoOf(t) === iso && t.emp === tgt.id)) {
            const isWeekend = dow === 0 || dow === 6;
            const rec = window.QRTimeData ? window.QRTimeData.dayRecord(tgt.id, iso) : null;
            if (rec && rec.found) {
              merged.unshift({ iso, emp: tgt.id, name: tgt.name, date: ptFmtThai(iso), dow, status: rec.status, in: rec.in, out: rec.out, work: rec.work, ot: rec.ot, late: rec.late, excuseLate: false });
            } else if (isWeekend) {
              const c = calcRow("วันหยุด", "", "");
              merged.unshift({ iso, emp: tgt.id, name: tgt.name, date: ptFmtThai(iso), dow, status: "วันหยุด", in: "", out: "", excuseLate: false, ...c });
            } else {
              merged.unshift({ iso, emp: tgt.id, name: tgt.name, date: ptFmtThai(iso), dow, status: "ไม่พบข้อมูล", in: "", out: "", work: 0, ot: 0, late: 0, excuseLate: false });
            }
          }
          cur2.setDate(cur2.getDate() + 1);
        }
      });
      setTimeRecs(merged);
      setEmpId("");
      window.toast && window.toast(`สร้างตารางเวลาให้พนักงาน ${targets.length} คนแล้ว — ดูและแก้ไขได้ด้านล่าง`);
      return;
    }
    const days = [];
    const cur = new Date(startDate + "T00:00:00");
    const end = new Date(endDate + "T00:00:00");
    let found = 0, missing = 0;
    while (cur <= end) {
      const dow = cur.getDay();
      const iso = `${cur.getFullYear()}-${String(cur.getMonth() + 1).padStart(2, "0")}-${String(cur.getDate()).padStart(2, "0")}`;
      const existing = timeRecs.find(t => ptIsoOf(t) === iso && t.emp === empId);
      const isWeekend = dow === 0 || dow === 6;
      if (existing) { days.push({ excuseLate: false, ...existing, iso, dow, date: ptFmtThai(iso) }); found++; }
      else {
        // ✅ ดึงจากข้อมูลลงเวลา QR จริง — ไม่สร้างเวลาใหม่
        const rec = window.QRTimeData ? window.QRTimeData.dayRecord(empId, iso) : null;
        if (rec && rec.found) {
          days.push({ iso, emp: empId, name: emp?.name, date: ptFmtThai(iso), dow, status: rec.status, in: rec.in, out: rec.out, work: rec.work, ot: rec.ot, late: rec.late, excuseLate: false });
          found++;
        } else if (isWeekend) {
          const c = calcRow("วันหยุด", "", "");
          days.push({ iso, emp: empId, name: emp?.name, date: ptFmtThai(iso), dow, status: "วันหยุด", in: "", out: "", excuseLate: false, ...c });
        } else {
          // ไม่มีข้อมูลลงเวลาของวันทำงาน — ให้ user แก้ไขเอง
          days.push({ iso, emp: empId, name: emp?.name, date: ptFmtThai(iso), dow, status: "ไม่พบข้อมูล", in: "", out: "", work: 0, ot: 0, late: 0, excuseLate: false });
          missing++;
        }
      }
      cur.setDate(cur.getDate() + 1);
    }
    setSchedule(days);
    window.toast && window.toast(`ดึงลงเวลา ${emp?.name} — พบข้อมูล ${found} วัน${missing ? ` · ไม่พบ ${missing} วัน (แก้ไขเอง)` : ""}`);
  };

  const updateRow = (i, patch) => {
    setSchedule(s => s.map((r, j) => {
      if (j !== i) return r;
      const next = { ...r, ...patch };
      if (patch.in !== undefined || patch.out !== undefined) {
        const c = calcRow(next.status, next.in, next.out);
        next.work = c.work; next.ot = c.ot; next.late = c.late;
        if (next.ot > 0 && next.status === "ทำงาน") next.status = "OT";
      }
      return next;
    }));
  };

  const onStatusChange = (i, status) => {
    const r = schedule[i];
    const p = { status, excuseLate: false };
    if (status === "วันหยุด" || status === "ลา" || status === "ขาด") { p.in = ""; p.out = ""; }
    else if (status === "นอกสถานที่") { p.in = ""; p.out = ""; }
    else if (status === "ลาเช้า") { p.in = policy.breakEnd; p.out = policy.defaultOut; }
    else if (status === "ลาบ่าย") { p.in = policy.defaultIn; p.out = policy.breakStart; }
    else if (status === "กำหนดเอง") { p.in = r.in || policy.defaultIn; p.out = r.out || "11:00"; }
    else if (status === "OT") { p.in = r.in || policy.defaultIn; p.out = "20:00"; }
    else { p.in = r.in || policy.defaultIn; p.out = policy.defaultOut; }
    const c = calcRow(status, p.in, p.out);
    p.work = c.work; p.ot = c.ot; p.late = c.late;
    updateRow(i, p);
  };

  const saveSchedule = () => {
    const merged = [...timeRecs];
    schedule.forEach(s => {
      const idx = merged.findIndex(t => ptIsoOf(t) === s.iso && t.emp === s.emp);
      if (idx >= 0) merged[idx] = s; else merged.unshift(s);
    });
    setTimeRecs(merged);
    setSchedule([]);           // พับเก็บ → ไปทำคนถัดไปได้เลย
    setExpanded(empId);
    setEmpId("");
    window.toast && window.toast(`บันทึกตารางของ ${emp?.name} แล้ว — พับเก็บในรายการด้านล่าง`);
  };

  // ---------- saved: จัดกลุ่มตามพนักงานในเดือนที่เลือก ----------
  const recsInMonth = useMemoPT(() => timeRecs.filter(t => ptIsoOf(t).startsWith(month)), [timeRecs, month]);
  const groups = useMemoPT(() => {
    const m = {};
    recsInMonth.forEach(t => { (m[t.emp] = m[t.emp] || []).push(t); });
    return Object.keys(m).map(id => {
      const rows = m[id].sort((a, b) => ptIsoOf(a).localeCompare(ptIsoOf(b)));
      const empD = D.Employees.find(e => e.id === id);
      return { empId: id, name: empD?.name || rows[0].name, role: empD?.role || "", rows, sum: ptSummarize(rows) };
    }).sort((a, b) => a.empId.localeCompare(b.empId));
  }, [recsInMonth]);

  const editGroup = (g) => {
    setEmpId(g.empId);
    setSchedule(g.rows.map(r => ({ excuseLate: false, ...r, iso: ptIsoOf(r), dow: new Date(ptIsoOf(r) + "T00:00:00").getDay(), date: ptFmtThai(ptIsoOf(r)) })));
    window.scrollTo && document.querySelector(".content")?.scrollTo({ top: 0, behavior: "smooth" });
  };
  const deleteGroup = async (g) => {
    const ok = await window.confirmDelete(`ตารางเวลา ${g.name}`, `${ptMonthLabel(month)} · ${g.rows.length} วัน`);
    if (!ok) return;
    setTimeRecs(timeRecs.filter(t => !(t.emp === g.empId && ptIsoOf(t).startsWith(month))));
  };

  const sum = ptSummarize(schedule);
  const cellStyle = { height: 32, padding: "0 8px", fontSize: 12 };

  return (
    <>
      {/* ---- ขั้น 1: เลือกคน + ช่วงวัน ---- */}
      <Card title="ลงเวลาทีละคน" sub={`เลือกพนักงาน → กด "สร้างตาราง" ระบบจะดึงข้อมูลจากลงเวลา QR · วันที่ไม่มีข้อมูลจะขึ้น "ไม่พบข้อมูล" ให้แก้ไขเอง · เดือน ${ptMonthLabel(month)}`}
        right={<Btn size="sm" kind="ghost" icon={I.cog} onClick={() => setShowPolicy(true)}>ตั้งค่าเวลา & OT</Btn>}>
        <div className="field-row cols-4">
          <div className="field"><label>พนักงาน</label>
            <select className="input" value={empId} onChange={e => setEmpId(e.target.value)}>
              <option value="">— เลือกพนักงาน —</option>
              <option value="__ALL__">👥 — พนักงานทั้งหมด (สร้างรวดเดียว) —</option>
              {D.Employees.map(e => {
                const done = groups.some(g => g.empId === e.id);
                return <option key={e.id} value={e.id}>{done ? "✓ " : ""}{e.id} · {e.name}</option>;
              })}
            </select>
          </div>
          <div className="field"><label>วันที่เริ่ม</label><input className="input" type="date" value={startDate} onChange={e => setStartDate(e.target.value)}></input></div>
          <div className="field"><label>วันที่สิ้นสุด</label><input className="input" type="date" value={endDate} onChange={e => setEndDate(e.target.value)}></input></div>
          <div className="field" style={{display: "flex", flexDirection: "column", justifyContent: "flex-end"}}>
            <Btn kind="primary" icon={I.calc} onClick={generateSchedule}>สร้างตาราง</Btn>
          </div>
        </div>
        <div style={{marginTop: 10, padding: "8px 12px", background: "var(--info-bg)", color: "var(--info)", borderRadius: 6, fontSize: 12.5, display: "flex", gap: 14, flexWrap: "wrap"}}>
          <span>⚙️ <b>นโยบาย:</b></span>
          <span>เข้า {policy.defaultIn} · ออก {policy.defaultOut} · พัก {policy.breakStart}-{policy.breakEnd}</span>
          <span>🌅 ลาเช้า = คิดเวลา {policy.breakEnd}–{policy.defaultOut}</span>
          <span>🌇 ลาบ่าย = คิดเวลา {policy.defaultIn}–{policy.breakStart}</span>
          <span>✏️ กำหนดเอง = กรอกเข้า-ออกเอง ไม่หักพัก</span>
        </div>
      </Card>

      {/* ---- ขั้น 2: กรอกตาราง ---- */}
      {schedule.length > 0 && (
        <Card flush title={`กำลังกรอก: ${emp?.name} · ${schedule.length} วัน`}
          sub={`ทำงาน ${sum.days} วัน · ${sum.hours.toFixed(1)} ชม. · OT ${sum.ot.toFixed(1)} ชม. · ลา ${sum.leave} · ขาด ${sum.absent} · สาย ${sum.lateCount} ครั้ง (${sum.lateMin} นาที)`}
          right={<>
            <Btn size="sm" kind="ghost" onClick={() => { setSchedule([]); }}>ยกเลิก</Btn>
            <Btn size="sm" kind="primary" icon={I.check} onClick={saveSchedule}>บันทึก + พับเก็บ</Btn>
          </>}>
          <div className="table-wrap">
            <table className="t" style={{fontSize: 13}}>
              <thead>
                <tr>
                  <th style={{width: 38}}>วัน</th>
                  <th style={{width: 105}}>วันที่</th>
                  <th style={{width: 150}}>สถานะ</th>
                  <th style={{width: 92}}>เข้างาน</th>
                  <th style={{width: 92}}>เลิกงาน</th>
                  <th className="right" style={{width: 70}}>ชม.</th>
                  <th className="right" style={{width: 64}}>OT</th>
                  <th className="right" style={{width: 70}}>สาย<div style={{fontSize: 9, fontWeight: 400, color: "var(--ink-4)"}}>(นาที)</div></th>
                  <th style={{width: 86, textAlign: "center"}}>ละเว้นสาย<div style={{fontSize: 9, fontWeight: 400, color: "var(--ink-4)"}}>มีเหตุจำเป็น</div></th>
                </tr>
              </thead>
              <tbody>
                {schedule.map((r, i) => {
                  const isWeekend = r.dow === 0 || r.dow === 6;
                  const noTime = PT_NO_TIME[r.status];
                  const dayNames = ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส"];
                  return (
                    <tr key={r.iso} style={{background: isWeekend ? "var(--surface-2)" : "transparent"}}>
                      <td style={{textAlign: "center", color: isWeekend ? "var(--danger)" : "var(--ink-3)"}}>{dayNames[r.dow]}</td>
                      <td style={{fontSize: 12}}>{r.date}</td>
                      <td>
                        <select className="input" style={cellStyle} value={r.status} onChange={e => onStatusChange(i, e.target.value)}>
                          {PT_STATUSES.map(s => <option key={s.key} value={s.key}>{s.emoji} {s.key}</option>)}
                        </select>
                      </td>
                      <td><input className="input mono" type="time" style={cellStyle} disabled={noTime} value={r.in || ""} onChange={e => updateRow(i, { in: e.target.value })}></input></td>
                      <td><input className="input mono" type="time" style={cellStyle} disabled={noTime} value={r.out || ""} onChange={e => updateRow(i, { out: e.target.value })}></input></td>
                      <td className="right amount">{(r.work || 0).toFixed(1)}</td>
                      <td className="right amount" style={{color: r.ot > 0 ? "var(--info)" : "inherit", fontWeight: r.ot > 0 ? 600 : 400}}>{r.ot > 0 ? r.ot.toFixed(1) : "—"}</td>
                      <td className="right amount" style={{color: ptLate(r) > 0 ? "var(--danger)" : "inherit", textDecoration: r.excuseLate && r.late > 0 ? "line-through" : "none"}}>
                        {(r.late || 0) > 0 ? r.late : "—"}
                      </td>
                      <td style={{textAlign: "center"}}>
                        {(r.late || 0) > 0
                          ? <input type="checkbox" checked={!!r.excuseLate} title="ติ๊กเพื่อละเว้นการคิดมาสายของวันนี้" onChange={e => updateRow(i, { excuseLate: e.target.checked })} style={{width: 16, height: 16, accentColor: "var(--success)"}}></input>
                          : <span style={{color: "var(--ink-4)"}}>—</span>}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </Card>
      )}

      {/* ---- ขั้น 3: รายการที่บันทึกแล้ว (พับเป็นกล่องรายคน) ---- */}
      <div style={{marginTop: 14}}>
        <div style={{fontSize: 13.5, fontWeight: 700, marginBottom: 8}}>บันทึกแล้ว · {ptMonthLabel(month)} <span style={{fontWeight: 400, color: "var(--ink-3)", fontSize: 12}}>({groups.length} คน · กดเพื่อดูรายละเอียด)</span></div>
        {groups.length === 0 && <div style={{padding: 26, textAlign: "center", color: "var(--ink-3)", fontSize: 13, border: "1px dashed var(--line)", borderRadius: 10}}>ยังไม่มีตารางเวลาในเดือนนี้ — เลือกพนักงานด้านบนเพื่อเริ่มลงเวลา</div>}
        <div style={{display: "flex", flexDirection: "column", gap: 8}}>
          {groups.map(g => {
            const open = expanded === g.empId;
            return (
              <div key={g.empId} style={{border: "1px solid var(--line)", borderRadius: 10, background: "var(--surface)", overflow: "hidden"}}>
                <div onClick={() => setExpanded(open ? null : g.empId)} style={{display: "flex", alignItems: "center", gap: 12, padding: "10px 14px", cursor: "pointer", flexWrap: "wrap"}}>
                  {window.RankAvatar ? <window.RankAvatar name={g.name} size={32}/> : <span className="avatar" style={{width: 32, height: 32}}>{(g.name || "?").slice(0, 2)}</span>}
                  <div style={{minWidth: 150}}>
                    <div style={{fontSize: 13.5, fontWeight: 700}}>ของ {g.name}</div>
                    <div style={{fontSize: 11, color: "var(--ink-3)"}}>{g.role} · {g.rows.length} วันในตาราง</div>
                  </div>
                  <div style={{display: "flex", gap: 6, flexWrap: "wrap", flex: 1, fontSize: 11.5}}>
                    <span className="badge success">ทำงาน {g.sum.days} วัน</span>
                    <span className="badge outline">{g.sum.hours.toFixed(1)} ชม.</span>
                    {g.sum.ot > 0 && <span className="badge info">OT {g.sum.ot.toFixed(1)} ชม.</span>}
                    {g.sum.leave > 0 && <span className="badge">ลา {g.sum.leave} วัน</span>}
                    {g.sum.absent > 0 && <span className="badge danger">ขาด {g.sum.absent} วัน</span>}
                    {g.sum.lateMin > 0 && <span className="badge warning">สาย {g.sum.lateCount} ครั้ง · {g.sum.lateMin} นาที</span>}
                    {g.sum.lateExcused > 0 && <span className="badge outline">ละเว้นสาย {g.sum.lateExcused} ครั้ง</span>}
                  </div>
                  <div style={{display: "flex", gap: 4}} onClick={e => e.stopPropagation()}>
                    <Btn size="sm" kind="ghost" icon={I.edit} onClick={() => editGroup(g)}>แก้ไข</Btn>
                    <button className="icon-btn" title="ลบตารางทั้งเดือนของคนนี้" onClick={() => deleteGroup(g)}><I.trash size={13}/></button>
                    <button className="icon-btn" title={open ? "พับเก็บ" : "ดูรายละเอียด"} onClick={() => setExpanded(open ? null : g.empId)}>{open ? <I.chevronUp size={13}/> : <I.chevronDown size={13}/>}</button>
                  </div>
                </div>
                {open && (
                  <div className="table-wrap" style={{borderTop: "1px solid var(--line)"}}>
                    <table className="t" style={{fontSize: 12.5}}>
                      <thead><tr><th>วันที่</th><th>สถานะ</th><th>เข้า</th><th>ออก</th><th className="right">ชม.</th><th className="right">OT</th><th className="right">สาย</th><th></th></tr></thead>
                      <tbody>
                        {g.rows.map((t, i) => (
                          <tr key={i}>
                            <td>{t.date || ptFmtThai(ptIsoOf(t))}</td>
                            <td><Badge>{t.status}</Badge>{t.excuseLate && (t.late || 0) > 0 && <span style={{fontSize: 10, color: "var(--success)", marginLeft: 6}}>ละเว้นสาย</span>}</td>
                            <td className="mono">{t.in || "—"}</td>
                            <td className="mono">{t.out || "—"}</td>
                            <td className="right amount">{(t.work || 0).toFixed(1)}</td>
                            <td className="right amount">{t.ot > 0 ? t.ot.toFixed(1) : "—"}</td>
                            <td className="right amount" style={{color: ptLate(t) > 0 ? "var(--danger)" : "inherit", textDecoration: t.excuseLate && t.late > 0 ? "line-through" : "none"}}>{(t.late || 0) > 0 ? t.late : "—"}</td>
                            <td><button className="icon-btn" onClick={async () => {
                              const ok = await window.confirmDelete("ตารางเวลา " + (t.date || ptIsoOf(t)), g.name);
                              if (ok) setTimeRecs(timeRecs.filter(x => x !== t));
                            }}><I.trash size={12}/></button></td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>

      {showPolicy && window.PayrollPolicyModal && <window.PayrollPolicyModal policy={policy} setPolicy={setPolicy} onClose={() => setShowPolicy(false)}/>}
    </>
  );
}

// =============== ใบเตือน (พิมพ์ได้) ===============
function ptPrintWarning(g, month) {
  const C = window.SSSData.Company;
  const ML = ptMonthLabel(month);
  const esc = (s) => String(s || "").replace(/&/g, "&amp;").replace(/</g, "&lt;");
  const lateList = g.sum.lateRows.map(r => `<li>มาสาย ${r.late} นาที — วันที่ ${esc(r.date || ptFmtThai(ptIsoOf(r)))} (เข้างาน ${esc(r.in)} น.)</li>`).join("");
  const absentList = g.sum.absentRows.map(r => `<li>ขาดงาน — วันที่ ${esc(r.date || ptFmtThai(ptIsoOf(r)))}</li>`).join("");

  const html = `<div style="background:white;color:#0c0a09;padding:36px 46px;min-height:90vh;border-top:5px solid #b45309;font-size:13px;line-height:1.8">
    <div style="display:flex;justify-content:space-between;align-items:flex-start">
      <div style="display:flex;gap:14px;align-items:center">
        <div style="width:52px;height:52px;background:#0c0a09;color:white;display:grid;place-items:center;font-weight:700;font-size:16px;border-radius:5px">SSS</div>
        <div>
          <div style="font-weight:700;font-size:14px">${esc(C.name)}</div>
          <div style="font-size:10.5px;color:#57534e;max-width:340px">${esc(C.address)}</div>
          <div style="font-size:10.5px;color:#57534e">โทร ${esc(C.phone)}</div>
        </div>
      </div>
      <div style="text-align:right">
        <h1 style="margin:0;font-size:24px;color:#b45309;font-weight:700">หนังสือเตือน</h1>
        <div style="font-size:10.5px;color:#78716c;letter-spacing:0.1em">WARNING LETTER</div>
        <div style="font-size:11px;margin-top:8px">วันที่ออก: 22 พ.ค. 2569</div>
      </div>
    </div>

    <div style="margin-top:26px;padding:12px 16px;border:1px solid #e7e5e4;border-radius:6px;display:flex;gap:30px;flex-wrap:wrap;font-size:12.5px">
      <span>ถึง: <b>${esc(g.name)}</b></span>
      <span>ตำแหน่ง: <b>${esc(g.role || "—")}</b></span>
      <span>รหัส: <b style="font-family:monospace">${esc(g.empId)}</b></span>
      <span>ประจำเดือน: <b>${esc(ML)}</b></span>
    </div>

    <p style="margin-top:22px">บริษัทฯ ขอแจ้งเตือนเรื่องการมาปฏิบัติงานของท่านในเดือน ${esc(ML)} ซึ่งมีรายละเอียดดังนี้</p>

    <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin:14px 0">
      <div style="border:1px solid #e7e5e4;border-radius:6px;padding:10px;text-align:center"><div style="font-size:11px;color:#78716c">มาทำงาน</div><div style="font-size:20px;font-weight:700">${g.sum.days} วัน</div></div>
      <div style="border:1px solid #e7e5e4;border-radius:6px;padding:10px;text-align:center"><div style="font-size:11px;color:#78716c">มาสาย</div><div style="font-size:20px;font-weight:700;color:#b45309">${g.sum.lateCount} ครั้ง · ${g.sum.lateMin} นาที</div></div>
      <div style="border:1px solid #e7e5e4;border-radius:6px;padding:10px;text-align:center"><div style="font-size:11px;color:#78716c">ขาดงาน</div><div style="font-size:20px;font-weight:700;color:#dc2626">${g.sum.absent} วัน</div></div>
      <div style="border:1px solid #e7e5e4;border-radius:6px;padding:10px;text-align:center"><div style="font-size:11px;color:#78716c">ลา</div><div style="font-size:20px;font-weight:700">${g.sum.leave} วัน</div></div>
    </div>

    ${(lateList || absentList) ? `<div style="font-weight:700;margin-top:8px">รายการที่เป็นเหตุแห่งการเตือน</div>
    <ul style="margin:6px 0 0;padding-left:22px;font-size:12.5px">${lateList}${absentList}</ul>` : ""}

    <p style="margin-top:18px">จึงขอให้ท่านปรับปรุงการมาปฏิบัติงานให้ตรงต่อเวลาและสม่ำเสมอ หากยังคงมีพฤติกรรมดังกล่าวซ้ำอีก บริษัทฯ อาจพิจารณาดำเนินการตามระเบียบข้อบังคับการทำงานต่อไป</p>

    <div style="display:grid;grid-template-columns:1fr 1fr;gap:40px;margin-top:60px;font-size:12px;text-align:center">
      <div><div style="border-top:1px dashed #57534e;padding-top:6px;margin-top:40px">ลงชื่อ ผู้บังคับบัญชา / ฝ่ายบุคคล<br/>วันที่ ............................</div></div>
      <div><div style="border-top:1px dashed #57534e;padding-top:6px;margin-top:40px">ลงชื่อ ${esc(g.name)} (พนักงานรับทราบ)<br/>วันที่ ............................</div></div>
    </div>
  </div>`;

  document.getElementById("__print_modal")?.remove();
  document.body.classList.remove("printing-modal");
  const modal = document.createElement("div");
  modal.id = "__print_modal";
  modal.className = "print-modal";
  modal.innerHTML = `
    <div class="print-modal-bar no-print">
      <div style="font-weight:600;font-size:14px;flex:1">หนังสือเตือน — ${esc(g.name)} · ${esc(ML)}</div>
      <button id="__print_close" class="pm-btn pm-btn-ghost">ปิด (Esc)</button>
      <button id="__print_btn" class="pm-btn pm-btn-primary">🖨 พิมพ์ / บันทึก PDF</button>
    </div>
    <div class="print-modal-paper">${html}</div>`;
  document.body.appendChild(modal);
  document.body.classList.add("printing-modal");
  const cleanup = () => { modal.remove(); document.body.classList.remove("printing-modal"); document.removeEventListener("keydown", onKey); };
  const onKey = (e) => { if (e.key === "Escape") cleanup(); };
  document.addEventListener("keydown", onKey);
  modal.addEventListener("click", e => { if (e.target === modal) cleanup(); });
  modal.querySelector("#__print_btn").addEventListener("click", () => window.print());
  modal.querySelector("#__print_close").addEventListener("click", cleanup);
}

// =============== แท็บ การมาสาย/ขาดงาน (รายงาน ไม่หักเงิน) ===============
function PayrollAttendanceTab({ timeRecs, month }) {
  const D = window.SSSData;
  const { Btn, Badge, Card } = window.UI;
  const recs = timeRecs.filter(t => ptIsoOf(t).startsWith(month));
  const groups = useMemoPT(() => {
    const m = {};
    recs.forEach(t => { (m[t.emp] = m[t.emp] || []).push(t); });
    return Object.keys(m).map(id => {
      const empD = D.Employees.find(e => e.id === id);
      const rows = m[id];
      return { empId: id, name: empD?.name || rows[0].name, role: empD?.role || "", rows, sum: ptSummarize(rows) };
    }).sort((a, b) => (b.sum.lateMin + b.sum.absent * 1000) - (a.sum.lateMin + a.sum.absent * 1000));
  }, [timeRecs, month]);

  return (
    <Card title={`สรุปการมาทำงาน — ${ptMonthLabel(month)}`} sub="รายงานเพื่อติดตาม ไม่ใช่การหักเงิน · ออกใบเตือนสำหรับคนที่สาย/ขาดบ่อย" flush>
      <div className="table-wrap">
        <table className="t">
          <thead><tr>
            <th>พนักงาน</th>
            <th className="right">มาทำงาน (วัน)</th>
            <th className="right">ชม.รวม</th>
            <th className="right">OT (ชม.)</th>
            <th className="right">ลา (วัน)</th>
            <th className="right">ขาด (วัน)</th>
            <th className="right">สาย (ครั้ง)</th>
            <th className="right">สายรวม (นาที)</th>
            <th>ระดับ</th>
            <th></th>
          </tr></thead>
          <tbody>
            {groups.map(g => {
              const warn = g.sum.absent >= 2 || g.sum.lateCount >= 4 || g.sum.lateMin >= 60;
              const mild = !warn && (g.sum.absent >= 1 || g.sum.lateCount >= 2);
              return (
                <tr key={g.empId}>
                  <td>
                    <div style={{display: "flex", alignItems: "center", gap: 8}}>
                      {window.RankAvatar ? <window.RankAvatar name={g.name} size={26}/> : null}
                      <div><div style={{fontWeight: 600}}>{g.name}</div><div style={{fontSize: 10.5, color: "var(--ink-3)"}}>{g.role}</div></div>
                    </div>
                  </td>
                  <td className="right amount">{g.sum.days}</td>
                  <td className="right amount">{g.sum.hours.toFixed(1)}</td>
                  <td className="right amount">{g.sum.ot > 0 ? g.sum.ot.toFixed(1) : "—"}</td>
                  <td className="right amount">{g.sum.leave || "—"}</td>
                  <td className="right amount" style={{color: g.sum.absent > 0 ? "var(--danger)" : "inherit"}}>{g.sum.absent || "—"}</td>
                  <td className="right amount" style={{color: g.sum.lateCount > 0 ? "var(--warning)" : "inherit"}}>{g.sum.lateCount || "—"}</td>
                  <td className="right amount" style={{color: g.sum.lateMin > 0 ? "var(--warning)" : "inherit"}}>{g.sum.lateMin || "—"}</td>
                  <td>{warn ? <Badge tone="danger">ควรออกใบเตือน</Badge> : mild ? <Badge tone="warning">เฝ้าระวัง</Badge> : <Badge tone="success">ปกติ</Badge>}</td>
                  <td><Btn size="sm" kind={warn ? "primary" : "ghost"} icon={I.print} onClick={() => ptPrintWarning(g, month)}>ใบเตือน</Btn></td>
                </tr>
              );
            })}
            {groups.length === 0 && <tr><td colSpan={10} style={{padding: 22, textAlign: "center", color: "var(--ink-3)"}}>ยังไม่มีข้อมูลลงเวลาในเดือนนี้ — ไปที่แท็บ "ลงเวลา / OT" เพื่อบันทึก</td></tr>}
          </tbody>
        </table>
      </div>
    </Card>
  );
}

window.PayrollTimeTab = PayrollTimeTab;
window.PayrollAttendanceTab = PayrollAttendanceTab;
window.ptMonthLabel = ptMonthLabel;
