// ─── Savuki Drilling — Jobcard View / Edit Module ────────────────────────
import { getTeams } from '../api.js';
import { showToast, openModal, closeModal, navigate } from '../app.js';
import { richSelect, teamItems } from './rich-select.js';

const API = '/api/jobcards';

// Timeline types grouped for UI
const TIMELINE_GROUPS = {
  Drilling: ['DRILLING_START', 'DRILLING_STOP', 'DRILLING_PAUSE', 'DRILLING_RESUME'],
  Rieming: ['RIEMING_START', 'RIEMING_STOP', 'RIEMING_PAUSED', 'RIEMING_RESUMED'],
  Casing: ['CASING_START', 'CASING_STOP', 'CASING_PAUSE', 'CASING_RESUME'],
  Blasting: ['BLASTING_START', 'BLASTING_STOP', 'BLASTING_PAUSE', 'BLASTING_RESUME'],
  Rods: ['RODS_START', 'RODS_STOP'],
  Other: ['OTHER'],
};

const ALL_TYPES = Object.values(TIMELINE_GROUPS).flat();

// Types that carry meters (STOP/PAUSE events)
const METER_TYPES = new Set([
  'DRILLING_STOP', 'DRILLING_PAUSE',
  'RIEMING_STOP', 'RIEM_STOP', 'RIEMING_PAUSED',
  'CASING_STOP', 'CASING_PAUSE',
  'BLASTING_START', 'BLASTING_STOP', 'BLASTING_PAUSE',
  'RODS_STOP',
]);

// Requires a serial number (bit changes)
const SERIAL_TYPES = new Set([
  'RIEMING_START', 'RIEMING_STOP', 'RIEM_START', 'RIEM_STOP',
  'DRILLING_START', 'DRILLING_STOP',
]);

let _jcData = null;
let _teams = [];
let _isAdmin = false;

// ─────────────────────────────────────────────────────────────────────────
// Entry point — called from router with jobcard record_id
// ─────────────────────────────────────────────────────────────────────────
export async function initJobcardView(recordId, role) {
  _isAdmin = ['admin', 'dev', 'test'].includes(role);
  const c = document.getElementById('view-content');
  c.innerHTML = loader();

  try {
    [_jcData, _teams] = await Promise.all([
      fetchJobcard(recordId),
      getTeams().catch(() => []),
    ]);
  } catch (err) {
    c.innerHTML = `<div class="empty-state"><p>${err.message}</p></div>`;
    return;
  }

  renderPage();
}

async function fetchJobcard(id) {
  const token = localStorage.getItem('sd_token') || '';
  const res = await fetch(`${API}/get.php?id=${id}&token=${token}`);
  const json = await res.json();
  if (!json.success) throw new Error(json.message);
  return json.data;
}

