// Generic engine for a "browse one resource type across all patients" page
// (Conditions, Observations, Allergies, Medications, Encounters). Each page
// just defines window.RESOURCE_PAGE_CONFIG and includes this script — no
// per-page JS needed. See conditions.html for the config shape.

let rpPatientsCache = [];
let rpSearchTerm = '';
let rpAddModal, rpEditingRowId = null, rpEditingPatientId = null;

function rpEscapeHtml(str) {
  if (str === null || str === undefined) return '';
  return String(str)
    .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;').replace(/'/g, '&#39;');
}

function rpFmtDate(value) {
  if (!value) return '—';
  const d = new Date(value);
  if (isNaN(d)) return '—';
  return d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
}

function rpShowToast(message, variant = 'success') {
  const container = document.getElementById('toastContainer');
  if (!container) { alert(message); return; }
  const el = document.createElement('div');
  el.className = `toast align-items-center text-bg-${variant === 'danger' ? 'danger' : 'success'} border-0 show mb-2`;
  el.innerHTML = `<div class="d-flex"><div class="toast-body">${rpEscapeHtml(message)}</div>
    <button type="button" class="btn-close btn-close-white me-2 m-auto" onclick="this.closest('.toast').remove()"></button></div>`;
  container.appendChild(el);
  setTimeout(() => el.remove(), 5000);
}

function rpFieldInputHtml(field, value) {
  const id = `rp_field_${field.key}`;
  const val = value !== undefined && value !== null ? value : (field.default || '');

  if (field.type === 'select') {
    return `<div class="col-12">
      <label class="form-label small">${rpEscapeHtml(field.label)}</label>
      <select class="form-select" id="${id}">
        ${field.options.map(o => `<option value="${o}" ${o === val ? 'selected' : ''}>${o}</option>`).join('')}
      </select>
    </div>`;
  }

  if (field.type === 'checkbox') {
    const checked = value === true || value === 'true';
    return `<div class="col-12 form-check mt-1">
      <input type="checkbox" class="form-check-input" id="${id}" ${checked ? 'checked' : ''}>
      <label class="form-check-label small" for="${id}">${rpEscapeHtml(field.label)}</label>
    </div>`;
  }

  if (field.type === 'textarea') {
    return `<div class="col-12">
      <label class="form-label small">${rpEscapeHtml(field.label)}</label>
      <textarea ${field.required ? 'required' : ''} class="form-control" id="${id}" rows="2">${rpEscapeHtml(val)}</textarea>
    </div>`;
  }

  const inputVal = field.type === 'date' && val ? String(val).slice(0, 10)
    : field.type === 'datetime-local' && val ? String(val).slice(0, 16)
    : val;
  return `<div class="col-12">
    <label class="form-label small">${rpEscapeHtml(field.label)}</label>
    <input type="${field.type}" ${field.required ? 'required' : ''} class="form-control" id="${id}" value="${rpEscapeHtml(inputVal)}">
  </div>`;
}

async function rpLoadPatientsForPicker() {
  try {
    rpPatientsCache = await Api.getPatients();
    const select = document.getElementById('rp_patientSelect');
    if (select) {
      select.innerHTML = rpPatientsCache.map(p => `<option value="${p.id}">${rpEscapeHtml(p.fullName)} (${rpEscapeHtml(p.medicalRecordNumber)})</option>`).join('');
    }
  } catch { /* patient picker just won't populate; add flow will fail loudly instead */ }
}

function rpOpenAddModal() {
  rpEditingRowId = null;
  rpEditingPatientId = null;
  const config = window.RESOURCE_PAGE_CONFIG;
  document.getElementById('rp_modalTitle').textContent = `Add ${config.title.replace(/s$/, '')}`;
  document.getElementById('rp_patientPickerRow').classList.remove('d-none');
  document.getElementById('rp_fieldsBody').innerHTML = config.fields.map(f => rpFieldInputHtml(f, null)).join('');
  rpAddModal.show();
}

function rpOpenEditModal(row) {
  rpEditingRowId = row.id;
  rpEditingPatientId = row.patientId;
  const config = window.RESOURCE_PAGE_CONFIG;
  document.getElementById('rp_modalTitle').textContent = `Edit ${config.title.replace(/s$/, '')} — ${row.patientName}`;
  document.getElementById('rp_patientPickerRow').classList.add('d-none');
  document.getElementById('rp_fieldsBody').innerHTML = config.fields.map(f => rpFieldInputHtml(f, row[f.key])).join('');
  rpAddModal.show();
}

