// daygig-invoicing.js — Estimates & Invoices UI (contractor mode)

(function () {
  const $ = (id) => document.getElementById(id);
  const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, c => (
    { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
  const money = (cents) => window.dgMoneyC(cents);
  const toCents = (v) => Math.round(parseFloat(String(v || '').replace(/[^0-9.]/g, '')) * 100) || 0;

  const _selected = { estimate: null, invoice: null };

  const STATUS_COLOR = {
    draft: '#888', sent: 'var(--info)', accepted: 'var(--pos)', declined: 'var(--neg)',
    converted: 'var(--info)', partial: 'var(--warn-amber)', paid: 'var(--pos)', void: '#888',
  };

  // ── Line-item rows in the create forms ──────────────────────────────────
  function _lineRow() {
    return `
      <div class="doc-line" style="display:flex;gap:6px;margin-bottom:6px;align-items:center;">
        <input type="text" class="dl-desc" placeholder="Description" style="flex:1;">
        <select class="dl-kind" style="width:90px;"><option value="labor">Labor</option><option value="material">Material</option><option value="other">Other</option></select>
        <input type="text" class="dl-qty" placeholder="Qty" value="1" style="width:48px;">
        <input type="text" class="dl-unit" placeholder="$/unit" style="width:74px;">
        <label style="font-size:11px;display:flex;align-items:center;gap:3px;"><input type="checkbox" class="dl-tax" checked>tax</label>
        <button class="btn btn-ghost btn-sm" onclick="this.closest('.doc-line').remove()">✕</button>
      </div>`;
  }
  function docAddLine(which) {
    const box = which === 'est' ? $('doc-est-lines') : $('doc-inv-lines');
    box.insertAdjacentHTML('beforeend', _lineRow());
  }
  function _collectLines(boxId) {
    return Array.from(document.querySelectorAll('#' + boxId + ' .doc-line')).map(row => ({
      description: row.querySelector('.dl-desc').value.trim(),
      kind: row.querySelector('.dl-kind').value,
      quantity: parseFloat(row.querySelector('.dl-qty').value) || 0,
      unit_cents: toCents(row.querySelector('.dl-unit').value),
      taxable: row.querySelector('.dl-tax').checked,
    })).filter(l => l.description);
  }

  // ── Create ──────────────────────────────────────────────────────────────
  async function docCreate(docType) {
    const isEst = docType === 'estimate';
    const errEl = $(isEst ? 'doc-est-err' : 'doc-inv-err');
    errEl.textContent = '';
    const customer = $(isEst ? 'doc-est-customer' : 'doc-inv-customer').value.trim();
    if (!customer) { errEl.textContent = 'Customer is required.'; errEl.classList.add('show'); return; }
    const lines = _collectLines(isEst ? 'doc-est-lines' : 'doc-inv-lines');
    if (!lines.length) { errEl.textContent = 'Add at least one line item.'; errEl.classList.add('show'); return; }
    const taxRaw = $(isEst ? 'doc-est-taxrate' : 'doc-inv-taxrate').value.trim();
    const payload = {
      customer_name: customer,
      site_address: $(isEst ? 'doc-est-address' : 'doc-inv-address').value.trim(),
      line_items: lines,
    };
    if (taxRaw !== '') payload.tax_rate = parseFloat(taxRaw) || 0;
    const url = isEst ? '/api/estimates' : '/api/invoices';
    const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }).then(r => r.json());
    if (!res.ok) { errEl.textContent = res.error || 'Could not create.'; errEl.classList.add('show'); return; }
    // reset form
    $(isEst ? 'doc-est-customer' : 'doc-inv-customer').value = '';
    $(isEst ? 'doc-est-address' : 'doc-inv-address').value = '';
    $(isEst ? 'doc-est-lines' : 'doc-inv-lines').innerHTML = '';
    $(isEst ? 'doc-est-taxrate' : 'doc-inv-taxrate').value = '';
    await docLoad(docType);
    docOpen(docType, res.document.id);
  }

  // ── List ────────────────────────────────────────────────────────────────
  async function docLoad(docType) {
    const isEst = docType === 'estimate';
    const url = isEst ? '/api/estimates' : '/api/invoices';
    const listEl = $(isEst ? 'estimates-list' : 'invoices-list');
    // seed one empty line row if the create form is empty
    const linesBox = $(isEst ? 'doc-est-lines' : 'doc-inv-lines');
    if (linesBox && !linesBox.children.length) linesBox.insertAdjacentHTML('beforeend', _lineRow());
    try {
      const data = await fetch(url).then(r => r.json());
      const docs = data.documents || [];
      if (!docs.length) { listEl.innerHTML = `<div class="hint">No ${docType}s yet.</div>`; return; }
      listEl.innerHTML = docs.map(d => `
        <button class="doc-row" onclick="docOpen('${docType}', ${d.id})" style="display:block;width:100%;text-align:left;background:${_selected[docType] === d.id ? 'var(--surface2)' : 'transparent'};border:1px solid var(--border-soft);border-radius:6px;padding:9px 11px;margin-bottom:6px;cursor:pointer;">
          <div style="display:flex;justify-content:space-between;gap:8px;">
            <strong style="font-size:13px;color:var(--text);">${esc(d.number)} · ${esc(d.customer_name)}</strong>
            <span style="font-size:10px;font-weight:700;text-transform:uppercase;color:${STATUS_COLOR[d.status] || '#888'};">${esc(d.status)}</span>
          </div>
          <div style="font-size:11px;color:var(--text-soft);margin-top:2px;">${money(d.total_cents)}${!isEst && d.balance_cents ? ' · balance ' + money(d.balance_cents) : ''}</div>
        </button>`).join('');
      // Open the first record so the detail pane is never a blank half-screen.
      if (!_selected[docType] || !docs.some(d => d.id === _selected[docType])) {
        docOpen(docType, docs[0].id);
      }
    } catch (e) {
      listEl.innerHTML = '<div class="alert err show">Could not load.</div>';
    }
  }

  // ── Detail ──────────────────────────────────────────────────────────────
  async function docOpen(docType, id) {
    _selected[docType] = id;
    const res = await fetch('/api/documents/' + id).then(r => r.json());
    if (!res.ok) return;
    const d = res.document;
    const isEst = d.doc_type === 'estimate';
    const detEl = $(isEst ? 'estimate-detail' : 'invoice-detail');
    const rows = (d.line_items || []).map(li => `
      <tr><td>${esc(li.description)}</td><td style="text-transform:capitalize;color:var(--text-soft);">${esc(li.kind)}</td>
      <td style="text-align:right;">${li.quantity}</td><td style="text-align:right;">${money(li.unit_cents)}</td>
      <td style="text-align:right;">${money(li.line_total_cents)}</td></tr>`).join('');

    let actions = '';
    if (isEst) {
      if (d.status !== 'converted') {
        if (d.status !== 'accepted') actions += `<button class="btn btn-ghost" onclick="docAccept(${d.id})">Mark Accepted</button>`;
        actions += `<button class="btn btn-primary" onclick="docConvert(${d.id})">Convert to Invoice</button>`;
      } else {
        actions += `<span class="hint">Converted to an invoice.</span>`;
      }
      actions += `<button class="btn btn-ghost" onclick="docDelete('estimate', ${d.id})">Delete</button>`;
    } else {
      const payBlock = (d.status !== 'paid' && d.status !== 'void') ? `
        <div style="display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap;margin:10px 0;">
          <div class="field" style="margin:0;"><label>Amount ($)</label><input type="text" id="inv-pay-amt" placeholder="${(Number(d.balance_cents||0)/100).toFixed(2)}" style="width:120px;"></div>
          <button class="btn btn-ghost" onclick="docPay(${d.id}, 'deposit')">Deposit</button>
          <button class="btn btn-primary" onclick="docPay(${d.id}, 'payment')">Record Payment</button>
        </div>` : '';
      actions = payBlock;
      if (d.amount_paid_cents === 0 && d.status !== 'void') actions += `<button class="btn btn-ghost" onclick="docVoid(${d.id})">Void</button>`;
    }

    detEl.innerHTML = `
      <div class="card-header" style="display:flex;justify-content:space-between;align-items:flex-start;">
        <div><div class="card-title">${esc(d.number)}</div><div class="card-sub">${esc(d.customer_name)}${d.site_address ? ' · ' + esc(d.site_address) : ''}</div></div>
        <span style="font-size:10px;font-weight:700;text-transform:uppercase;color:${STATUS_COLOR[d.status] || '#888'};">${esc(d.status)}</span>
      </div>
      <table class="schema-table" style="width:100%;font-size:12px;margin-bottom:10px;">
        <thead><tr><th>Description</th><th>Type</th><th style="text-align:right;">Qty</th><th style="text-align:right;">Unit</th><th style="text-align:right;">Amount</th></tr></thead>
        <tbody>${rows}</tbody>
      </table>
      <div style="text-align:right;font-size:13px;line-height:1.8;margin-bottom:12px;">
        <div>Subtotal: <strong>${money(d.subtotal_cents)}</strong></div>
        <div>Tax (${d.tax_rate || 0}%): <strong>${money(d.tax_cents)}</strong></div>
        <div style="font-size:15px;">Total: <strong>${money(d.total_cents)}</strong></div>
        ${!isEst && d.amount_paid_cents ? `<div>Paid: <strong>${money(d.amount_paid_cents)}</strong></div><div>Balance: <strong>${money(d.balance_cents)}</strong></div>` : ''}
      </div>
      <div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;">
        ${actions}
        <a class="btn btn-ghost" href="/api/documents/${d.id}/pdf" target="_blank">Download PDF</a>
      </div>`;
    docLoad(d.doc_type);
  }

  async function _post(url, body) {
    return fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body || {}) }).then(r => r.json());
  }

  async function docAccept(id) { await _post(`/api/estimates/${id}/accept`, {}); docOpen('estimate', id); }
  async function docConvert(id) {
    const res = await _post(`/api/estimates/${id}/convert`, {});
    if (!res.ok) { alert(res.error || 'Could not convert.'); return; }
    docOpen('estimate', id);
    alert('Invoice ' + (res.invoice ? res.invoice.number : '') + ' created. See the Invoices tab.');
  }
  async function docPay(id, kind) {
    const amt = toCents($('inv-pay-amt').value);
    if (amt <= 0) return;
    const res = await _post(`/api/invoices/${id}/payment`, { amount_cents: amt, kind: kind, payment_method: 'bank' });
    if (!res.ok) { alert(res.error || 'Could not record payment.'); return; }
    docOpen('invoice', id);
  }
  async function docVoid(id) {
    if (!confirm('Void this invoice?')) return;
    const res = await _post(`/api/invoices/${id}/void`, {});
    if (!res.ok) { alert(res.error || 'Could not void.'); return; }
    docOpen('invoice', id);
  }
  async function docDelete(docType, id) {
    if (!confirm('Delete this ' + docType + '?')) return;
    const res = await _post(`/api/documents/${id}/delete`, {});
    if (!res.ok) { alert(res.error || 'Could not delete.'); return; }
    _selected[docType] = null;
    $(docType === 'estimate' ? 'estimate-detail' : 'invoice-detail').innerHTML = '<div class="hint">Select a document.</div>';
    docLoad(docType);
  }

  window.docLoad = docLoad;
  window.docCreate = docCreate;
  window.docAddLine = docAddLine;
  window.docOpen = docOpen;
  window.docAccept = docAccept;
  window.docConvert = docConvert;
  window.docPay = docPay;
  window.docVoid = docVoid;
  window.docDelete = docDelete;
})();