// ─────────────────────────────────────────────────────────────────────────
// Full page render
// ─────────────────────────────────────────────────────────────────────────
function renderPage() {
  const { jobcard, timeline, totals, notes, payments } = _jcData;
  const jc = jobcard;

  document.getElementById('page-title').textContent = `JC #${jc.jc_no}`;

  document.getElementById('view-content').innerHTML = `

  <!-- ── Page header ──────────────────────────────────────────────── -->
  <div class="page-header">
    <div>
      <h1>JC #${jc.jc_no}</h1>
      <div class="sub">${jc.client_name || jc.address || 'No client name'} · ${jcStatusBadge(jc.jc_current_status)}</div>
    </div>
    <div style="display:flex;gap:0.5rem;flex-wrap:wrap">
      ${_isAdmin ? `<button class="btn btn-primary" id="btn-edit-jc">Edit Jobcard</button>` : ''}
      ${_isAdmin ? `<button class="btn btn-ghost btn-sm" id="btn-create-invoice">🧾 Invoice</button>` : ''}
      ${_isAdmin ? `<button class="btn btn-ghost btn-sm" id="btn-print-report">📄 PDF Report</button>` : ''}
      ${_isAdmin ? `<button class="btn btn-accent" id="btn-add-timeline">+ Timeline Entry</button>` : ''}
      <button class="btn btn-ghost btn-sm" id="btn-view-payments">
        💳 Payments${payments.length ? ` (${payments.length})` : ''}
      </button>
      <button class="btn btn-ghost" id="btn-back">← Back</button>
    </div>
  </div>

  <!-- ── Meter totals strip ───────────────────────────────────────── -->
  <div class="stat-grid" style="margin-bottom:1rem">
    ${meterStat('Drilling', totals.drilling, 'blue')}
    ${meterStat('Rieming', totals.rieming, 'navy')}
    ${meterStat('Casing', totals.casing, 'orange')}
    ${meterStat('Blasting', totals.blasting, 'red')}
    ${totals.rods > 0 ? meterStat('Rods', totals.rods, 'green') : ''}
    ${meterStat('Total', totals.total, 'green')}
    <div class="stat-card green" style="cursor:pointer" id="stat-payments-card">
      <div class="stat-label">Total Paid</div>
      <div class="stat-value" style="font-size:1.3rem">R ${(payments.reduce((s, p) => s + (+p.amount || 0), 0)).toLocaleString('en-ZA', { minimumFractionDigits: 2 })}</div>
      <div class="stat-sub">${payments.length} payment${payments.length !== 1 ? 's' : ''}</div>
    </div>
  </div>

  <!-- ── Tab nav ───────────────────────────────────────────────────── -->
  <div style="display:flex;gap:0;border-bottom:2px solid var(--border);margin-bottom:1rem;overflow-x:auto;flex-wrap:nowrap">
    ${['Client', 'Drilling', 'Jobcard Info', 'Timeline', 'Notes', 'Payments', 'Site Photos', 'Map'].map((t, i) => `
      <button class="jc-tab-btn${i === 0 ? ' active' : ''}" data-tab="${i}"
        style="padding:.55rem 1rem;border:none;background:none;cursor:pointer;white-space:nowrap;
               font-size:.85rem;font-weight:600;color:var(--text-muted);border-bottom:2px solid transparent;
               margin-bottom:-2px;transition:color .15s">
        ${t}
      </button>`).join('')}
  </div>

  <!-- ── Tab panels ─────────────────────────────────────────────────── -->

  <!-- 0: Client Details -->
  <div class="jc-tab-panel" data-panel="0">
    <div class="card"><div style="padding:0">
      ${detailRows([
    ['Client Name', jc.client_name],
    ['Contact Name', jc.contact_name],
    ['Contact Number', jc.contact_number],
    ['Other Number', jc.other_number],
    ['Alternate Number', jc.alternate_number],
    ['Address', jc.address],
    ['GPS Coordinates', jc.drill_co_ordinates],
    ['Slip No', jc.slip_no],
  ])}
    </div></div>
  </div>

  <!-- 1: Drilling Results -->
  <div class="jc-tab-panel" data-panel="1" style="display:none">
    <div class="card"><div style="padding:0">
      ${detailRows([
    ['Water Strike', jc.water_strike],
    ['Water Flow', jc.water_flow],
    ['Interested in Pump', jc.interested_in_pump],
    ['Compressor Hours', jc.compressor_hours],
    ['Diesel Start', jc.diesel_start],
    ['Diesel Stop', jc.diesel_stop],
    ['Diesel Used', dieselUsed(jc.diesel_start, jc.diesel_stop)],
    ['Estimated Litres', jc.estimated_liters],
  ])}
    </div></div>
  </div>

  <!-- 2: Jobcard Info -->
  <div class="jc-tab-panel" data-panel="2" style="display:none">
    <div class="card"><div style="padding:0">
      ${detailRows([
    ['JC Number', jc.jc_no],
    ['Team', jc.team_name],
    ['Status', jc.jc_current_status],
    ['Action Date', jc.action_date],
    ['Date Created', jc.date_created],
    ['Date Closed', jc.date_time_closed],
    ['Created By', jc.created_by],
  ])}
    </div></div>
  </div>

  <!-- 3: Timeline -->
  <div class="jc-tab-panel" data-panel="3" style="display:none">
    <div class="card" id="timeline-card">
      <div class="card-body" style="padding:0" id="timeline-body">
        ${renderTimeline(timeline)}
      </div>
    </div>
  </div>

  <!-- 4: Notes -->
  <div class="jc-tab-panel" data-panel="4" style="display:none">
    <div class="card">
      <div class="card-body" id="notes-body">
        ${renderNotes(notes)}
      </div>
    </div>
  </div>

  <!-- 5: Payments -->
  <div class="jc-tab-panel" data-panel="5" style="display:none">
    <div class="card">
      <div class="card-body" style="padding:0" id="payments-panel">
        ${renderPayments(payments)}
      </div>
    </div>
  </div>

  <!-- 6: Site Photos -->
  <div class="jc-tab-panel" data-panel="6" style="display:none">
    <div class="card">
      <div class="card-body">
        ${renderSitePhotos(jc) || '<div class="empty-state"><p>No site photos.</p></div>'}
      </div>
    </div>
  </div>

  <!-- 7: Map -->
  <div class="jc-tab-panel" data-panel="7" style="display:none">
    <div class="card">
      <div class="card-body">
        ${jc.drill_co_ordinates ? `
        <div id="jc-map" style="width:100%;height:400px;border-radius:8px;overflow:hidden"></div>` :
      '<div class="empty-state"><p>No GPS coordinates recorded.</p></div>'}
      </div>
    </div>
  </div>

    </div>
  </div>`;

  // Wire buttons
  document.getElementById('btn-back')?.addEventListener('click', () => navigate('jobcards'));

  // ── Tab switching ──────────────────────────────────────────────────
  const tabBtns = document.querySelectorAll('.jc-tab-btn');
  const tabPanels = document.querySelectorAll('.jc-tab-panel');
  tabBtns.forEach(btn => {
    btn.addEventListener('click', () => {
      const idx = +btn.dataset.tab;
      tabBtns.forEach(b => {
        const active = +b.dataset.tab === idx;
        b.style.color = active ? 'var(--navy)' : 'var(--text-muted)';
        b.style.borderColor = active ? 'var(--navy)' : 'transparent';
      });
      tabPanels.forEach(p => {
        p.style.display = +p.dataset.panel === idx ? '' : 'none';
      });
      // Lazy-init map when Map tab is opened
      if (idx === 7) initJcMap(_jcData.jobcard.drill_co_ordinates);
    });
  });
  // Set initial active tab style
  tabBtns[0].style.color = 'var(--navy)';
  tabBtns[0].style.borderColor = 'var(--navy)';

  if (_isAdmin) {
    document.getElementById('btn-edit-jc')?.addEventListener('click', openEditModal);
    document.getElementById('btn-create-invoice')?.addEventListener('click', () =>
      navigate('invoice-create', { jc_id: _jcData.jobcard.record_id })
    );
    document.getElementById('btn-print-report')?.addEventListener('click', () => {
      const token = localStorage.getItem('sd_token') || '';
      const id = _jcData.jobcard.record_id;
      window.open(`/api/jobcards/print-report.php?id=${id}&token=${encodeURIComponent(token)}`, '_blank');
    });
    document.getElementById('btn-add-timeline')?.addEventListener('click', () => openTimelineModal());

    const openPay = () => openPaymentsModal(_jcData.jobcard.record_id);
    document.getElementById('btn-view-payments')?.addEventListener('click', openPay);
    document.getElementById('stat-payments-card')?.addEventListener('click', openPay);
  }

  // Edit/delete on existing timeline rows
  rebindTimeline();
}

