/* global React, window */
// ลงเวลา / Time Attendance — hrzoft-style daily detail.
// One row per employee for the selected date, showing the person's PROFILE PHOTO
// and the DEVICE FACE-SCAN SNAPSHOT captured at every punch (the core feature).
// Data: GET /api/attendance/day-detail?date=YYYY-MM-DD  → window.AttendancePage.
const { useState: useAttState, useEffect: useAttEffect } = React;

const ATT_DOW = ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'];

function attToday() {
  return window.TODAY || new Date().toISOString().slice(0, 10);
}
// Thai Buddhist-era date, e.g. "ศ. 14/08/2569".
function attThaiDate(dateStr) {
  const d = new Date(dateStr + 'T00:00:00');
  if (isNaN(d)) return dateStr;
  const p = (n) => String(n).padStart(2, '0');
  return `${ATT_DOW[d.getDay()]} ${p(d.getDate())}/${p(d.getMonth() + 1)}/${d.getFullYear() + 543}`;
}
// minutes → "X ชม. Y น." (or "-" when empty).
function attHM(min) {
  if (!min || min <= 0) return '-';
  const h = Math.floor(min / 60), m = min % 60;
  if (h && m) return `${h} ชม. ${m} น.`;
  if (h) return `${h} ชม.`;
  return `${m} น.`;
}
function attScoreFmt(v) {
  return (v < 0 ? '-' : '') + Math.abs(v).toFixed(2);
}
function attName(r) {
  return `${r.first_name || ''} ${r.last_name || ''}`.trim() || r.code || r.employee_id || '—';
}
function attInitials(r) {
  const a = (r.first_name || '')[0] || '';
  const b = (r.last_name || '')[0] || '';
  return (a + b) || attName(r).slice(0, 2) || '—';
}

// Status → chip. `notArrivedYet` = date is today/future (absent may still show up).
function attStatusChip(r, notArrivedYet) {
  const s = r.status || 'absent';
  const late = r.late_min || 0;
  if (s === 'holiday' || s === 'off') return { label: 'วันหยุด', cls: 'c-gray' };
  if (s === 'leave') return { label: 'ลาหยุด', cls: 'c-blue' };
  if (s === 'absent') {
    return notArrivedYet ? { label: 'ยังไม่มาทำงาน', cls: 'c-gray' } : { label: 'ขาดงาน', cls: 'c-coral' };
  }
  if (late > 0) return { label: `สาย ${late} นาที`, cls: 'c-amber' };
  if (s === 'in_only') return { label: 'ลืมออกงาน', cls: 'c-amber' };
  return { label: 'ตรงเวลา', cls: 'c-green' };
}
// Punch role label by chronological position (matches server `kind`).
function attPunchLabel(i, n) {
  if (i === 0) return 'เข้างาน';
  if (n >= 2 && i === n - 1) return 'ออกงาน';
  return i === 1 ? 'พักเบรก' : 'ออกเบรก';
}

const AttCameraIcon = ({ size = 16 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" strokeWidth="1.8">
    <path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" />
    <circle cx="12" cy="13" r="4" />
  </svg>
);

function AttAvatar({ r, size = 46 }) {
  const [err, setErr] = useAttState(false);
  const eid = r.employee_id;
  const open = () => eid && window.openProfile && window.openProfile(eid);
  const base = { width: size, height: size, borderRadius: '50%', flex: 'none', cursor: eid ? 'pointer' : 'default',
    objectFit: 'cover', border: '1px solid var(--line)' };
  const src = (r.photo_url && !err) ? r.photo_url : '/img/avatar-person.svg';
  return <img src={src} alt="" onError={() => setErr(true)} onClick={open} title={eid ? 'ดูโปรไฟล์' : ''} style={base} />;
}

// Colorful stat icon (hrzoft style).
const ATT_ICONS = {
  people: <><path d="M17 21v-2a4 4 0 0 0-3-3.87M9 21v-2a4 4 0 0 1 3-3.87" /><circle cx="9" cy="7" r="3" /><path d="M16 3.13a4 4 0 0 1 0 7.75" /></>,
  usercheck: <><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" /><circle cx="9" cy="7" r="4" /><path d="m16.5 11.5 2 2 3.5-3.5" /></>,
  check: <><circle cx="12" cy="12" r="9" /><path d="M8.5 12l2.5 2.5 4.5-5" /></>,
  clock: <><circle cx="12" cy="12" r="9" /><path d="M12 7.5v5l3 2" /></>,
  clockdot: <><circle cx="12" cy="12" r="9" strokeDasharray="2.6 2.6" /><path d="M12 7.5v5l3 2" /></>,
  cal: <><rect x="3" y="4" width="18" height="17" rx="2.5" /><path d="M3 9h18M8 2v4M16 2v4" /></>,
  calx: <><rect x="3" y="4" width="18" height="17" rx="2.5" /><path d="M3 9h18M8 2v4M16 2v4M9.5 13.5l5 4M14.5 13.5l-5 4" /></>,
  sun: <><circle cx="12" cy="12" r="4" /><path d="M12 2v2M12 20v2M4 12H2M22 12h-2M5 5l1.4 1.4M17.6 17.6 19 19M5 19l1.4-1.4M17.6 6.4 19 5" /></>,
};
const AttIcon = ({ k, color, size = 26 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke={color} strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round">{ATT_ICONS[k]}</svg>
);

// Stat = colored icon + label + colored count pill (hrzoft).
function AttStat({ label, n, ic, col, active, onClick }) {
  return (
    <div onClick={onClick} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 7, minWidth: 78,
      padding: '10px 8px', borderRadius: 16, cursor: onClick ? 'pointer' : 'default',
      background: active ? col : 'transparent', transition: 'background .12s' }}>
      <AttIcon k={ic} color={active ? '#fff' : col} />
      <div style={{ fontSize: 12, color: active ? '#fff' : 'var(--ink-4)', fontWeight: 500, whiteSpace: 'nowrap' }}>{label}</div>
      <div className="tnum" style={{ background: active ? 'rgba(255,255,255,.25)' : col, color: '#fff',
        fontSize: 12, fontWeight: 700, padding: '3px 13px', borderRadius: 999, whiteSpace: 'nowrap' }}>{n} คน</div>
    </div>
  );
}

