// daygig-jobs.js — Contractor job costing UI (list, detail, costs, payments, time)

(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 dollarsToCents = (v) => Math.round(parseFloat(String(v || '').replace(/[^0-9.]/g, '')) * 100) || 0;

  let _selectedJobId = null;

  const STATUS_COLOR = {
    estimate: 'var(--warn-amber)', scheduled: 'var(--info)', active: 'var(--pos)',
    completed: 'var(--info)', cancelled: '#888',
  };

  async function jobsLoad() {
    try {
      const [listRes, repRes] = await Promise.all([
        fetch('/api/jobs').then(r => r.json()),
        fetch('/api/jobs/report/profitability').then(r => r.json()),
      ]);
      const jobs = listRes.jobs || [];

      // Stats
      const openCount = jobs.filter(j => j.status !== 'completed' && j.status !== 'cancelled').length;
      const outstanding = jobs.reduce((s, j) => s + (j.outstanding_cents || 0), 0);
      $('jobs-stat-open').textContent = openCount;
      $('jobs-stat-outstanding').textContent = money(outstanding);
      if (repRes && repRes.totals) {
        $('jobs-stat-revenue').textContent = money(repRes.totals.revenue_cents);
        $('jobs-stat-profit').textContent = money(repRes.totals.profit_cents);
      }

      // List
      const list = $('jobs-list');
      if (!jobs.length) {
        list.innerHTML = '<div class="hint">No jobs yet. Create one on the left.</div>';
        return;
      }
      list.innerHTML = jobs.map(j => `
        <button class="job-row" onclick="jobsOpen(${j.id})" style="display:block;width:100%;text-align:left;background:${_selectedJobId === j.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(j.title)}</strong>
            <span style="font-size:10px;font-weight:700;text-transform:uppercase;color:${STATUS_COLOR[j.status] || '#888'};">${esc(j.status)}</span>
          </div>
          <div style="font-size:11px;color:var(--text-soft);margin-top:2px;">${esc(j.customer_name)} · profit ${money(j.costs.profit_cents)}</div>
        </button>`).join('');
      // Open the first job so the detail pane is never a blank half-screen.
      if (!_selectedJobId || !jobs.some(j => j.id === _selectedJobId)) {
        jobsOpen(jobs[0].id);
      }
    } catch (e) {
      const list = $('jobs-list');
      if (list) list.innerHTML = '<div class="alert err show">Could not load jobs.</div>';
    }
  }

  async function jobsCreate() {
    const errEl = $('job-new-err');
    errEl.textContent = '';
    const customer = $('job-new-customer').value.trim();
    const title = $('job-new-title').value.trim();
    if (!customer || !title) { errEl.textContent = 'Customer and job title are required.'; errEl.classList.add('show'); return; }
    const payload = {
      customer_name: customer,
      title: title,
      site_address: $('job-new-address').value.trim(),
      quoted_total_cents: dollarsToCents($('job-new-quote').value),
      status: 'active',
    };
    const res = await fetch('/api/jobs', { 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 job.'; errEl.classList.add('show'); return; }
    $('job-new-customer').value = ''; $('job-new-title').value = ''; $('job-new-address').value = ''; $('job-new-quote').value = '';
    await jobsLoad();
    jobsOpen(res.job.id);
  }

  async function jobsOpen(id) {
    _selectedJobId = id;
    const res = await fetch('/api/jobs/' + id).then(r => r.json());
    if (!res.ok) return;
    const j = res.job;
    const c = j.costs;
    const det = $('job-detail');
    const timeRows = (j.time_entries || []).map(t => `
      <tr><td>${esc(t.work_date)}</td><td>${esc(t.worker || '')}</td><td style="text-align:right;">${t.hours}</td>
      <td style="text-align:right;">${money(t.rate_cents)}</td><td style="text-align:right;">${money(t.amount_cents)}</td>
      <td style="text-align:center;">${t.billed ? '<span style="color:var(--info);font-size:10px;font-weight:700;">BILLED</span>' : (t.billable ? '<span style="color:var(--pos);font-size:10px;font-weight:700;">UNBILLED</span>' : '<span style="color:#888;font-size:10px;">n/b</span>')}</td>
      <td style="text-align:right;">${t.billed ? '' : `<button class="btn btn-ghost btn-sm" onclick="jobsDeleteTime(${t.id})">✕</button>`}</td></tr>`).join('')
      || '<tr><td colspan="7" style="text-align:center;color:var(--text-muted);padding:8px;">No time logged.</td></tr>';
    const unbilledCents = (j.time_entries || []).filter(t => t.billable && !t.billed).reduce((s, t) => s + (t.amount_cents || 0), 0);

    det.innerHTML = `
      <div class="card-header" style="display:flex;justify-content:space-between;align-items:flex-start;">
        <div><div class="card-title">${esc(j.title)}</div>
          <div class="card-sub">${esc(j.customer_name)}${j.site_address ? ' · ' + esc(j.site_address) : ''}</div></div>
        <span style="font-size:10px;font-weight:700;text-transform:uppercase;color:${STATUS_COLOR[j.status] || '#888'};">${esc(j.status)}</span>
      </div>

      <div class="stat-grid" style="grid-template-columns:repeat(3,1fr);margin-bottom:14px;">
        <div class="stat-tile"><div class="stat-label">Revenue</div><div class="stat-value">${money(c.revenue_cents)}</div></div>
        <div class="stat-tile"><div class="stat-label">Total Cost</div><div class="stat-value">${money(c.total_cost_cents)}</div></div>
        <div class="stat-tile"><div class="stat-label">Profit</div><div class="stat-value" style="color:${c.profit_cents < 0 ? 'var(--neg)' : 'var(--pos)'};">${money(c.profit_cents)} <span style="font-size:12px;color:var(--text-soft);">(${c.margin_pct}%)</span></div></div>
      </div>

      <table class="schema-table" style="width:100%;font-size:12px;margin-bottom:14px;">
        <tr><td>Materials & parts</td><td style="text-align:right;">${money(c.materials_cents)}</td></tr>
        <tr><td>Subcontractor labor</td><td style="text-align:right;">${money(c.subcontractor_cents)}</td></tr>
        <tr><td>Permits & fees</td><td style="text-align:right;">${money(c.permits_cents)}</td></tr>
        <tr><td>Other job costs</td><td style="text-align:right;">${money(c.other_cents)}</td></tr>
        <tr><td>Labor (logged time)</td><td style="text-align:right;">${money(c.labor_cents)}</td></tr>
        <tr style="font-weight:700;"><td>Total cost</td><td style="text-align:right;">${money(c.total_cost_cents)}</td></tr>
      </table>

      <div style="display:flex;gap:18px;flex-wrap:wrap;margin-bottom:14px;font-size:12px;color:var(--text-soft);">
        <span>Quoted: <strong style="color:var(--text);">${money(j.quoted_total_cents)}</strong></span>
        <span>Paid: <strong style="color:var(--text);">${money(j.total_paid_cents)}</strong></span>
        <span>Outstanding: <strong style="color:var(--text);">${money(j.outstanding_cents)}</strong></span>
      </div>

      <div class="card" style="margin-bottom:12px;">
        <div class="card-header"><div class="card-title" style="font-size:13px;">Record money in</div></div>
        <div style="display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap;">
          <div class="field" style="margin:0;"><label>Amount ($)</label><input type="text" id="job-pay-amount" placeholder="0.00" style="width:120px;"></div>
          <button class="btn btn-ghost" onclick="jobsRecordDeposit(${j.id})">Deposit</button>
          <button class="btn btn-primary" onclick="jobsRecordPayment(${j.id})">Payment</button>
        </div>
      </div>

      <div class="card" style="margin-bottom:12px;">
        <div class="card-header"><div class="card-title" style="font-size:13px;">Time & labor</div></div>
        <div style="display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap;margin-bottom:8px;">
          <div class="field" style="margin:0;"><label>Worker</label><input type="text" id="job-time-worker" placeholder="Name" style="width:110px;"></div>
          <div class="field" style="margin:0;"><label>Hours</label><input type="text" id="job-time-hours" placeholder="0" style="width:70px;"></div>
          <div class="field" style="margin:0;"><label>Rate ($/hr)</label><input type="text" id="job-time-rate" placeholder="0" style="width:90px;"></div>
          <button class="btn btn-ghost" onclick="jobsAddTime(${j.id})">Add time</button>
        </div>
        <table class="schema-table" style="width:100%;font-size:12px;">
          <thead><tr><th>Date</th><th>Worker</th><th style="text-align:right;">Hrs</th><th style="text-align:right;">Rate</th><th style="text-align:right;">Cost</th><th style="text-align:center;">Status</th><th></th></tr></thead>
          <tbody>${timeRows}</tbody>
        </table>
        ${unbilledCents > 0 ? `<div style="margin-top:10px;display:flex;justify-content:space-between;align-items:center;gap:8px;">
          <span style="font-size:12px;color:var(--text-soft);">Unbilled time: <strong style="color:var(--text);">${money(unbilledCents)}</strong></span>
          <button class="btn btn-primary btn-sm" onclick="jobsBillTime(${j.id})">Bill time → Invoice</button>
        </div>` : ''}
      </div>

      <div style="display:flex;gap:8px;flex-wrap:wrap;">
        ${j.status !== 'completed' ? `<button class="btn btn-primary" onclick="jobsComplete(${j.id})">Mark Complete</button>` : ''}
        ${(j.total_paid_cents === 0) ? `<button class="btn btn-ghost" onclick="jobsDelete(${j.id})">Delete</button>` : ''}
      </div>
      <div class="hint" style="margin-top:10px;">Tip: tag expenses and material purchases to this job (job_id ${j.id}) so their cost shows here automatically.</div>
    `;
    jobsLoad();  // refresh list highlight + stats
  }

  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 jobsRecordDeposit(id) {
    const amt = dollarsToCents($('job-pay-amount').value);
    if (amt <= 0) return;
    await _post(`/api/jobs/${id}/deposit`, { amount_cents: amt, payment_method: 'bank' });
    jobsOpen(id);
  }
  async function jobsRecordPayment(id) {
    const amt = dollarsToCents($('job-pay-amount').value);
    if (amt <= 0) return;
    await _post(`/api/jobs/${id}/payment`, { amount_cents: amt, payment_method: 'bank' });
    jobsOpen(id);
  }
  async function jobsAddTime(id) {
    const hours = parseFloat($('job-time-hours').value) || 0;
    if (hours <= 0) return;
    await _post(`/api/jobs/${id}/time`, {
      worker: $('job-time-worker').value.trim(),
      hours: hours,
      rate_cents: dollarsToCents($('job-time-rate').value),
    });
    jobsOpen(id);
  }
  async function jobsDeleteTime(entryId) {
    await _post(`/api/jobs/time/${entryId}/delete`, {});
    if (_selectedJobId) jobsOpen(_selectedJobId);
  }
  async function jobsComplete(id) {
    await _post(`/api/jobs/${id}/complete`, {});
    jobsOpen(id);
  }
  async function jobsBillTime(id) {
    const res = await _post(`/api/jobs/${id}/invoice-from-time`, {});
    if (!res.ok) { alert(res.error || 'Could not bill time.'); return; }
    alert('Invoice ' + (res.invoice ? res.invoice.number : '') + ' created from unbilled time. See the Invoices tab.');
    jobsOpen(id);
  }
  async function jobsDelete(id) {
    if (!confirm('Delete this job? This cannot be undone.')) return;
    const res = await _post(`/api/jobs/${id}/delete`, {});
    if (!res.ok) { alert(res.error || 'Could not delete.'); return; }
    _selectedJobId = null;
    $('job-detail').innerHTML = '<div class="hint">Select a job to see costs, payments, and profit.</div>';
    jobsLoad();
  }

  // Expose for inline handlers + the nav tab hook.
  window.jobsLoad = jobsLoad;
  window.jobsCreate = jobsCreate;
  window.jobsOpen = jobsOpen;
  window.jobsRecordDeposit = jobsRecordDeposit;
  window.jobsRecordPayment = jobsRecordPayment;
  window.jobsAddTime = jobsAddTime;
  window.jobsDeleteTime = jobsDeleteTime;
  window.jobsComplete = jobsComplete;
  window.jobsBillTime = jobsBillTime;
  window.jobsDelete = jobsDelete;
})();