// ── Map initialiser ──────────────────────────────────────────────────────
function initJcMap(coordStr) {
  const el = document.getElementById('jc-map');
  if (!el || el.dataset.loaded) return;
  el.dataset.loaded = '1';
  if (!coordStr) return;
  const [lat, lng] = coordStr.split(',').map(s => parseFloat(s.trim()));
  if (isNaN(lat) || isNaN(lng)) return;

  const iframe = document.createElement('iframe');
  iframe.style.cssText = 'width:100%;height:400px;border:none';
  iframe.src = `https://maps.google.com/maps?q=${lat},${lng}&z=15&output=embed`;
  el.appendChild(iframe);
}

// ─────────────────────────────────────────────────────────────────────────
// Timeline render
// ─────────────────────────────────────────────────────────────────────────
function renderTimeline(timeline) {
  if (!timeline.length) return `<div class="empty-state" style="padding:2rem"><p>No timeline entries yet.</p></div>`;

  // Group into visual segments
  let rows = timeline.map(t => {
    const hasMeter = METER_TYPES.has(t.type) && +t.meters > 0;
    const category = typeCategory(t.type);
    return `<tr data-tid="${t.record_id}">
      <td data-label="Time" class="tl-time">${formatTime(t.date_time)}</td>
      <td data-label="Event">${typeBadge(t.type)}</td>
      <td data-label="Meters" style="font-weight:600;color:var(--accent)">
        ${hasMeter ? t.meters + 'm' : '—'}
      </td>
      <td data-label="Serial" style="font-size:0.78rem;color:var(--text-muted)">${t.serial_number || '—'}</td>
      <td data-label="By" style="font-size:0.78rem;color:var(--text-muted)">${t.username || '—'}</td>
      ${_isAdmin ? `
      <td data-label="">
        <div style="display:flex;gap:0.3rem;justify-content:flex-end">
          <button class="btn btn-ghost btn-sm tl-edit" data-tid="${t.record_id}">Edit</button>
          <button class="btn btn-ghost btn-sm tl-del" data-tid="${t.record_id}"
            style="color:var(--danger)">Del</button>
        </div>
      </td>` : '<td></td>'}
    </tr>`;
  }).join('');

  return `<div class="table-wrap"><table>
    <thead><tr>
      <th>Time</th><th>Event</th><th>Meters</th><th>Serial / Bit</th><th>By</th>
      ${_isAdmin ? '<th></th>' : '<th></th>'}
    </tr></thead>
    <tbody>${rows}</tbody>
  </table></div>`;
}

function rebindTimeline() {
  if (!_isAdmin) return;
  document.querySelectorAll('.tl-edit').forEach(btn => {
    btn.addEventListener('click', () => {
      const entry = _jcData.timeline.find(t => t.record_id == btn.dataset.tid);
      if (entry) openTimelineModal(entry);
    });
  });
  document.querySelectorAll('.tl-del').forEach(btn => {
    btn.addEventListener('click', async () => {
      if (!confirm('Delete this timeline entry?')) return;
      try {
        await timelineDelete(btn.dataset.tid);
        _jcData.timeline = _jcData.timeline.filter(t => t.record_id != btn.dataset.tid);
        recalcTotals();
        refreshTimelineCard();
        showToast('Entry deleted.', 'success');
      } catch (err) { showToast(err.message, 'error'); }
    });
  });
}

function refreshTimelineCard() {
  document.getElementById('timeline-body').innerHTML = renderTimeline(_jcData.timeline);
  document.querySelector('.card-header .badge-navy').textContent = `${_jcData.timeline.length} entries`;
  rebindTimeline();
  // Refresh stat cards
  const strip = document.querySelector('.stat-grid');
  if (strip) {
    const t = _jcData.totals;
    strip.innerHTML = `
      ${meterStat('Drilling', t.drilling, 'blue')}
      ${meterStat('Rieming', t.rieming, 'navy')}
      ${meterStat('Casing', t.casing, 'orange')}
      ${meterStat('Blasting', t.blasting, 'red')}
      ${t.rods > 0 ? meterStat('Rods', t.rods, 'green') : ''}
      ${meterStat('Total', t.total, 'green')}`;
  }
}

function recalcTotals() {
  const totals = { rieming: 0, drilling: 0, casing: 0, blasting: 0, rods: 0, total: 0 };
  for (const t of _jcData.timeline) {
    const type = (t.type || '').toUpperCase();
    const m = parseFloat(t.meters) || 0;
    if (['RIEMING_STOP', 'RIEM_STOP', 'RIEMING_PAUSED'].includes(type)) totals.rieming += m;
    if (['DRILLING_STOP', 'DRILLING_PAUSE'].includes(type)) totals.drilling += m;
    if (['CASING_STOP', 'CASING_PAUSE'].includes(type)) totals.casing += m;
    if (['BLASTING_START', 'BLASTING_STOP', 'BLASTING_PAUSE'].includes(type)) totals.blasting += m;
    if (['RODS_STOP'].includes(type)) totals.rods += m;
  }
  totals.total = totals.rieming + totals.drilling + totals.casing + totals.blasting + totals.rods;
  _jcData.totals = totals;
}

