<?php
// admin/guests_edit.php — Inline editable guest list with AJAX multi-update
require_once __DIR__ . '/../config.php';
adminGuard();
requireCsrf();  // reject POSTs without a valid CSRF token
require_once __DIR__ . '/_layout.php';

$db      = db();
$adminId = (int)$_SESSION['admin_id'];
$eventId = (int)($_GET['event_id'] ?? $_POST['event_id'] ?? 0);
$msg = $error = '';

// Load event
$evStmt = $db->prepare('SELECT * FROM events WHERE id=? AND admin_id=?');
$evStmt->execute([$eventId, $adminId]);
$event = $evStmt->fetch();
if (!$event) { header('Location: ' . BASE_URL . '/admin/guests.php'); exit; }

// ── AJAX: update single guest field ──────────────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SERVER['HTTP_X_GUEST_UPDATE'])) {
    $body    = json_decode(file_get_contents('php://input'), true) ?? [];
    $guestId = (int)($body['guest_id'] ?? 0);
    $field   = $body['field']  ?? '';
    $value   = trim($body['value'] ?? '');

    $allowed = ['name','email','phone','table_number','seat_number','category'];
    if (!$guestId || !in_array($field, $allowed)) {
        jsonOut(['ok'=>false,'error'=>'Invalid field'], 400);
    }

    // Verify guest belongs to this admin's event
    $chk = $db->prepare('SELECT g.id FROM guests g JOIN events e ON e.id=g.event_id WHERE g.id=? AND e.admin_id=?');
    $chk->execute([$guestId, $adminId]);
    if (!$chk->fetch()) jsonOut(['ok'=>false,'error'=>'Not found'], 404);

    $db->prepare("UPDATE guests SET {$field}=? WHERE id=?")->execute([$value ?: null, $guestId]);
    jsonOut(['ok'=>true, 'value'=>$value]);
}

// ── AJAX: bulk update (POST JSON array) ──────────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SERVER['HTTP_X_BULK_UPDATE'])) {
    $body    = json_decode(file_get_contents('php://input'), true) ?? [];
    $updates = $body['updates'] ?? [];
    $allowed = ['name','email','phone','table_number','seat_number','category'];
    $count   = 0;
    foreach ($updates as $upd) {
        $guestId = (int)($upd['guest_id'] ?? 0);
        $field   = $upd['field']  ?? '';
        $value   = trim($upd['value'] ?? '');
        if (!$guestId || !in_array($field, $allowed)) continue;
        $chk = $db->prepare('SELECT g.id FROM guests g JOIN events e ON e.id=g.event_id WHERE g.id=? AND e.admin_id=?');
        $chk->execute([$guestId, $adminId]);
        if (!$chk->fetch()) continue;
        $db->prepare("UPDATE guests SET {$field}=? WHERE id=?")->execute([$value ?: null, $guestId]);
        $count++;
    }
    jsonOut(['ok'=>true, 'updated'=>$count]);
}

// ── AJAX: delete guest ────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SERVER['HTTP_X_DELETE_GUEST'])) {
    $body    = json_decode(file_get_contents('php://input'), true) ?? [];
    $guestId = (int)($body['guest_id'] ?? 0);
    $chk     = $db->prepare('SELECT g.id FROM guests g JOIN events e ON e.id=g.event_id WHERE g.id=? AND e.admin_id=?');
    $chk->execute([$guestId, $adminId]);
    if (!$chk->fetch()) jsonOut(['ok'=>false], 404);
    $db->prepare('DELETE FROM guests WHERE id=?')->execute([$guestId]);
    jsonOut(['ok'=>true]);
}

// ── Load guests with filters ──────────────────────────────────
$search  = trim($_GET['q'] ?? '');
$perPage = max(10, min(100, (int)($_GET['per'] ?? 25)));
$page    = max(1, (int)($_GET['page'] ?? 1));

$where  = 'WHERE g.event_id=?'; $params = [$eventId];
if ($search) {
    $where  .= ' AND (g.name LIKE ? OR g.email LIKE ? OR g.phone LIKE ?)';
    $params[] = "%{$search}%"; $params[] = "%{$search}%"; $params[] = "%{$search}%";
}

$cntStmt = $db->prepare("SELECT COUNT(*) FROM guests g {$where}");
$cntStmt->execute($params);
$totalCount = (int)$cntStmt->fetchColumn();
$totalPages = max(1, (int)ceil($totalCount / $perPage));
$page       = min($page, $totalPages);
$offset     = ($page - 1) * $perPage;