async function rpSubmitModal(e) {
  e.preventDefault();
  const config = window.RESOURCE_PAGE_CONFIG;
  const payload = {};
  for (const f of config.fields) {
    const el = document.getElementById(`rp_field_${f.key}`);
    let v;
    if (f.type === 'checkbox') {
      v = el.checked;
    } else {
      v = el.value;
      if (f.type === 'number') v = v === '' ? null : parseFloat(v);
      v = v === '' ? null : v;
    }
    payload[f.key] = v;
  }

  try {
    if (rpEditingRowId) {
      await config.update(rpEditingPatientId, rpEditingRowId, payload);
      rpShowToast(`${config.title} updated.`);
    } else {
      const patientId = document.getElementById('rp_patientSelect').value;
      if (!patientId) { rpShowToast('Select a patient first.', 'danger'); return; }
      await config.add(patientId, payload);
      rpShowToast(`${config.title} added.`);
    }
    rpAddModal.hide();
    await rpLoadGrid();
  } catch (err) {
    rpShowToast(err.message, 'danger');
  }
}

async function rpDeleteRow(row) {
  const config = window.RESOURCE_PAGE_CONFIG;
  if (!confirm(`Delete this ${config.title.replace(/s$/, '').toLowerCase()} for ${row.patientName}?`)) return;
  try {
    await config.remove(row.patientId, row.id);
    rpShowToast('Deleted.');
    await rpLoadGrid();
    // The row's Delete button lives inside the popup modal — refresh (or
    // close, if that was their last record) so it doesn't show stale data.
    const container = document.getElementById('rp_gridBody');
    const stillHasRows = (container._rpRows || []).some(r => r.patientId === row.patientId);
    if (stillHasRows) rpOpenViewModal(row.patientId);
    else if (rpViewModalInstance) rpViewModalInstance.hide();
  } catch (err) {
    rpShowToast(err.message, 'danger');
  }
}

// Bootstrap "bg-*" classes cycled per tile so patients are visually easy to
// tell apart at a glance — not tied to any data meaning, just variety.
const RP_TILE_COLORS = ['primary', 'success', 'info', 'warning', 'danger', 'secondary'];

// The pages ship a <table><thead>...<tbody id="rp_gridBody"> wrapper (from
// before this was a tile grid). Swap that whole table out for a plain grid
// div, once, so none of the 7 HTML pages that use this engine need editing.
function rpEnsureTileContainer() {
  const existing = document.getElementById('rp_gridBody');
  if (existing.tagName.toLowerCase() === 'div') return existing;
  const table = existing.closest('table');
  const div = document.createElement('div');
  div.id = 'rp_gridBody';
  div.className = 'rp-tile-grid';
  table.replaceWith(div);
  return div;
}

let rpViewModalInstance = null;

// The pages don't ship a "view details" modal in their HTML — build it once
// and reuse it, same approach as rpEnsureTileContainer above. Scrollable so
// patients with a lot of records don't blow out the page.
function rpEnsureViewModal() {
  let el = document.getElementById('rp_viewModal');
  if (el) return el;
  el = document.createElement('div');
  el.className = 'modal fade';
  el.id = 'rp_viewModal';
  el.tabIndex = -1;
  el.innerHTML = `
    <div class="modal-dialog modal-lg modal-dialog-scrollable">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="rp_viewModalTitle"></h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body p-0" id="rp_viewModalBody"></div>
      </div>
    </div>`;
  document.body.appendChild(el);
  rpViewModalInstance = new bootstrap.Modal(el);
  return el;
}

function rpOpenViewModal(patientId) {
  const config = window.RESOURCE_PAGE_CONFIG;
  const container = document.getElementById('rp_gridBody');
  const rows = (container._rpRows || []).filter(r => r.patientId === patientId);
  if (rows.length === 0) return;

  rpEnsureViewModal();
  document.getElementById('rp_viewModalTitle').textContent = rows[0].patientName;

  const detailColumns = config.columns.filter(c => c.key !== 'patientName');
  const detailRows = rows.map(row => {
    const cells = detailColumns.map(c => {
      if (c.render) return `<td>${c.render(row[c.key], row)}</td>`;
      let v = row[c.key];
      v = c.type === 'date' ? rpFmtDate(v) : rpEscapeHtml(v ?? '—');
      return `<td>${v}</td>`;
    }).join('');
    const actions = config.readOnly ? '' : `
      <td class="text-end">
        <button class="btn btn-sm btn-outline-secondary me-1" data-edit-row="${row.id}" data-edit-patient="${row.patientId}">Edit</button>
        <button class="btn btn-sm btn-outline-danger" data-delete-row="${row.id}" data-delete-patient="${row.patientId}">Delete</button>
      </td>`;
    return `<tr data-row-id="${row.id}" data-row-patient="${row.patientId}">${cells}${actions}</tr>`;
  }).join('');

  document.getElementById('rp_viewModalBody').innerHTML = `
    <div style="max-height:60vh;overflow-y:auto">
      <table class="table table-sm resource-grid-table align-middle mb-0">
        <thead><tr>${detailColumns.map(c => `<th>${rpEscapeHtml(c.label)}</th>`).join('')}${config.readOnly ? '' : '<th></th>'}</tr></thead>
        <tbody>${detailRows}</tbody>
      </table>
    </div>`;

  rpViewModalInstance.show();
}