// ─────────────────────────────────────────────────────────────────────────
// Timeline modal — add or edit
// ─────────────────────────────────────────────────────────────────────────
function openTimelineModal(entry = null) {
  const isEdit = !!entry;
  const dt = entry ? entry.date_time?.replace(' ', 'T') : new Date().toISOString().slice(0, 16);

  // Build type options grouped
  const typeOpts = Object.entries(TIMELINE_GROUPS).map(([group, types]) =>
    `<optgroup label="${group}">${types.map(t =>
      `<option value="${t}" ${entry?.type === t ? 'selected' : ''}>${t.replace(/_/g, ' ')}</option>`
    ).join('')}</optgroup>`
  ).join('');

  openModal(isEdit ? 'Edit Timeline Entry' : 'Add Timeline Entry', `
    <div class="form-group">
      <label class="form-label">Event Type <span style="color:var(--danger)">*</span></label>
      <select class="form-control" id="tl-type" required>
        <option value="">— Select Type —</option>
        ${typeOpts}
      </select>
    </div>

    <div class="form-row">
      <div class="form-group" id="tl-meters-wrap">
        <label class="form-label">Meters</label>
        <input class="form-control" id="tl-meters" type="number" min="0" step="0.5"
               value="${entry?.meters || 0}" placeholder="0" />
        <div style="font-size:0.72rem;color:var(--text-muted);margin-top:0.2rem">
          Only required for STOP / PAUSE events
        </div>
      </div>
      <div class="form-group" id="tl-serial-wrap">
        <label class="form-label">Serial / Bit #</label>
        <input class="form-control" id="tl-serial" type="text"
               value="${entry?.serial_number || ''}" placeholder="Optional" />
        <div style="font-size:0.72rem;color:var(--text-muted);margin-top:0.2rem">
          Required for Rieming / Drilling events
        </div>
      </div>
    </div>

    <div class="form-group">
      <label class="form-label">Date & Time <span style="color:var(--danger)">*</span></label>
      <input class="form-control" id="tl-datetime" type="datetime-local" value="${dt}" required />
    </div>

    <div id="tl-error" class="login-error"></div>
  `, async () => {
    const errEl = document.getElementById('tl-error');
    errEl.classList.remove('visible');
    const type = document.getElementById('tl-type').value;
    const dt2 = document.getElementById('tl-datetime').value;
    if (!type) { errEl.textContent = 'Event type is required.'; errEl.classList.add('visible'); return; }
    if (!dt2) { errEl.textContent = 'Date & time is required.'; errEl.classList.add('visible'); return; }

    const payload = {
      type,
      meters: document.getElementById('tl-meters').value,
      serial_number: document.getElementById('tl-serial').value,
      date_time: dt2,
    };

    try {
      if (isEdit) {
        await timelineUpdate({ record_id: entry.record_id, ...payload });
        const idx = _jcData.timeline.findIndex(t => t.record_id == entry.record_id);
        if (idx > -1) _jcData.timeline[idx] = { ..._jcData.timeline[idx], ...payload, date_time: dt2.replace('T', ' ') };
        showToast('Entry updated.', 'success');
      } else {
        const res = await timelineAdd({ jobcard_id: _jcData.jobcard.record_id, ...payload });
        _jcData.timeline.push({ ...res, date_time: dt2.replace('T', ' ') });
        showToast('Entry added.', 'success');
      }
      recalcTotals();
      closeModal();
      refreshTimelineCard();
    } catch (err) {
      errEl.textContent = err.message;
      errEl.classList.add('visible');
    }
  }, {
    confirmLabel: isEdit ? 'Save Changes' : 'Add Entry',
    confirmClass: 'btn-primary',
  });

  // Show/hide meters hint based on type selection
  document.getElementById('tl-type')?.addEventListener('change', e => {
    const needsMeters = METER_TYPES.has(e.target.value);
    document.getElementById('tl-meters').style.fontWeight = needsMeters ? '700' : '';
  });
  if (entry?.type) {
    const sel = document.getElementById('tl-type');
    if (sel) sel.dispatchEvent(new Event('change'));
  }
}