// A single face-scan snapshot thumbnail (or camera placeholder). Click → lightbox.
function AttThumb({ url, label, onOpen }) {
  const box = { width: 40, height: 40, borderRadius: 10, border: '1px solid var(--line)', flex: 'none' };
  if (url) {
    return <img src={url} alt={label} title={label} onClick={() => onOpen(url, label)}
      style={{ ...box, objectFit: 'cover', cursor: 'zoom-in' }} />;
  }
  return (
    <div title={`${label} · ไม่มีรูป`} style={{ ...box, display: 'grid', placeItems: 'center',
      background: 'var(--surface-2)', color: 'var(--ink-5)' }}>
      <AttCameraIcon />
    </div>
  );
}

function AttendancePage({ role }) {
  const [date, setDate] = useAttState(attToday());
  const [deptFilter, setDeptFilter] = useAttState('all');
  const [rows, setRows] = useAttState([]);
  const [loading, setLoading] = useAttState(true);
  const [lightbox, setLightbox] = useAttState(null);   // { url, label }
  const [statFilter, setStatFilter] = useAttState('all');

  const load = async (d, dept) => {
    setLoading(true);
    try {
      const q = new URLSearchParams({ date: d });
      if (dept && dept !== 'all') q.set('department_id', dept);
      const r = await fetch('/api/attendance/day-detail?' + q.toString(), { credentials: 'include' });
      if (r.ok) { const data = await r.json(); setRows(data.rows || []); }
      else setRows([]);
    } catch (_) { setRows([]); } finally { setLoading(false); }
  };
  useAttEffect(() => { load(date, deptFilter); }, [date, deptFilter]);

  // Live refresh when a scan for the shown date arrives.
  useAttEffect(() => {
    if (!window.scanStream) return undefined;
    return window.scanStream.subscribe((scan) => {
      if (scan && scan.daily && scan.daily.date === date) load(date, deptFilter);
    });
  }, [date, deptFilter]);

  // Esc closes the lightbox.
  useAttEffect(() => {
    if (!lightbox) return undefined;
    const onKey = (e) => { if (e.key === 'Escape') setLightbox(null); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [lightbox]);

  const notArrivedYet = date >= attToday();

  // ── Stat-row counts ─────────────────────────────────────────────────────────
  let total = rows.length, notYet = 0, absent = 0, came = 0, onTime = 0, late = 0,
    leave = 0, forgotOut = 0, holiday = 0, early = 0;
  for (const r of rows) {
    const s = r.status || 'absent';
    if (s === 'present' || s === 'in_only') {
      came++;
      if ((r.late_min || 0) > 0) late++; else onTime++;
      if (s === 'in_only') forgotOut++;
      if ((r.early_min || 0) > 0) early++;
    } else if (s === 'leave') { leave++; }
    else if (s === 'holiday' || s === 'off') { holiday++; }
    else { if (notArrivedYet) notYet++; else absent++; }
  }
  const stats = [
    { k: 'all', label: 'ทั้งหมด', n: total, ic: 'people', col: '#0EA5E9' },
    { k: 'onTime', label: 'ตรงเวลา', n: onTime, ic: 'check', col: '#16A34A' },
    { k: 'late', label: 'มาสาย', n: late, ic: 'clock', col: '#F59E0B' },
    { k: 'leave', label: 'ลาหยุด', n: leave, ic: 'cal', col: '#F97316' },
    { k: 'forgotOut', label: 'ลืมออกงาน', n: forgotOut, ic: 'clockdot', col: '#8B5CF6' },
    { k: 'holiday', label: 'วันหยุด', n: holiday, ic: 'sun', col: '#94A3B8' },
    { k: 'early', label: 'กลับก่อน', n: early, ic: 'usercheck', col: '#0EA5E9' },
  ];
  const topBadges = [
    { k: 'notYet', label: 'ยังไม่มาทำงาน', n: notYet, ic: 'clock', col: '#94A3B8' },
    { k: 'absent', label: 'ขาดงาน', n: absent, ic: 'calx', col: '#EF4444' },
  ];
  const matchFilter = (r) => {
    const s = r.status || 'absent'; const isWork = s === 'present' || s === 'in_only';
    switch (statFilter) {
      case 'onTime': return isWork && !((r.late_min || 0) > 0);
      case 'late': return (r.late_min || 0) > 0;
      case 'leave': return s === 'leave';
      case 'forgotOut': return s === 'in_only';
      case 'holiday': return s === 'holiday' || s === 'off';
      case 'early': return (r.early_min || 0) > 0;
      case 'notYet': return !isWork && s === 'absent' && notArrivedYet;
      case 'absent': return !isWork && s === 'absent' && !notArrivedYet;
      default: return true;
    }
  };
  const visibleRows = rows.filter(matchFilter);
  const toggleStat = (k) => setStatFilter((cur) => (cur === k || k === 'all') ? 'all' : k);

  const depts = window.DEPARTMENTS || [];
  const qrPlaceholder = () => {
    if (window.appToast) window.appToast('สร้าง QR Code — ยังไม่เปิดใช้งาน', { tone: 'info' });
  };

  return (
    <div data-screen-label="Time Attendance">
      {/* ── Header ── */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 12, flexWrap: 'wrap', marginBottom: 16 }}>
        <div>
          <h1 style={{ fontFamily: 'var(--font-display)', fontSize: 22, fontWeight: 700, color: 'var(--ink)', margin: 0 }}>
            ลงเวลา / Time Attendance
          </h1>
          <div style={{ fontSize: 12.5, color: 'var(--ink-4)', marginTop: 4 }}>
            รูปโปรไฟล์ + ภาพสแกนใบหน้าจากเครื่อง ยืนยันการเข้า-ออกงานทุกครั้ง
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
          <input className="gv-input" type="date" value={date} onChange={(e) => setDate(e.target.value)}
            style={{ width: 168 }} />
          {depts.length > 0 && (
            <select className="gv-select" value={deptFilter} onChange={(e) => setDeptFilter(e.target.value)} style={{ width: 168 }}>
              <option value="all">ทุก{window.T.dept}</option>
              {depts.map((d) => <option key={d.id} value={String(d.id)}>{d.name}</option>)}
            </select>
          )}
          <button className="gv-btn ok" onClick={qrPlaceholder}>สร้าง QR Code</button>
        </div>
      </div>

      {/* ── Stat card (icons + colored count pills) ── */}
      <div className="gv-card" style={{ marginBottom: 18, padding: '14px 18px' }}>
        <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10, flexWrap: 'wrap', marginBottom: 8 }}>
          {topBadges.map((b) => (
            <span key={b.k} onClick={() => toggleStat(b.k)} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12.5, cursor: 'pointer',
              color: statFilter === b.k ? '#fff' : 'var(--ink-4)', background: statFilter === b.k ? b.col : 'transparent', padding: '4px 10px', borderRadius: 999 }}>
              <AttIcon k={b.ic} color={statFilter === b.k ? '#fff' : b.col} size={16} />{b.label} <b style={{ color: statFilter === b.k ? '#fff' : b.col }}>{b.n} คน</b>
            </span>
          ))}
        </div>
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 4, overflowX: 'auto' }}>
          {stats.map((s) => <AttStat key={s.k} {...s} active={statFilter === s.k} onClick={() => toggleStat(s.k)} />)}
        </div>
      </div>

      {/* ── Main table ── */}
      <div className="gv-card">
        <div style={{ overflowX: 'auto' }}>
          <table className="gv-tbl">
            <thead>
              <tr>
                <th>รหัส</th>
                <th>ชื่อ-นามสกุล</th>
                <th>สถานะ</th>
                <th>คะแนน</th>
                <th>สถานที่</th>
                <th>เวลาเข้า-ออกงาน</th>
                <th>รูปภาพยืนยันตัวตน</th>
                <th>ชั่วโมงการทำงาน</th>
                <th>โอที</th>
                <th>วันที่</th>
              </tr>
            </thead>
            <tbody>
              {loading ? (
                <tr><td colSpan={10}><div className="gv-empty">กำลังโหลด…</div></td></tr>
              ) : visibleRows.length === 0 ? (
                <tr><td colSpan={10}><div className="gv-empty">{rows.length ? '— ไม่มีพนักงานในกลุ่มที่เลือก —' : '— ไม่มีข้อมูลพนักงานสำหรับวันที่นี้ —'}</div></td></tr>
              ) : visibleRows.map((r) => {
                const chip = attStatusChip(r, notArrivedYet);
                const times = r.punches.map((p) => p.time);
                const inT = times[0] || null;
                const outT = times.length >= 2 ? times[times.length - 1] : null;
                const mids = times.slice(1, -1);
                const slots = [
                  { lb: 'เข้างาน', t: inT },
                  { lb: 'พักเบรก', t: mids[0] || null },
                  { lb: 'ออกเบรก', t: mids[1] || null },
                  { lb: 'ออกงาน', t: outT },
                ];
                const scoreColor = r.score > 0 ? 'var(--mint-ink)' : r.score < 0 ? 'var(--coral-ink)' : 'var(--ink-4)';
                return (
                  <tr key={r.employee_id}>
                    <td className="tnum" style={{ color: 'var(--ink-4)', whiteSpace: 'nowrap' }}>{r.code}</td>
                    <td>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                        <AttAvatar r={r} />
                        <div style={{ minWidth: 0 }}>
                          <div style={{ fontWeight: 600, fontSize: 13.5, whiteSpace: 'nowrap' }}>
                            {r.title ? r.title + ' ' : ''}{attName(r)}
                          </div>
                          <div style={{ fontSize: 11.5, color: 'var(--ink-4)' }}>{r.department_name || '—'}</div>
                        </div>
                      </div>
                    </td>
                    <td>
                      <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap', alignItems: 'center' }}>
                        <span className={`gv-chip ${chip.cls}`}>{chip.label}</span>
                        {r.ot_min > 0 && <span className="gv-chip c-blue">OT</span>}
                        {r.early_min > 0 && (r.status === 'present' || r.status === 'in_only') &&
                          <span className="gv-chip c-amber">กลับก่อน</span>}
                      </div>
                    </td>
                    <td className="tnum" style={{ fontWeight: 700, color: scoreColor }}>{attScoreFmt(r.score)}</td>
                    <td style={{ color: 'var(--ink-3)', whiteSpace: 'nowrap' }}>{r.location || '-'}</td>
                    <td>
                      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '2px 14px', minWidth: 190 }}>
                        {slots.map((s) => (
                          <div key={s.lb} style={{ display: 'flex', justifyContent: 'space-between', gap: 8, fontSize: 12 }}>
                            <span style={{ color: 'var(--ink-5)' }}>{s.lb}</span>
                            <span className="tnum" style={{ fontWeight: 600, color: s.t ? 'var(--ink)' : 'var(--ink-5)' }}>{s.t || '-'}</span>
                          </div>
                        ))}
                      </div>
                    </td>
                    <td>
                      {r.punches.length === 0 ? (
                        <span style={{ fontSize: 12, color: 'var(--ink-5)' }}>—</span>
                      ) : (
                        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                          {r.punches.map((p, i) => (
                            <AttThumb key={i} url={p.snapshot_url}
                              label={`${attPunchLabel(i, r.punches.length)} ${p.time}`}
                              onOpen={(url, label) => setLightbox({ url, label })} />
                          ))}
                        </div>
                      )}
                    </td>
                    <td className="tnum" style={{ whiteSpace: 'nowrap', color: r.work_min ? 'var(--ink)' : 'var(--ink-5)' }}>{attHM(r.work_min)}</td>
                    <td className="tnum" style={{ whiteSpace: 'nowrap', color: r.ot_min ? 'var(--mint-ink)' : 'var(--ink-5)' }}>{attHM(r.ot_min)}</td>
                    <td style={{ whiteSpace: 'nowrap', color: 'var(--ink-4)', fontSize: 12.5 }}>{attThaiDate(date)}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      {/* ── Lightbox ── */}
      {lightbox && (
        <div onClick={() => setLightbox(null)}
          style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.72)', display: 'grid', placeItems: 'center', zIndex: 9999, padding: 20 }}>
          <div onClick={(e) => e.stopPropagation()}
            style={{ background: 'var(--surface)', borderRadius: 'var(--r-lg)', padding: 12, boxShadow: 'var(--shadow-lg)', maxWidth: '92vw', maxHeight: '92vh' }}>
            <img src={lightbox.url} alt="" style={{ display: 'block', maxWidth: '86vw', maxHeight: '76vh', borderRadius: 'var(--r-md)' }} />
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, marginTop: 10 }}>
              <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink-3)' }}>{lightbox.label}</div>
              <button className="gv-btn no sm" onClick={() => setLightbox(null)}>ปิด</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

window.AttendancePage = AttendancePage;