async function rpLoadGrid() {
  const config = window.RESOURCE_PAGE_CONFIG;
  const container = rpEnsureTileContainer();
  const empty = document.getElementById('rp_gridEmpty');
  const countLabel = document.getElementById('rp_countLabel');

  try {
    const rows = await config.listAll(rpSearchTerm.trim());
    const patientCount = new Set(rows.map(r => r.patientId)).size;
    if (countLabel) countLabel.textContent = `${rows.length} record${rows.length === 1 ? '' : 's'} · ${patientCount} patient${patientCount === 1 ? '' : 's'}`;

    if (rows.length === 0) {
      container.innerHTML = '';
      empty.classList.remove('d-none');
      return;
    }
    empty.classList.add('d-none');

    const groups = new Map();
    rows.forEach(r => {
      if (!groups.has(r.patientId)) groups.set(r.patientId, { patientId: r.patientId, patientName: r.patientName, items: [] });
      groups.get(r.patientId).items.push(r);
    });

    container.innerHTML = [...groups.values()].map((g, i) => {
      const color = RP_TILE_COLORS[i % RP_TILE_COLORS.length];
      const initials = g.patientName.split(' ').map(n => n[0]).slice(0, 2).join('').toUpperCase();

      return `
        <div class="card shadow-sm border-0" style="cursor:pointer" data-view-patient="${g.patientId}">
          <div class="card-body text-center py-3">
            <div class="rounded-circle bg-${color} text-white d-inline-flex align-items-center justify-content-center mb-2" style="width:44px;height:44px;font-size:14px" aria-hidden="true">${rpEscapeHtml(initials)}</div>
            <div class="fw-semibold small">${rpEscapeHtml(g.patientName)}</div>
            <span class="badge bg-${color}-subtle text-${color}-emphasis rounded-pill mt-1">${g.items.length} record${g.items.length === 1 ? '' : 's'}</span>
            <div class="mt-2">
              <button type="button" class="btn btn-sm btn-outline-${color}" data-view-patient="${g.patientId}">View</button>
            </div>
          </div>
        </div>`;
    }).join('');

    // Stash rows for the View/Edit/Delete handlers (avoids a second fetch per click).
    container._rpRows = rows;

    // Lets a page compute something from the freshly-loaded rows (e.g. an
    // "X% actioned" stat) without the generic engine needing to know about
    // page-specific fields like "Actioned".
    if (typeof config.afterLoad === 'function') config.afterLoad(rows);
  } catch (err) {
    rpShowToast(err.message, 'danger');
  }
}

function rpInit() {
  const config = window.RESOURCE_PAGE_CONFIG;
  if (!config) return;

  if (!sessionStorage.getItem('cip_token')) {
    window.location.href = 'login.html';
    return;
  }

  renderSidebar(config.key);

  document.getElementById('rp_pageIcon').textContent = config.icon;
  document.getElementById('rp_pageTitle').textContent = config.title;
  document.title = `${config.title} — Clinical Insight Pro`;
  document.getElementById('clinicianLabel').textContent = `👤 ${sessionStorage.getItem('cip_clinician') || 'Clinician'}`;

  document.getElementById('logoutBtn').addEventListener('click', () => {
    sessionStorage.clear();
    window.location.href = 'login.html';
  });

  if (config.readOnly) {
    document.getElementById('rp_addBtn').classList.add('d-none');
  }

  // "View" opens a scrollable popup with that patient's records, instead of
  // expanding inline (which used to push the rest of the grid down). Works
  // on every page, including read-only ones (Risk Assessment, Care Plans).
  rpEnsureTileContainer().addEventListener('click', (e) => {
    const viewEl = e.target.closest('[data-view-patient]');
    if (!viewEl) return;
    rpOpenViewModal(viewEl.dataset.viewPatient);
  });

  if (!config.readOnly) {
    rpAddModal = new bootstrap.Modal(document.getElementById('rp_modal'));
    document.getElementById('rp_addBtn').addEventListener('click', rpOpenAddModal);
    document.getElementById('rp_form').addEventListener('submit', rpSubmitModal);
    rpLoadPatientsForPicker();

    rpEnsureViewModal().addEventListener('click', (e) => {
      const editBtn = e.target.closest('[data-edit-row]');
      const delBtn = e.target.closest('[data-delete-row]');
      const tbody = document.getElementById('rp_gridBody');
      if (editBtn) {
        const row = (tbody._rpRows || []).find(r => String(r.id) === editBtn.dataset.editRow && r.patientId === editBtn.dataset.editPatient);
        if (row) { rpViewModalInstance.hide(); rpOpenEditModal(row); }
      } else if (delBtn) {
        const row = (tbody._rpRows || []).find(r => String(r.id) === delBtn.dataset.deleteRow && r.patientId === delBtn.dataset.deletePatient);
        if (row) rpDeleteRow(row);
      }
    });
  }

  document.getElementById('rp_searchInput').addEventListener('input', (e) => {
    rpSearchTerm = e.target.value;
    rpLoadGrid();
  });

  rpLoadGrid();
}

document.addEventListener('DOMContentLoaded', rpInit);