// ─────────────────────────────────────────────────────────────────────────
// Edit jobcard modal
// ─────────────────────────────────────────────────────────────────────────
function openEditModal() {
  const jc = _jcData.jobcard;
  let ejTeamRs = null;

  const actionDt = (jc.action_date || '').replace(' ', 'T');

  openModal(`Edit JC #${jc.jc_no}`, `
    <div class="form-row">
      <div class="form-group">
        <label class="form-label">Client Name</label>
        <input class="form-control" id="ej-client" value="${esc(jc.client_name)}" />
      </div>
      <div class="form-group">
        <label class="form-label">Contact Name</label>
        <input class="form-control" id="ej-cname" value="${esc(jc.contact_name)}" />
      </div>
    </div>
    <div class="form-row">
      <div class="form-group">
        <label class="form-label">Contact Number</label>
        <input class="form-control" id="ej-phone" value="${esc(jc.contact_number)}" />
      </div>
      <div class="form-group">
        <label class="form-label">Other Number</label>
        <input class="form-control" id="ej-other" value="${esc(jc.other_number)}" />
      </div>
    </div>
    <div class="form-group">
      <label class="form-label">Alternate Number</label>
      <input class="form-control" id="ej-alt" value="${esc(jc.alternate_number)}" />
    </div>
    <div class="form-group">
      <label class="form-label">Address</label>
      <input class="form-control" id="ej-address" value="${esc(jc.address)}" />
    </div>
    <div class="form-group">
      <label class="form-label">GPS Coordinates</label>
      <input class="form-control" id="ej-gps" value="${esc(jc.drill_co_ordinates)}" placeholder="-25.123, 31.456" />
    </div>
    <div class="form-row">
      <div class="form-group">
        <label class="form-label">Team</label>
        <div id="ej-team-rs"></div>
      </div>
      <div class="form-group">
        <label class="form-label">Status</label>
        <select class="form-control" id="ej-status">
          ${['PENDING', 'ACTIVE', 'DRILLING', 'COMPLETE'].map(s =>
    `<option value="${s}" ${jc.jc_current_status === s ? 'selected' : ''}>${s}</option>`
  ).join('')}
        </select>
      </div>
    </div>
    <div class="form-group">
      <label class="form-label">Action Date</label>
      <input class="form-control" id="ej-date" type="datetime-local" value="${actionDt}" />
    </div>

    <hr style="border:none;border-top:1px solid var(--border);margin:1rem 0">
    <div style="font-family:var(--font-display);font-size:0.7rem;letter-spacing:.1em;text-transform:uppercase;
                color:var(--text-muted);margin-bottom:0.75rem">Drilling Results</div>

    <div class="form-row">
      <div class="form-group">
        <label class="form-label">Water Strike (m)</label>
        <input class="form-control" id="ej-wstrike" value="${esc(jc.water_strike)}" />
      </div>
      <div class="form-group">
        <label class="form-label">Water Flow</label>
        <input class="form-control" id="ej-wflow" value="${esc(jc.water_flow)}" />
      </div>
    </div>
    <div class="form-row">
      <div class="form-group">
        <label class="form-label">Diesel Start</label>
        <input class="form-control" id="ej-dstart" type="number" value="${esc(jc.diesel_start)}" />
      </div>
      <div class="form-group">
        <label class="form-label">Diesel Stop</label>
        <input class="form-control" id="ej-dstop" type="number" value="${esc(jc.diesel_stop)}" />
      </div>
    </div>
    <div class="form-row">
      <div class="form-group">
        <label class="form-label">Compressor Hours</label>
        <input class="form-control" id="ej-comp" value="${esc(jc.compressor_hours)}" />
      </div>
      <div class="form-group">
        <label class="form-label">Interested in Pump?</label>
        <select class="form-control" id="ej-pump">
          <option value="">—</option>
          <option value="YES" ${jc.interested_in_pump === 'YES' ? 'selected' : ''}>YES</option>
          <option value="NO"  ${jc.interested_in_pump === 'NO' ? 'selected' : ''}>NO</option>
        </select>
      </div>
    </div>
    <div class="form-row">
      <div class="form-group">
        <label class="form-label">Slip No</label>
        <input class="form-control" id="ej-slip" value="${esc(jc.slip_no)}" />
      </div>
      <div class="form-group">
        <label class="form-label">Estimated Litres</label>
        <input class="form-control" id="ej-liters" type="number" value="${esc(jc.estimated_liters)}" />
      </div>
    </div>

    <div id="ej-error" class="login-error"></div>
  `, async () => {
    const errEl = document.getElementById('ej-error');
    errEl.classList.remove('visible');
    try {
      await jobcardUpdate({
        id: jc.record_id,
        jc_no: jc.jc_no,
        client_name: document.getElementById('ej-client').value,
        contact_name: document.getElementById('ej-cname').value,
        contact_number: document.getElementById('ej-phone').value,
        other_number: document.getElementById('ej-other').value,
        alternate_number: document.getElementById('ej-alt').value,
        address: document.getElementById('ej-address').value,
        drill_co_ordinates: document.getElementById('ej-gps').value,
        team_assigned_id: ejTeamRs?.getValue() || '',
        jc_current_status: document.getElementById('ej-status').value,
        action_date: document.getElementById('ej-date').value,
        water_strike: document.getElementById('ej-wstrike').value,
        water_flow: document.getElementById('ej-wflow').value,
        diesel_start: document.getElementById('ej-dstart').value,
        diesel_stop: document.getElementById('ej-dstop').value,
        compressor_hours: document.getElementById('ej-comp').value,
        interested_in_pump: document.getElementById('ej-pump').value,
        slip_no: document.getElementById('ej-slip').value,
        estimated_liters: document.getElementById('ej-liters').value,
      });

      // Update local data & re-render
      const newTeamId = ejTeamRs?.getValue() || '';
      Object.assign(_jcData.jobcard, {
        client_name: document.getElementById('ej-client').value,
        contact_name: document.getElementById('ej-cname').value,
        contact_number: document.getElementById('ej-phone').value,
        other_number: document.getElementById('ej-other').value,
        alternate_number: document.getElementById('ej-alt').value,
        address: document.getElementById('ej-address').value,
        drill_co_ordinates: document.getElementById('ej-gps').value,
        jc_current_status: document.getElementById('ej-status').value,
        water_strike: document.getElementById('ej-wstrike').value,
        water_flow: document.getElementById('ej-wflow').value,
        diesel_start: document.getElementById('ej-dstart').value,
        diesel_stop: document.getElementById('ej-dstop').value,
        compressor_hours: document.getElementById('ej-comp').value,
        interested_in_pump: document.getElementById('ej-pump').value,
        slip_no: document.getElementById('ej-slip').value,
        team_assigned_id: newTeamId,
        team_name: _teams.find(t => String(t.record_id) === String(newTeamId))?.name || jc.team_name,
      });

      closeModal();
      showToast('Jobcard updated.', 'success');
      renderPage();
    } catch (err) {
      errEl.textContent = err.message;
      errEl.classList.add('visible');
    }
  }, { confirmLabel: 'Save Jobcard', confirmClass: 'btn-primary' });

  // Init team rich select after modal is in DOM
  ejTeamRs = richSelect('ej-team-rs', {
    placeholder: 'Search teams…',
    items: teamItems(_teams),
  });
  if (jc.team_assigned_id) ejTeamRs.setValue(jc.team_assigned_id);
}

