// Daily Report — table cards (INVOICE / NO INVOICE / รายจ่าย)
const { useState: useStateT } = React;

const isPendingPayment = (r) => r.paymentStatus === 'pending_payment';
const isPartialPayment = (r) => r.paymentStatus === 'partial_deposit';
const isPrivateOta = (r) => !!(r.privateOta || r.paymentStatus === 'private_ota');

function StatusBadge({ row, isInvoice }) {
  // For Payment Group rows, use the group-derived display status instead of the
  // individual stored paymentStatus — prevents badge from contradicting amount columns.
  const status = row._displayStatus !== undefined ? row._displayStatus : row.paymentStatus;
  if (status === 'pg_member')
    return <div className="status-stack"><span className="badge empty-payment">—</span></div>;
  return (
    <div className="status-stack">
      {isPrivateOta(row)
        ? <span className="badge empty-payment">—</span>
        : status === 'pending_payment'
        ? <span className="badge due">PENDING PAYMENT</span>
        : status === 'partial_deposit'
          ? <span className="badge partial">PARTIAL / DEPOSIT</span>
          : status === 'no_payment'
              ? <span className="badge empty-payment">—</span>
            : <span className="badge paid">RECEIVED</span>}
      {isPrivateOta(row) && <span className="badge private">PRIVATE OTA</span>}
    </div>
  );
}

// inv number not yet assigned (new row before a real INV no. is issued)
const unnumbered = (r) => !r.id || /x{2,}/i.test(r.id);
// OTA sources that REQUIRE a Booking ID on both Invoice and No Invoice
const OTA_SOURCES = ['Agoda INV', 'Agoda NoINV', 'Ascend', 'Webbeds', 'Booking.com', 'Expedia', 'Ctrip', 'Thai Tour'];
const isOTA = (s) => OTA_SOURCES.includes(s);
// รายการ: ถ้าพิมพ์ชื่อรายการไว้ (หมวดอื่นๆ/ค่าเสียหาย) ให้โชว์ชื่อนั้นแทนชื่อหมวด
const catLabel = (r) => (r.detail && String(r.detail).trim()) ? r.detail : r.cat;
// ci/co อาจว่างหรือมาเป็น Date object จาก Sheets — กัน crash
const d5 = (v) => String(v || '').slice(0, 5);
const SourceCell = ({ r }) => (
  <td>{r.source}{isOTA(r.source) && (
    <span className="booking-id" title="Booking ID">{r.bookingId || 'no booking id'}</span>
  )}</td>
);
// channel cell — for No Invoice, a QR row shows the success time captured at payment
const ChannelCell = ({ r }) => (
  <td>{r.channel}{r.channel === 'QR' && r.qrTime && (
    <span className="qr-time" title="เวลาสำเร็จ QR">{r.qrTime}</span>
  )}</td>
);
// parse HH:MM → minutes; blank/invalid sorts last
const toMin = (t) => { const m = /^(\d{1,2}):(\d{2})/.exec(String(t || '')); return m ? (+m[1]) * 60 + (+m[2]) : 1e9; };
// recv cell — blank (—, centered) when nothing received yet
const RecvCell = ({ v }) => v > 0
  ? <td className="mono-c r">{fmt(v)}</td>
  : <td className="mono-c c muted">—</td>;
const PendingCell = ({ v }) => Number(v || 0) > 0
  ? <td className="mono-c r pending-amount">{fmt(v)}</td>
  : <td className="mono-c c muted">—</td>;
// forced order: status-driven Pending Payment first, then rows with no INV number, then the rest.
// keep original index so edit/delete still target the correct source row.
function sortInvoice(rows) {
  const rank = (r) => (isPendingPayment(r) ? 0 : isPartialPayment(r) ? 1 : unnumbered(r) ? 2 : 3);
  return rows
    .map((r, idx) => ({ r, idx: r._srcIdx ?? idx }))
    .sort((a, b) => rank(a.r) - rank(b.r) || toMin(a.r.time) - toMin(b.r.time) || a.idx - b.idx);
}
// no-invoice: Pending Payment first, then by time (oldest first)
function sortDueFirst(rows) {
  return rows
    .map((r, idx) => ({ r, idx: r._srcIdx ?? idx }))
    .sort((a, b) => ((isPendingPayment(b.r) ? 2 : isPartialPayment(b.r) ? 1 : 0) - (isPendingPayment(a.r) ? 2 : isPartialPayment(a.r) ? 1 : 0)) || toMin(a.r.time) - toMin(b.r.time) || a.idx - b.idx);
}
// Legacy add-on rows are no longer part of the active transaction UI.
// Keep them out of the list without reordering the remaining source indexes.
const activeTransactionRows = (ordered) => ordered.filter(({ r }) => !r._addon);
// Row color rule for Transactions tables: only two states carry the amber row
// tint — pending_payment and partial_deposit (both mean "guest still owes"). All
// other states (received / no_payment / private_ota / pg_member) render plain.
const isUnpaidRow = (r) => {
  const st = r._displayStatus !== undefined ? r._displayStatus : r.paymentStatus;
  return st === 'pending_payment' || st === 'partial_deposit';
};
const GuestCell = ({ r }) => <td>{r.guest}
  {isPrivateOta(r) && <span className="private-tag" style={{marginLeft:'4px',verticalAlign:'middle'}}>PRIVATE</span>}
  {r.paymentGroupCode && <span className={'pg-badge ' + (r.paymentGroupIsPrimary ? 'pg-primary' : 'pg-member')} style={{marginLeft:'4px',verticalAlign:'middle'}}>{r.paymentGroupCode}</span>}
