/* global React, window */
const { useState: usePayState, useEffect: usePayEffect } = React;

const baht = (n) => (n || 0).toLocaleString('th-TH', { minimumFractionDigits: 2, maximumFractionDigits: 2 });

// Circular face avatar (clickable → profile). Stops row-click so it opens the
// profile instead of the payslip.
function PayAvatar({ id, size = 36 }) {
  const [err, setErr] = usePayState(false);
  const src = (err || !id) ? '/img/avatar-person.svg' : `/faces/${id}.jpg`;
  return <img src={src} alt="" onError={() => setErr(true)}
    onClick={(e) => { e.stopPropagation(); id && window.openProfile && window.openProfile(id); }} title={id ? 'ดูโปรไฟล์' : ''}
    style={{ width: size, height: size, borderRadius: '50%', objectFit: 'cover', flex: 'none',
      cursor: id ? 'pointer' : 'default', border: '1px solid var(--line)' }} />;
}

// เงินเดือน — configurable payroll. Computes from attendance + each employee's
// pay profile. HR tunes all rates in ตั้งค่า. Preview is live; กดปิดงวด to lock.
function PayrollPage({ role }) {
  const [month, setMonth] = usePayState((window.TODAY || new Date().toISOString().slice(0, 10)).slice(0, 7));
  const [deptFilter, setDeptFilter] = usePayState('all');
  const [data, setData] = usePayState(null);
  const [loading, setLoading] = usePayState(true);
  const [detail, setDetail] = usePayState(null);
  const [showSettings, setShowSettings] = usePayState(false);
  const canEdit = role === 'admin' || role === 'hr';

  const load = async () => {
    setLoading(true);
    const q = new URLSearchParams({ month });
    if (deptFilter !== 'all') q.set('department_id', deptFilter);
    const r = await fetch('/api/payroll/run?' + q.toString(), { credentials: 'include' });
    if (r.ok) setData(await r.json());
    setLoading(false);
  };
  usePayEffect(() => { load(); }, [month, deptFilter]);

  const finalize = async () => {
    const ok = await window.appConfirm({ title: `ปิดงวดเงินเดือน ${month}?`, message: 'บันทึก payslip ทุกคนและล็อกงวดนี้', confirmText: 'ปิดงวด' });
    if (!ok) return;
    const r = await fetch('/api/payroll/finalize?month=' + month, { method: 'POST', credentials: 'include' });
    const d = await r.json().catch(() => ({}));
    window.appToast(`ปิดงวดแล้ว — ${d.finalized} payslip`, { tone: 'success' });
    load();
  };

  const exportCsv = () => {
    if (!data?.slips) return;
    const header = ['รหัส', 'ชื่อ-สกุล', 'แผนก', 'ฐาน', 'OT', 'เบี้ยเลี้ยง', 'รวมรับ', 'สาย', 'ขาด', 'ปกส.', 'ภาษี', 'อื่นๆหัก', 'รวมหัก', 'สุทธิ'];
    const lines = data.slips.map((p) => [
      p.employee_id, p.employee_name, p.department_name || '',
      p.base_pay, p.ot_pay, p.allowance, p.gross,
      p.late_deduct, p.absent_deduct, p.sso, p.tax, p.other_deduct, p.total_deduct, p.net,
    ]);
    const csv = '﻿' + [header, ...lines].map((row) => row.map((c) => `"${String(c).replace(/"/g, '""')}"`).join(',')).join('\n');
    const a = document.createElement('a');
    a.href = URL.createObjectURL(new Blob([csv], { type: 'text/csv;charset=utf-8' }));
    a.download = `payroll_${month}.csv`; a.click();
  };

  const monthLabel = new Date(month + '-01T00:00:00').toLocaleDateString('th-TH', { month: 'long', year: 'numeric' });

  return (
    <div data-screen-label="Payroll">
      <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, margin: 0 }}>เงินเดือน / Payroll</h1>
          <div style={{ fontSize: 12.5, color: 'var(--ink-4)', marginTop: 4, display: 'flex', alignItems: 'center', gap: 8 }}>
            คำนวณจากการลงเวลา · {monthLabel} {data?.status === 'finalized' && <span className="gv-chip c-green">ปิดงวดแล้ว</span>}
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
          <input className="gv-input" type="month" value={month} onChange={(e) => setMonth(e.target.value)} style={{ width: 150 }}/>
          <select className="gv-select" value={deptFilter} onChange={(e) => setDeptFilter(e.target.value)} style={{ width: 160 }}>
            <option value="all">ทุกแผนก</option>
            {(window.DEPARTMENTS || []).map((d) => <option key={d.id} value={String(d.id)}>{d.name}</option>)}
          </select>
          {canEdit && <button className="gv-btn no sm" onClick={() => setShowSettings(true)}>⚙ ตั้งค่า</button>}
          <button className="gv-btn no sm" onClick={exportCsv}>⬇ CSV</button>
          {canEdit && <button className="gv-btn ok sm" onClick={finalize}>✓ ปิดงวด</button>}
        </div>
      </div>

      {/* Totals */}
      {data?.totals && (
        <div style={{ marginBottom: 16, display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(170px,1fr))', gap: 12 }}>
          <Kpi label="พนักงาน" value={data.totals.count} unit="คน"/>
          <Kpi label="รวมรายรับ" value={baht(data.totals.gross)} color="var(--mint-ink)"/>
          <Kpi label="รวมรายหัก" value={baht(data.totals.deduct)} color="var(--coral-ink)"/>
          <Kpi label="จ่ายสุทธิ" value={baht(data.totals.net)} color="var(--ink)"/>
        </div>
      )}

      <div className="gv-card">
        <div style={{ overflowX: 'auto' }}>
          <table className="gv-tbl" style={{ minWidth: 760 }}>
            <thead>
              <tr><th>พนักงาน</th><th>ประเภท</th><th style={{ textAlign: 'right' }}>ฐาน</th><th style={{ textAlign: 'right' }}>OT</th><th style={{ textAlign: 'right' }}>เบี้ยเลี้ยง</th><th style={{ textAlign: 'right' }}>รวมหัก</th><th style={{ textAlign: 'right' }}>สุทธิ</th></tr>
            </thead>
            <tbody>
              {loading ? (
                <tr><td colSpan={7}><div className="gv-empty">กำลังคำนวณ…</div></td></tr>
              ) : !data?.slips?.length ? (
                <tr><td colSpan={7}><div className="gv-empty">— ไม่มีพนักงาน —</div></td></tr>
              ) : data.slips.map((p) => (
                <tr key={p.employee_id} style={{ cursor: 'pointer' }} onClick={() => setDetail(p)}>
                  <td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <PayAvatar id={p.employee_id} />
                      <div style={{ minWidth: 0 }}>
                        <div style={{ fontWeight: 600, fontSize: 13.5, whiteSpace: 'nowrap' }}>{p.employee_name || p.employee_id}</div>
                        <div style={{ fontSize: 11.5, color: 'var(--ink-4)' }}>{p.employee_id}{p.department_name ? ` · ${p.department_name}` : ''}</div>
                      </div>
                    </div>
                  </td>
                  <td><span className="gv-chip c-gray">{({ monthly: 'รายเดือน', daily: 'รายวัน', hourly: 'รายชั่วโมง' })[p.pay_type] || p.pay_type}</span></td>
                  <td className="tnum" style={{ textAlign: 'right' }}>{baht(p.base_pay)}</td>
                  <td className="tnum" style={{ textAlign: 'right', color: p.ot_pay ? 'var(--mint-ink)' : 'var(--ink-5)' }}>{p.ot_pay ? baht(p.ot_pay) : '–'}</td>
                  <td className="tnum" style={{ textAlign: 'right' }}>{p.allowance ? baht(p.allowance) : '–'}</td>
                  <td className="tnum" style={{ textAlign: 'right', color: p.total_deduct ? 'var(--coral-ink)' : 'var(--ink-5)' }}>{p.total_deduct ? baht(p.total_deduct) : '–'}</td>
                  <td className="tnum" style={{ textAlign: 'right', fontWeight: 700 }}>{baht(p.net)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      {detail && <PayslipModal slip={detail} month={month} canEdit={canEdit} onClose={() => setDetail(null)} onChanged={load}/>}
      {showSettings && <PayrollSettingsModal onClose={() => setShowSettings(false)} onSaved={() => { setShowSettings(false); load(); }}/>}
    </div>
  );
}

function Kpi({ label, value, unit, color }) {
  return (
    <div className="gv-card" style={{ padding: '16px 20px', boxShadow: 'var(--shadow-sm)' }}>
      <div style={{ fontSize: 12.5, color: 'var(--ink-4)', fontWeight: 500 }}>{label}</div>
      <div className="tnum" style={{ fontFamily: 'var(--font-display)', fontSize: 24, fontWeight: 700, color: color || 'var(--ink)', marginTop: 4, lineHeight: 1 }}>
        {value}{unit ? <small style={{ fontSize: 13, color: 'var(--ink-4)', fontWeight: 500, marginLeft: 4 }}>{unit}</small> : ''}
      </div>
    </div>
  );
}

// Payslip detail — full line breakdown + attendance + per-employee items editor.
function PayslipModal({ slip, month, canEdit, onClose, onChanged }) {
  const [items, setItems] = usePayState([]);
  const [adding, setAdding] = usePayState(false);
  const [nm, setNm] = usePayState(''); const [kind, setKind] = usePayState('earning'); const [amt, setAmt] = usePayState('');
  const a = slip.attendance || {};

  const loadItems = async () => {
    const r = await fetch(`/api/payroll/employee/${encodeURIComponent(slip.employee_id)}/items`, { credentials: 'include' });
    if (r.ok) setItems(await r.json());
  };
  usePayEffect(() => { loadItems(); }, []);

  const addItem = async () => {
    if (!nm.trim() || !amt) return;
    await fetch(`/api/payroll/employee/${encodeURIComponent(slip.employee_id)}/items`, {
      method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name: nm.trim(), kind, amount: Number(amt) }),
    });
    setNm(''); setAmt(''); setAdding(false);
    await loadItems(); onChanged && onChanged();
    window.appToast('เพิ่มรายการแล้ว', { tone: 'success' });
  };
  const delItem = async (id) => {
    await fetch(`/api/payroll/items/${id}`, { method: 'DELETE', credentials: 'include' });
    await loadItems(); onChanged && onChanged();
  };

  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 200, background: 'rgba(15,23,42,.45)', display: 'grid', placeItems: 'center', padding: 20 }}>
      <div className="gv-card" onClick={(e) => e.stopPropagation()} style={{ width: 'min(560px,100%)', maxHeight: '90vh', overflow: 'auto' }}>
        <div className="gv-card-h">
          <b style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <PayAvatar id={slip.employee_id} size={30} />
            สลิปเงินเดือน — {slip.employee_name}
          </b>
          <button className="gv-btn no sm" onClick={onClose}>ปิด</button>
        </div>
        <div className="gv-card-b">
          <div style={{ fontSize: 12.5, color: 'var(--ink-4)', marginBottom: 14 }}>
            งวด {month} · มา {a.present_days} วัน · ขาด {a.absent_days} · ลา {a.leave_days} · OT {a.ot_hours} ชม. · สาย {a.late_min} นาที
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 5, marginBottom: 14 }}>
            {(slip.lines || []).map((l, i) => (
              <div key={i} style={{ display: 'flex', justifyContent: 'space-between', padding: '8px 12px', background: 'var(--surface-2)', borderRadius: 'var(--r-md)' }}>
                <span style={{ fontSize: 13, color: l.kind === 'deduction' ? 'var(--coral-ink)' : 'var(--ink)' }}>
                  {l.kind === 'deduction' ? '−' : '+'} {l.label}
                </span>
                <span className="tnum" style={{ fontSize: 13, fontWeight: 600, color: l.kind === 'deduction' ? 'var(--coral-ink)' : 'var(--mint-ink)' }}>{baht(l.amount)}</span>
              </div>
            ))}
          </div>

          <div style={{ borderTop: '1px solid var(--line)', paddingTop: 12 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13.5 }}><span>รวมรายรับ</span><span className="tnum" style={{ fontWeight: 600 }}>{baht(slip.gross)}</span></div>
            <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13.5, marginTop: 4 }}><span>รวมรายหัก</span><span className="tnum" style={{ fontWeight: 600, color: 'var(--coral-ink)' }}>{baht(slip.total_deduct)}</span></div>
            <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 8, paddingTop: 8, borderTop: '1px solid var(--line)' }}>
              <span style={{ fontWeight: 700, fontSize: 15 }}>เงินสุทธิ</span>
              <span className="tnum" style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 20 }}>{baht(slip.net)}</span>
            </div>
          </div>

          {canEdit && (
            <div style={{ marginTop: 16, borderTop: '1px solid var(--line)', paddingTop: 14 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
                <div style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--ink-3)' }}>รายการเฉพาะคนนี้ (เบี้ยเลี้ยง/เงินกู้)</div>
                <button className="gv-btn no sm" onClick={() => setAdding(!adding)}>＋ เพิ่ม</button>
              </div>
              {items.map((it) => (
                <div key={it.id} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '7px 12px', background: 'var(--surface-2)', borderRadius: 'var(--r-md)', marginBottom: 5 }}>
                  <span className={`gv-chip ${it.kind === 'deduction' ? 'c-coral' : 'c-green'}`}>{it.kind === 'deduction' ? 'หัก' : 'เพิ่ม'}</span>
                  <span style={{ flex: 1, fontSize: 12.5 }}>{it.name}</span>
                  <span className="tnum" style={{ fontSize: 12.5 }}>{baht(it.amount)}</span>
                  <button className="gv-btn ghost sm" style={{ color: 'var(--coral-ink)', padding: '4px 10px' }} onClick={() => delItem(it.id)}>ลบ</button>
                </div>
              ))}
              {adding && (
                <div style={{ display: 'flex', gap: 6, marginTop: 8, alignItems: 'flex-end' }}>
                  <input className="gv-input" placeholder="ชื่อรายการ" value={nm} onChange={(e) => setNm(e.target.value)} style={{ flex: 1 }}/>
                  <select className="gv-select" value={kind} onChange={(e) => setKind(e.target.value)} style={{ width: 90 }}>
                    <option value="earning">เพิ่ม</option><option value="deduction">หัก</option>
                  </select>
                  <input className="gv-input" type="number" placeholder="บาท" value={amt} onChange={(e) => setAmt(e.target.value)} style={{ width: 90 }}/>
                  <button className="gv-btn ok sm" onClick={addItem}>OK</button>
                </div>
              )}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function PayrollSettingsModal({ onClose, onSaved }) {
  const [s, setS] = usePayState(null);
  usePayEffect(() => { fetch('/api/payroll/settings', { credentials: 'include' }).then(r => r.json()).then(setS); }, []);
  const set = (k, v) => setS((p) => ({ ...p, [k]: v }));
  const save = async () => {
    await fetch('/api/payroll/settings', { method: 'PUT', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(s) });
    window.appToast('บันทึกการตั้งค่าแล้ว', { tone: 'success' }); onSaved();
  };
  if (!s) return null;
  const Field = ({ k, label, hint, step }) => (
    <div className="gv-field" style={{ marginBottom: 0 }}>
      <label>{label}</label>
      <input className="gv-input" type="number" step={step || 'any'} value={s[k] ?? ''} onChange={(e) => set(k, e.target.value)}/>
      {hint && <div style={{ fontSize: 11, color: 'var(--ink-4)', marginTop: 3 }}>{hint}</div>}
    </div>
  );
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 200, background: 'rgba(15,23,42,.45)', display: 'grid', placeItems: 'center', padding: 20 }}>
      <div className="gv-card" onClick={(e) => e.stopPropagation()} style={{ width: 'min(520px,100%)', maxHeight: '90vh', overflow: 'auto' }}>
        <div className="gv-card-h">
          <b>ตั้งค่าการคำนวณเงินเดือน</b>
          <button className="gv-btn no sm" onClick={onClose}>ปิด</button>
        </div>
        <div className="gv-card-b" style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div style={{ display: 'flex', gap: 12 }}>
            <div style={{ flex: 1 }}><Field k="payroll.ot_multiplier" label="ตัวคูณ OT" hint="เช่น 1.5"/></div>
            <div style={{ flex: 1 }}><Field k="payroll.late_deduct_per_min" label="หักสาย (บาท/นาที)" hint="0 = ไม่หัก"/></div>
          </div>
          <div style={{ display: 'flex', gap: 12 }}>
            <div style={{ flex: 1 }}><Field k="payroll.sso_rate" label="ปกส. (สัดส่วน)" hint="0.05 = 5%"/></div>
            <div style={{ flex: 1 }}><Field k="payroll.sso_cap" label="ปกส. สูงสุด (บาท)" hint="เช่น 750"/></div>
          </div>
          <div style={{ display: 'flex', gap: 12 }}>
            <div style={{ flex: 1 }}><Field k="payroll.days_per_month" label="วันต่อเดือน (หาร)" hint="หาเรตรายวันจากเงินเดือน"/></div>
            <div style={{ flex: 1 }}><Field k="payroll.hours_per_day" label="ชม.ต่อวัน (หาร)" hint="หาเรตรายชั่วโมง"/></div>
          </div>
          <div style={{ display: 'flex', gap: 12 }}>
            <div style={{ flex: 1 }}><Field k="payroll.tax_percent" label="ภาษี ณ ที่จ่าย (%)" hint="0 = กรอกเอง/ไม่หัก"/></div>
            <div className="gv-field" style={{ flex: 1, marginBottom: 0 }}>
              <label>หักขาดงาน (รายเดือน)</label>
              <select className="gv-select" value={s['payroll.absent_deduct']} onChange={(e) => set('payroll.absent_deduct', e.target.value)}>
                <option value="1">หัก (วันละ 1 วันของเงินเดือน)</option>
                <option value="0">ไม่หัก</option>
              </select>
            </div>
          </div>
          <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 8, marginTop: 4 }}>
            <button className="gv-btn no" onClick={onClose}>ยกเลิก</button>
            <button className="gv-btn ok" onClick={save}>บันทึก</button>
          </div>
        </div>
      </div>
    </div>
  );
}

window.PayrollPage = PayrollPage;