$gStmt = $db->prepare("SELECT g.* FROM guests g {$where} ORDER BY g.name ASC LIMIT {$perPage} OFFSET {$offset}");
$gStmt->execute($params);
$guests = $gStmt->fetchAll();

$editableFields = [
    'name'         => ['label'=>'Name',       'type'=>'text',  'required'=>true],
    'email'        => ['label'=>'Email',       'type'=>'email', 'required'=>false],
    'phone'        => ['label'=>'Phone',       'type'=>'text',  'required'=>false],
    'table_number' => ['label'=>'Table',       'type'=>'text',  'required'=>false],
    'seat_number'  => ['label'=>'Seat',        'type'=>'text',  'required'=>false],
    'category'     => ['label'=>'Category',    'type'=>'text',  'required'=>false],
];

layout_start('Edit Guests — ' . $event['title'], 'guests');
?>

<style>
.edit-cell {
  position: relative; cursor: pointer;
  padding: 4px 6px; border-radius: 4px;
  transition: background .15s; min-width: 60px;
}
.edit-cell:hover { background: var(--surface-2); }
.edit-cell.editing { background: transparent; }
.edit-cell input, .edit-cell select {
  background: var(--surface-2); border: 1px solid var(--gold-dim);
  border-radius: 4px; color: var(--white); padding: 4px 8px;
  font-family: var(--font-body); font-size: .85rem;
  width: 100%; min-width: 80px; outline: none;
}
.edit-cell input:focus { border-color: var(--gold); }
.edit-cell .save-indicator {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  font-size: .65rem; pointer-events: none;
}
.cell-saving  .save-indicator::after { content: '⏳'; }
.cell-saved   .save-indicator::after { content: '✓'; color: var(--success); }
.cell-error   .save-indicator::after { content: '✕'; color: var(--danger); }
tr.modified { background: rgba(197,158,89,.04) !important; }
tr.modified td:first-child::before {
  content: '●'; color: var(--gold); font-size: .6rem;
  position: absolute; left: 6px; top: 50%; transform: translateY(-50%);
}
tr.modified td:first-child { position: relative; padding-left: 18px; }
#bulk-save-bar {
  position: sticky; top: 0; z-index: 200;
  background: rgba(197,158,89,.12); border: 1px solid var(--gold-dim);
  border-radius: var(--radius); padding: 10px 16px;
  display: none; align-items: center; gap: 12px; margin-bottom: 12px;
}
#bulk-save-bar.visible { display: flex; }
</style>

<div class="page-header">
  <div>
    <div class="page-header-sub">
      <a href="<?= BASE_URL ?>/admin/guests.php?event_id=<?= $eventId ?>" style="color:var(--muted);text-decoration:none">← Guest List</a>
      <span style="margin:0 6px;color:var(--border)">›</span>
      <?= htmlspecialchars($event['title']) ?>
    </div>
    <h1>Edit Guests</h1>
  </div>
  <div class="flex gap-2">
    <span class="badge badge-info text-sm" style="padding:6px 12px">
      Click any cell to edit · saves automatically
    </span>
  </div>
</div>

<!-- Search -->
<form method="GET" data-no-loader style="display:flex;gap:8px;margin-bottom:20px">
  <input type="hidden" name="event_id" value="<?= $eventId ?>">
  <input class="form-control" type="text" name="q" value="<?= htmlspecialchars($search) ?>"
         placeholder="Search name, email, phone…" style="max-width:300px">
  <select class="form-control" name="per" style="width:100px" onchange="this.form.submit()">
    <?php foreach ([25,50,100] as $n): ?>
      <option value="<?= $n ?>" <?= $n===$perPage?'selected':'' ?>><?= $n ?>/page</option>
    <?php endforeach; ?>
  </select>
  <button class="btn btn-outline" type="submit">Search</button>
  <?php if ($search): ?><a href="?event_id=<?= $eventId ?>" class="btn btn-outline">Clear</a><?php endif; ?>
</form>