</td>;

function InvoiceTable({ rows, onRow, onDelete, locked, canDelete }) {
  const ordered = activeTransactionRows(sortInvoice(rows));
  return (
    <div className="tcard">
      <div className="tcard-head">
        <span className="tcard-title blue">Invoice</span>
      </div>
      <div className="tscroll">
        <table className="dt">
          <thead><tr>
            <th>วันที่</th><th>เลขที่INV</th><th>ลูกค้า</th><th>ที่มา</th><th>หมวด</th><th>ห้อง</th>
            <th>ชำระ</th><th>เวลา</th><th>C/I</th><th>C/O</th>
            <th className="r">ยอดชำระ</th><th className="r">ยอดค้าง</th><th></th>
          </tr></thead>
          <tbody>
            {ordered.map(({ r, idx }) => (
              <tr key={idx} className={'clickable' + (isUnpaidRow(r) ? ' pending-row' : '')} onClick={() => onRow(r, idx)}>
                <td className="mono-c">{r.date || '—'}</td>
                <td className="mono-c">{unnumbered(r) ? '—' : r.id}</td><GuestCell r={r} /><SourceCell r={r} />
                <td>{catLabel(r)}</td><td className="mono-c">{r.room}</td><td>{r.channel}</td>
                <td className="mono-c">{r.time}</td><td className="mono-c">{d5(r.ci)}</td><td className="mono-c">{d5(r.co)}</td>
                <RecvCell v={r._displayRecv !== undefined ? r._displayRecv : r.recv} /><PendingCell v={r._displayPending !== undefined ? r._displayPending : r.pendingAmount} />
                <td>{(!locked || canDelete) && <button className="del-btn" title="ลบรายการ" onClick={(e) => { e.stopPropagation(); onDelete('inv', idx); }}>ลบ</button>}</td>
              </tr>
            ))}
            {rows.length === 0 && <tr className="empty-row"><td colSpan="13">ยังไม่มีรายการ</td></tr>}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function NoInvoiceTable({ rows, onRow, onDelete, locked, canDelete }) {
  const ordered = activeTransactionRows(sortDueFirst(rows));
  return (
    <div className="tcard">
      <div className="tcard-head">
        <span className="tcard-title blue">No Invoice</span>
      </div>
      <div className="tscroll">
        <table className="dt">
          <thead><tr>
            <th>วันที่</th><th>ลูกค้า</th><th>ที่มา</th><th>หมวด</th><th>ห้อง</th><th>ชำระ</th><th>เวลา</th>
            <th>C/I</th><th>C/O</th><th className="r">ยอดชำระ</th><th className="r">ยอดค้าง</th><th></th>
          </tr></thead>
          <tbody>
            {ordered.map(({ r, idx }) => (
              <tr key={idx} className={'clickable' + (isUnpaidRow(r) ? ' pending-row' : '')} onClick={() => onRow(r, idx)}>
                <td className="mono-c">{r.date || '—'}</td>
                <GuestCell r={r} /><SourceCell r={r} /><td>{catLabel(r)}</td><td className="mono-c">{r.room}</td>
                <ChannelCell r={r} /><td className="mono-c">{r.time}</td>
                <td className="mono-c">{d5(r.ci)}</td><td className="mono-c">{d5(r.co)}</td>
                <RecvCell v={r._displayRecv !== undefined ? r._displayRecv : r.recv} /><PendingCell v={r._displayPending !== undefined ? r._displayPending : r.pendingAmount} />
                <td>{(!locked || canDelete) && <button className="del-btn" title="ลบรายการ" onClick={(e) => { e.stopPropagation(); onDelete('noinv', idx); }}>ลบ</button>}</td>
              </tr>
            ))}
            {rows.length === 0 && <tr className="empty-row"><td colSpan="12">ยังไม่มีรายการ</td></tr>}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function ExpenseTable({ rows, onRow, onDelete, locked, canDelete, compact }) {
  const total = rows.reduce((s, r) => s + r.amount, 0);
  return (
    <div className={'tcard' + (compact ? ' tcard-side' : '')}>
      <div className="tcard-head">
        <span className="tcard-title red">รายจ่าย</span>
      </div>
      <div className="tscroll">
        <table className="dt exp-dt">
          <thead><tr><th>วันที่</th><th>หมวด</th><th>รายละเอียด</th><th className="r">จำนวนเงิน</th><th></th></tr></thead>
          <tbody>
            {rows.map((r, i) => (
              <tr key={i} className="clickable" onClick={() => onRow(r, i)}>
                <td className="mono-c">{r.date || '—'}</td><td>{r.cat}</td><td>{r.detail}</td><td className="mono-c r">{fmt(r.amount)}</td>
                <td>{(!locked || canDelete) && <button className="del-btn" onClick={(e) => { e.stopPropagation(); onDelete('exp', i); }}>ลบ</button>}</td>
              </tr>
            ))}
            {rows.length === 0 && <tr className="empty-row"><td colSpan="4">ยังไม่มีรายการ</td></tr>}
          </tbody>
          {rows.length > 0 && <tfoot><tr className="sum-row">
            <td colSpan="3" className="r">รวมทั้งหมด</td>
            <td className="mono-c r">{fmt(total)}</td>
            <td></td>
          </tr></tfoot>}
        </table>
      </div>
    </div>
  );
}

Object.assign(window, { InvoiceTable, NoInvoiceTable, ExpenseTable, StatusBadge });