// ─────────────────────────────────────────────────────────────────────────
// API calls
// ─────────────────────────────────────────────────────────────────────────
async function apiPost(path, data) {
  const token = localStorage.getItem('sd_token') || '';
  const body = new URLSearchParams({ ...data, token });
  const res = await fetch(`${API}/${path}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body,
  });
  const json = await res.json();
  if (!json.success) throw new Error(json.message);
  return json.data;
}

const jobcardUpdate = d => apiPost('update.php', d);
const timelineAdd = d => apiPost('timeline-add.php', d);
const timelineUpdate = d => apiPost('timeline-update.php', d);
const timelineDelete = id => apiPost('timeline-delete.php', { record_id: id });

// ─────────────────────────────────────────────────────────────────────────
// Render helpers
// ─────────────────────────────────────────────────────────────────────────
function meterStat(label, value, color) {
  return `<div class="stat-card ${color}">
    <div class="stat-label">${label}</div>
    <div class="stat-value">${value ?? 0}<span style="font-size:1rem;font-weight:500">m</span></div>
  </div>`;
}

function detailRows(pairs) {
  return `<table style="width:100%">
    ${pairs.map(([label, val]) => `
    <tr>
      <td style="padding:0.55rem 1rem;font-size:0.75rem;font-weight:700;text-transform:uppercase;
                 letter-spacing:.07em;color:var(--text-muted);white-space:nowrap;width:45%;
                 border-bottom:1px solid var(--border-light)">${label}</td>
      <td style="padding:0.55rem 1rem;font-size:0.875rem;color:var(--text);
                 border-bottom:1px solid var(--border-light)">${val || '<span style="color:var(--text-light)">—</span>'}</td>
    </tr>`).join('')}
  </table>`;
}

const SITE_PHOTO_FIELDS = [
  { field: 'samples_image', label: 'Rock Samples' },
  { field: 'client_merch_image', label: 'Client Merch' },
  { field: 'casing_report_image', label: 'Casing Report' },
  { field: 'bytel_report_image', label: 'Bytel Report' },
  { field: 'board_image', label: 'Board Image' },
  { field: 'slip_no_image', label: 'Slip Number' },
];

function renderSitePhotos(jc) {
  const hasPhotos = SITE_PHOTO_FIELDS.some(p => jc[p.field]);
  if (!hasPhotos) return '';
  return `<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px">
    ${SITE_PHOTO_FIELDS.filter(p => jc[p.field]).map(p => {
    const src = TECH_UPLOADS + 'jobcards/' + jc[p.field];
    return `<div style="text-align:center">
        <img src="${src}"
             onclick="window.open(this.src,'_blank')"
             style="width:100%;height:110px;object-fit:cover;border-radius:8px;
                    border:1px solid var(--border-light);cursor:pointer" />
        <div style="font-size:.72rem;color:var(--text-muted);margin-top:4px">${p.label}</div>
      </div>`;
  }).join('')}
  </div>`;
}

const TECH_UPLOADS = 'https://api.elegantwork.co.za/savuki_app/uploads/';

function renderNotes(notes) {
  if (!notes.length) return `<div class="empty-state"><p>No notes.</p></div>`;
  return notes.map(n => `
    <div style="border-bottom:1px solid var(--border-light);padding:0.65rem 0;last-child:border:none">
      ${n.reason ? `<div style="margin-bottom:.3rem">
        <span class="badge badge-navy" style="font-size:.7rem">${esc(n.reason)}</span>
      </div>` : ''}
      <div style="font-size:0.82rem;color:var(--text)">${n.note || ''}</div>
      ${n.image ? `
      <div style="margin-top:.5rem">
        <img src="${TECH_UPLOADS}notes/${n.image}"
             style="max-width:100%;max-height:220px;border-radius:8px;border:1px solid var(--border-light);cursor:pointer"
             onclick="window.open(this.src,'_blank')"
             alt="Note photo" />
      </div>` : ''}
      <div style="font-size:0.72rem;color:var(--text-muted);margin-top:0.2rem">
        ${n.date_time || ''}
      </div>
    </div>`).join('');
}

function bindPaymentEditButtons(container) {
  container.querySelectorAll('.pay-edit-btn').forEach(btn => {
    btn.addEventListener('click', () => {
      const payment = JSON.parse(decodeURIComponent(btn.dataset.payment));
      openEditPaymentModal(payment);
    });
  });
}

// ── Payments popup modal ──────────────────────────────────────────────────
function openPaymentsModal(jobcardId) {
  const payments = _jcData.payments || [];
  const total = payments.reduce((s, p) => s + (+p.amount || 0), 0);

  function modalBody() {
    const rows = _jcData.payments || [];
    const tot = rows.reduce((s, p) => s + (+p.amount || 0), 0);
    return `
      ${_isAdmin ? `<div style="margin-bottom:.75rem">
        <button class="btn btn-primary btn-sm" id="btn-pay-add-inner">+ Add Payment</button>
      </div>` : ''}
      ${rows.length ? `<div class="table-wrap"><table>
        <thead><tr>
          <th>Method</th><th>Amount</th><th>By</th><th>Date</th><th>Proof</th>
          ${_isAdmin ? '<th></th>' : ''}
        </tr></thead>
        <tbody>
          ${rows.map(p => `<tr>
            <td><span class="badge badge-navy">${p.payment_method || '—'}</span></td>
            <td><strong>R ${(+p.amount || 0).toLocaleString('en-ZA', { minimumFractionDigits: 2 })}</strong></td>
            <td style="font-size:.78rem;color:var(--text-muted)">${p.username || '—'}</td>
            <td style="font-size:.78rem;color:var(--text-muted)">${(p.date_time || '').slice(0, 10)}</td>
            <td>${p.file
        ? `<a href="/uploads/payments/${p.file}" target="_blank"
                   style="font-size:.75rem;color:var(--primary)"
                   onclick="checkPaySlip(event,this,'${p.file}')">View ↗</a>`
        : '<span style="color:var(--text-muted);font-size:.75rem">—</span>'}</td>
            ${_isAdmin ? `<td><button class="btn btn-ghost btn-sm pay-edit-btn"
              data-payment="${encodeURIComponent(JSON.stringify(p))}"
              style="font-size:.72rem">Edit</button></td>` : ''}
          </tr>`).join('')}
        </tbody>
      </table>
      <div style="text-align:right;padding:.75rem 1rem;font-weight:700;border-top:2px solid var(--border)">
        Total Paid: <span style="color:var(--success)">R ${tot.toLocaleString('en-ZA', { minimumFractionDigits: 2 })}</span>
      </div></div>`
        : `<div class="empty-state" style="padding:2rem"><p>No payments recorded yet.</p></div>`}`;
  }

  function refreshModal() {
    const body = document.getElementById('pay-modal-body');
    if (body) {
      body.innerHTML = modalBody();
      bindModalPaymentButtons(jobcardId, refreshModal);
    }
    // Refresh summary stat card
    const rows = _jcData.payments || [];
    const tot = rows.reduce((s, p) => s + (+p.amount || 0), 0);
    const statCard = document.getElementById('stat-payments-card');
    if (statCard) {
      statCard.querySelector('.stat-value').textContent =
        `R ${tot.toLocaleString('en-ZA', { minimumFractionDigits: 2 })}`;
      statCard.querySelector('.stat-sub').textContent =
        `${rows.length} payment${rows.length !== 1 ? 's' : ''}`;
    }
    const btn = document.getElementById('btn-view-payments');
    if (btn) btn.textContent = `💳 Payments${rows.length ? ` (${rows.length})` : ''}`;
  }

  openModal('Payments', `<div id="pay-modal-body">${modalBody()}</div>`,
    closeModal,
    { confirmLabel: 'Close', confirmClass: 'btn-ghost' }
  );

  setTimeout(() => {
    document.getElementById('modal-cancel-btn')?.remove();
    bindModalPaymentButtons(jobcardId, refreshModal);
  }, 50);
}

function bindModalPaymentButtons(jobcardId, refresh) {
  document.getElementById('btn-pay-add-inner')?.addEventListener('click', () =>
    openAddPaymentModal(jobcardId, refresh)
  );
  document.querySelectorAll('.pay-edit-btn').forEach(btn => {
    if (btn._bound) return; btn._bound = true;
    btn.addEventListener('click', () => {
      const p = JSON.parse(decodeURIComponent(btn.dataset.payment));
      openEditPaymentModal(p, refresh);
    });
  });
}

function openAddPaymentModal(jobcardId, onDone) {
  openPaymentModal({ jobcardId, mode: 'add', onDone });
}

function openEditPaymentModal(payment, onDone) {
  openPaymentModal({ jobcardId: payment.jobcard_id, mode: 'edit', payment, onDone });
}

function openPaymentModal({ jobcardId, mode, payment = null, onDone = null }) {
  const isEdit = mode === 'edit';
  const title = isEdit ? 'Edit Payment' : 'Add Payment';
  const hasFile = isEdit && payment.file;

  openModal(title, `
    <div class="form-row">
      <div class="form-group">
        <label class="form-label">Payment Method <span style="color:var(--danger)">*</span></label>
        <select class="form-control" id="pay-method">
          <option value="">— Select —</option>
          <option value="CASH"   ${payment?.payment_method === 'CASH' ? 'selected' : ''}>Cash</option>
          <option value="EFT"    ${payment?.payment_method === 'EFT' ? 'selected' : ''}>EFT</option>
          <option value="CARD"   ${payment?.payment_method === 'CARD' ? 'selected' : ''}>Card</option>
          <option value="CHEQUE" ${payment?.payment_method === 'CHEQUE' ? 'selected' : ''}>Cheque</option>
        </select>
      </div>
      <div class="form-group">
        <label class="form-label">Amount (R) <span style="color:var(--danger)">*</span></label>
        <input class="form-control" id="pay-amount" type="number" min="0.01" step="0.01"
               value="${payment?.amount || ''}" placeholder="0.00" />
      </div>
    </div>
    <div id="pay-eft-wrap" style="display:${payment?.payment_method === 'EFT' ? '' : 'none'}" class="form-group">
      <label class="form-label">
        Proof of Payment (EFT) <span style="color:var(--danger)">*</span>
        ${hasFile ? `<span style="font-size:.75rem;color:var(--success);margin-left:.5rem">✓ File on record${isEdit ? ' — upload new to replace' : ''}</span>` : ''}
      </label>
      <input class="form-control" id="pay-file" type="file" accept="image/*,.pdf"
             ${isEdit && hasFile ? '' : ''} />
      ${hasFile ? `<div style="font-size:.75rem;color:var(--text-muted);margin-top:.25rem">Current: ${payment.file}</div>` : ''}
    </div>
    <div id="pay-err" class="login-error"></div>
  `, async () => {
    const errEl = document.getElementById('pay-err');
    errEl.classList.remove('visible');
    const method = document.getElementById('pay-method')?.value;
    const amount = parseFloat(document.getElementById('pay-amount')?.value || 0);
    const fileInput = document.getElementById('pay-file');
    const hasNewFile = fileInput?.files?.length > 0;

    if (!method) { errEl.textContent = 'Payment method is required.'; errEl.classList.add('visible'); return; }
    if (amount <= 0) { errEl.textContent = 'Amount must be greater than 0.'; errEl.classList.add('visible'); return; }
    // EFT: new add always needs file; edit needs file only if no existing file
    if (method === 'EFT' && !hasNewFile && !(isEdit && payment.file)) {
      errEl.textContent = 'Proof of payment is required for EFT.'; errEl.classList.add('visible'); return;
    }

    try {
      const formData = new FormData();
      formData.append('token', localStorage.getItem('sd_token') || '');
      formData.append('payment_method', method);
      formData.append('amount', amount);
      if (isEdit) formData.append('record_id', payment.record_id);
      else formData.append('jobcard_id', jobcardId);
      if (hasNewFile) formData.append('file', fileInput.files[0]);

      const url = isEdit ? '/api/jobcards/payment-update.php' : '/api/jobcards/payment-add.php';
      const res = await fetch(url, { method: 'POST', body: formData });
      const json = await res.json();
      if (!json.success) throw new Error(json.message);

      if (isEdit) {
        // Replace in local data
        const idx = _jcData.payments.findIndex(p => p.record_id == payment.record_id);
        if (idx > -1) _jcData.payments[idx] = json.data;
      } else {
        _jcData.payments.push(json.data);
      }

      const bodyEl = document.getElementById('payments-body');
      const count = document.getElementById('payments-count');
      if (bodyEl) {
        bodyEl.innerHTML = renderPayments(_jcData.payments);
        bindPaymentEditButtons(bodyEl);
      }
      if (count) count.textContent = _jcData.payments.length;
      closeModal();
      showToast(isEdit ? 'Payment updated.' : 'Payment added.', 'success');
      if (onDone) onDone();
    } catch (err) { errEl.textContent = err.message; errEl.classList.add('visible'); }
  }, { confirmLabel: isEdit ? 'Save Payment' : 'Add Payment', confirmClass: 'btn-primary' });

  setTimeout(() => {
    document.getElementById('pay-method')?.addEventListener('change', e => {
      document.getElementById('pay-eft-wrap').style.display = e.target.value === 'EFT' ? '' : 'none';
    });
  }, 50);
}

function renderPayments(payments) {
  if (!payments?.length) return `<div class="empty-state" style="padding:1.5rem"><p>No payments recorded</p></div>`;
  return `<div class="table-wrap"><table>
    <thead><tr>
      <th>Method</th><th>Amount</th><th>By</th><th>Date</th><th>Proof</th>
      ${_isAdmin ? '<th></th>' : ''}
    </tr></thead>
    <tbody>
      ${payments.map(p => `<tr>
        <td data-label="Method"><span class="badge badge-navy">${p.payment_method || '—'}</span></td>
        <td data-label="Amount"><strong>R ${(+p.amount || 0).toLocaleString()}</strong></td>
        <td data-label="By" style="color:var(--text-muted);font-size:.8rem">${p.username || '—'}</td>
        <td data-label="Date" style="color:var(--text-muted);font-size:.8rem">${(p.date_time || '').slice(0, 10)}</td>
        <td data-label="Proof">
          ${p.file
      ? `<a href="/uploads/payments/${p.file}" target="_blank"
                 style="font-size:.78rem;color:var(--primary)"
                 onclick="checkPaySlip(event,this,'${p.file}')">View ↗</a>`
      : '<span style="color:var(--text-muted);font-size:.78rem">—</span>'}
        </td>
        ${_isAdmin ? `<td data-label="">
          <button class="btn btn-ghost btn-sm pay-edit-btn"
            data-payment="${encodeURIComponent(JSON.stringify(p))}"
            style="font-size:.72rem">Edit</button>
        </td>` : ''}
      </tr>`).join('')}
    </tbody>
  </table></div>`;
}

function jcStatusBadge(s) {
  const map = { DRILLING: 'badge-drilling', ACTIVE: 'badge-active', PENDING: 'badge-pending', COMPLETE: 'badge-complete' };
  return `<span class="badge ${map[s] || 'badge-navy'}">${s || '—'}</span>`;
}

function typeBadge(type) {
  const cat = typeCategory(type);
  const colors = {
    Drilling: 'badge-drilling', Rieming: 'badge-navy', Casing: 'badge-orange',
    Blasting: 'badge-pending', Rods: 'badge-active', Other: 'badge-complete'
  };
  const label = type.replace(/_/g, ' ');
  return `<span class="badge ${colors[cat] || 'badge-complete'}">${label}</span>`;
}

function typeCategory(type) {
  for (const [cat, types] of Object.entries(TIMELINE_GROUPS)) {
    if (types.includes(type)) return cat;
  }
  return 'Other';
}

function formatTime(dt) {
  if (!dt) return '—';
  return dt.replace('T', ' ').slice(0, 16);
}

function dieselUsed(start, stop) {
  const s = parseFloat(start), e = parseFloat(stop);
  if (isNaN(s) || isNaN(e)) return '';
  return `${Math.abs(s - e)} L`;
}

function esc(v) {
  return (v || '').toString().replace(/"/g, '&quot;').replace(/</g, '&lt;');
}

function loader() {
  return `<div class="page-loader"><div class="spinner"></div><span>Loading jobcard…</span></div>`;
}

// ── Collapsible detail rows helper ───────────────────────────────────────
function collapsibleDetailRows(preview, extra, id) {
  const rowHtml = ([label, val]) => `
    <tr>
      <td style="padding:.55rem 1rem;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.07em;
                 color:var(--text-muted);white-space:nowrap;width:45%;border-bottom:1px solid var(--border-light)">${label}</td>
      <td style="padding:.55rem 1rem;font-size:.875rem;border-bottom:1px solid var(--border-light)">${val || '<span style="color:var(--text-light)">—</span>'}</td>
    </tr>`;

  const extraFilled = extra.filter(([, v]) => v);
  const hasExtra = extraFilled.length > 0;

  return `<table style="width:100%">
    ${preview.map(rowHtml).join('')}
    ${hasExtra ? `<tbody id="extra-${id}" style="display:none">${extraFilled.map(rowHtml).join('')}</tbody>` : ''}
  </table>
  ${hasExtra ? `<div style="padding:.45rem 1rem;border-top:1px solid var(--border-light)">
    <button class="btn btn-ghost btn-sm jc-expand-btn"
      data-id="${id}" data-count="${extraFilled.length}"
      style="font-size:.75rem;color:var(--primary)">
      Show more (${extraFilled.length}) ▼
    </button>
  </div>` : ''}`;
}