<div class="card">
  <div class="card-header">
    <span class="card-title">
      <?= $search ? 'Search Results' : 'All Guests' ?>
      <span class="badge badge-muted" style="margin-left:6px"><?= $totalCount ?></span>
    </span>
    <div class="text-muted text-sm">Page <?= $page ?> of <?= $totalPages ?> · <?= $totalCount ?> guests</div>
  </div>

  <div class="table-wrap" style="overflow-x:auto">
    <table id="guests-table" style="min-width:900px">
      <thead>
        <tr>
          <th style="width:28px">#</th>
          <?php foreach ($editableFields as $f => $cfg): ?>
            <th><?= $cfg['label'] ?></th>
          <?php endforeach; ?>
          <th>Check-in</th>
          <th style="width:80px">Actions</th>
        </tr>
      </thead>
      <tbody>
        <?php if (empty($guests)): ?>
          <tr><td colspan="<?= count($editableFields)+3 ?>" class="text-muted" style="padding:32px;text-align:center">No guests found.</td></tr>
        <?php endif; ?>
        <?php foreach ($guests as $i => $g): ?>
        <tr id="grow-<?= $g['id'] ?>" data-guest-id="<?= $g['id'] ?>">
          <td class="text-muted text-sm"><?= ($page-1)*$perPage + $i + 1 ?></td>
          <?php foreach ($editableFields as $field => $cfg): ?>
          <td>
            <div class="edit-cell" data-field="<?= $field ?>" data-guest-id="<?= $g['id'] ?>"
                 data-original="<?= htmlspecialchars($g[$field] ?? '') ?>"
                 onclick="startEdit(this)">
              <span class="cell-display"><?= htmlspecialchars($g[$field] ?? '') ?: '<span class="text-muted" style="font-size:.8rem">—</span>' ?></span>
              <span class="save-indicator"></span>
            </div>
          </td>
          <?php endforeach; ?>
          <td>
            <?php if ($g['checked_in']): ?>
              <span class="badge badge-success">✓ In</span>
              <div class="text-muted" style="font-size:.65rem"><?= date('H:i M j', strtotime($g['check_in_time'])) ?></div>
            <?php else: ?>
              <span class="badge badge-muted">Pending</span>
            <?php endif; ?>
          </td>
          <td>
            <button class="btn btn-danger btn-sm" onclick="deleteGuest(<?= $g['id'] ?>, this)"
                    title="Remove guest">✕</button>
          </td>
        </tr>
        <?php endforeach; ?>
      </tbody>
    </table>
  </div>

  <!-- Pagination -->
  <?php if ($totalPages > 1): ?>
  <div style="padding:16px 14px;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px">
    <div class="text-muted text-sm">
      Showing <?= ($page-1)*$perPage+1 ?>–<?= min($page*$perPage,$totalCount) ?> of <?= $totalCount ?>
    </div>
    <div style="display:flex;gap:6px">
      <?php if ($page>1): ?>
        <a href="?event_id=<?= $eventId ?>&q=<?= urlencode($search) ?>&per=<?= $perPage ?>&page=<?= $page-1 ?>" class="btn btn-outline btn-sm">‹</a>
      <?php endif; ?>
      <?php for ($p=max(1,$page-2);$p<=min($totalPages,$page+2);$p++): ?>
        <a href="?event_id=<?= $eventId ?>&q=<?= urlencode($search) ?>&per=<?= $perPage ?>&page=<?= $p ?>"
           class="btn <?= $p===$page?'btn-gold':'btn-outline' ?> btn-sm"><?= $p ?></a>
      <?php endfor; ?>
      <?php if ($page<$totalPages): ?>
        <a href="?event_id=<?= $eventId ?>&q=<?= urlencode($search) ?>&per=<?= $perPage ?>&page=<?= $page+1 ?>" class="btn btn-outline btn-sm">›</a>
      <?php endif; ?>
    </div>
  </div>
  <?php endif; ?>
</div>

<script>
const BASE_URL  = '<?= BASE_URL ?>';
const EVENT_ID  = <?= (int)$eventId ?>;
const PAGE_URL  = window.location.pathname + '?event_id=' + EVENT_ID;
let pendingChanges = {}; // {guestId_field: {guest_id, field, value}}
let activeInput = null;

// ── Inline editing ────────────────────────────────────────────
function startEdit(cell) {
  if (cell.classList.contains('editing')) return;
  if (activeInput) finishEdit(activeInput.closest('.edit-cell'), true);

  const field    = cell.dataset.field;
  const guestId  = cell.dataset.guestId;
  const current  = cell.querySelector('.cell-display').textContent.trim();
  const original = cell.dataset.original;

  cell.classList.add('editing');
  const input = document.createElement('input');
  input.type  = 'text';
  input.value = original;
  input.dataset.original = original;
  cell.querySelector('.cell-display').style.display = 'none';
  cell.insertBefore(input, cell.querySelector('.save-indicator'));
  input.focus(); input.select();
  activeInput = input;

  input.addEventListener('keydown', e => {
    if (e.key === 'Enter') { e.preventDefault(); finishEdit(cell, true); }
    if (e.key === 'Escape') { finishEdit(cell, false); }
    if (e.key === 'Tab') {
      e.preventDefault(); finishEdit(cell, true);
      // Move to next cell in same column or next row
      const row   = cell.closest('tr');
      const cells = [...row.querySelectorAll('.edit-cell')];
      const idx   = cells.indexOf(cell);
      const next  = e.shiftKey ? cells[idx-1] : cells[idx+1];
      if (next) next.click();
    }
  });
  input.addEventListener('blur', () => { if (activeInput === input) finishEdit(cell, true); });
}

function finishEdit(cell, save) {
  if (!cell.classList.contains('editing')) return;
  const input   = cell.querySelector('input');
  if (!input) return;
  const value    = input.value.trim();
  const original = cell.dataset.original;
  const field    = cell.dataset.field;
  const guestId  = cell.dataset.guestId;
  const display  = cell.querySelector('.cell-display');

  input.remove();
  display.style.display = '';
  cell.classList.remove('editing');
  activeInput = null;

  if (!save) return; // Escape — revert

  display.innerHTML = value || '<span class="text-muted" style="font-size:.8rem">—</span>';

  if (value === original) return; // No change

  // Track in-flight change (cleared on save success; powers the unsaved-exit guard)
  const key = guestId + '_' + field;
  pendingChanges[key] = { guest_id: parseInt(guestId), field, value };
  cell.dataset.original = value;
  cell.closest('tr').classList.add('modified');

  // Auto-save single field immediately
  saveSingleCell(cell, guestId, field, value);
}

function saveSingleCell(cell, guestId, field, value) {
  cell.classList.add('cell-saving');
  fetch(PAGE_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'X-Guest-Update': '1' },
    body: JSON.stringify({ guest_id: parseInt(guestId), field, value })
  })
  .then(r => r.json())
  .then(d => {
    cell.classList.remove('cell-saving');
    cell.classList.add(d.ok ? 'cell-saved' : 'cell-error');
    if (d.ok) {
      const key = guestId + '_' + field;
      delete pendingChanges[key];
      updateBulkBar();
      // Remove modified class if no more pending for this row
      const row = cell.closest('tr');
      const stillPending = Object.keys(pendingChanges).some(k => k.startsWith(guestId + '_'));
      if (!stillPending) row.classList.remove('modified');
    }
    setTimeout(() => { cell.classList.remove('cell-saved','cell-error'); }, 2000);
  })
  .catch(() => { cell.classList.remove('cell-saving'); cell.classList.add('cell-error'); });
}

// ── Bulk save ─────────────────────────────────────────────────
function saveBulk() {
  const updates = Object.values(pendingChanges);
  if (!updates.length) return;
  showPageLoader('Saving ' + updates.length + ' changes…');
  fetch(PAGE_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'X-Bulk-Update': '1' },
    body: JSON.stringify({ updates })
  })
  .then(r => r.json())
  .then(d => {
    hidePageLoader();
    if (d.ok) {
      pendingChanges = {};
      document.querySelectorAll('tr.modified').forEach(r => r.classList.remove('modified'));
      updateBulkBar();
      showToast('Saved ' + d.updated + ' changes.', 'success');
    } else {
      showToast('Save failed. Try again.', 'error');
    }
  })
  .catch(() => { hidePageLoader(); showToast('Network error.', 'error'); });
}

function discardChanges() {
  location.reload();
}

function updateBulkBar() { /* bulk bar removed — auto-save per cell is the single model */ }

// ── Delete guest ──────────────────────────────────────────────
async function deleteGuest(guestId, btn) {
  const ok = window.uiConfirm
    ? await uiConfirm({ title: 'Remove this guest?', message: 'This cannot be undone.', confirmText: 'Remove', danger: true })
    : confirm('Remove this guest? This cannot be undone.');
  if (!ok) return;
  btnLoading(btn);
  fetch(PAGE_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'X-Delete-Guest': '1' },
    body: JSON.stringify({ guest_id: guestId })
  })
  .then(r => r.json())
  .then(d => {
    if (d.ok) {
      document.getElementById('grow-' + guestId)?.remove();
      showToast('Guest removed.', 'success');
    } else {
      btnReset(btn);
      showToast('Could not remove guest.', 'error');
    }
  })
  .catch(() => { btnReset(btn); });
}

// Warn before navigating away with unsaved changes
window.addEventListener('beforeunload', e => {
  if (Object.keys(pendingChanges).length > 0) {
    e.preventDefault();
    e.returnValue = '';
  }
});
</script>

<?php layout_end(); ?>
