<?php
if (session_status() !== PHP_SESSION_ACTIVE) { session_start(); }
require_once __DIR__ . '/config.php';
if (!isset($conn) || !($conn instanceof PDO)) {
  http_response_code(500);
  header('Content-Type: application/json');
  echo json_encode(['ok'=>false, 'error'=>'DB connection not available']);
  exit;
}
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// ----- JSON APIs (respond before HTML) -----
function jerr($m,$c=200){ http_response_code($c); header('Content-Type: application/json'); echo json_encode(['ok'=>false,'error'=>$m]); exit; }
function jok($d=null){ header('Content-Type: application/json'); echo json_encode(['ok'=>true,'data'=>$d]); exit; }
function clean_status($s){ $i=(int)$s; return in_array($i,[0,1,2,3],true)?$i:0; }

if (isset($_GET['api'])) {
  $api = $_GET['api'];

  if ($api === 'list') {
    try {
      $q = $conn->query("SELECT id,email,ticketno,subject,type,priority,message,status,AdminRemark,`Date` FROM crmticket ORDER BY `Date` DESC, id DESC");
      jok($q->fetchAll(PDO::FETCH_ASSOC));
    } catch (Throwable $e) { jerr('List failed: '.$e->getMessage()); }
  }

  if ($api === 'set_status') {
    $raw = file_get_contents('php://input');
    $js  = json_decode($raw,true);
    if (!is_array($js)) jerr('Invalid JSON payload');
    $id = isset($js['id'])?(int)$js['id']:0;
    $st = clean_status($js['status'] ?? 0);
    if ($id<=0) jerr('Invalid ticket id');
    try {
      $u = $conn->prepare("UPDATE crmticket SET status=:s WHERE id=:i");
      $u->execute([':s'=>$st, ':i'=>$id]);
      $s = $conn->prepare("SELECT id,email,ticketno,subject,type,priority,message,status,AdminRemark,`Date` FROM crmticket WHERE id=:i");
      $s->execute([':i'=>$id]);
      $row = $s->fetch(PDO::FETCH_ASSOC);
      if (!$row) jerr('Ticket not found after update');
      jok($row);
    } catch (Throwable $e) { jerr('Update failed: '.$e->getMessage()); }
  }

  // Optional: single view endpoint (not required for modal, but supported)
  if ($api === 'view') {
    $id = (int)($_GET['id'] ?? 0);
    if ($id<=0) jerr('Invalid ticket id');
    try {
      $s = $conn->prepare("SELECT id,email,ticketno,subject,type,priority,message,status,AdminRemark,`Date` FROM crmticket WHERE id=:i");
      $s->execute([':i'=>$id]);
      $row = $s->fetch(PDO::FETCH_ASSOC);
      if (!$row) jerr('Ticket not found',404);
      jok($row);
    } catch (Throwable $e) { jerr('View failed: '.$e->getMessage()); }
  }

  jerr('Unknown API');
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Tickets</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <script src="https://cdn.tailwindcss.com"></script>
  <style>
    .btn-sm{ padding:.25rem .5rem; font-size:.75rem; line-height:1rem; border-radius:.375rem; }
    .badge{ padding:.15rem .5rem; font-size:.7rem; border-radius:9999px; font-weight:700; display:inline-block; }
    .badge-pr-low{ background:#dcfce7; color:#166534; }
    .badge-pr-medium{ background:#fef9c3; color:#854d0e; }
    .badge-pr-high{ background:#fee2e2; color:#991b1b; }
    .badge-st-open{ background:#dbeafe; color:#1e40af; }
    .badge-st-closed{ background:#e5e7eb; color:#111827; }
    .badge-st-progress{ background:#cffafe; color:#155e75; }
    .badge-st-resolved{ background:#dcfce7; color:#166534; }
    /* Overlay */
.modal-overlay{
  position:fixed;margin-top:30px; inset:0; background:rgba(0,0,0,.45);
  display:none; align-items:center; justify-content:center; z-index:50;
  padding:16px;                 /* gutter on small screens */
  overscroll-behavior:contain;  /* block background scroll chaining */
}

/* Card uses GRID: header | body | footer */
.modal-card{
  width:min(92vw, 640px);
  max-height:92vh;              /* cap by viewport */
  background:#fff;
  border-radius:12px;
  box-shadow:0 15px 30px rgba(0,0,0,.2);

  display:grid;
  grid-template-rows:auto 1fr auto;   /* header, scrollable body, footer */
  overflow:hidden;                    /* clip inner scroll only to body */
}

/* Header & footer stick at edges of the scroll container */
.modal-header{
  border-bottom:1px solid #e5e7eb;
  position:sticky; top:0; z-index:1; background:#fff;
}
.modal-footer{
  border-top:1px solid #e5e7eb;
  position:sticky; bottom:0; z-index:1; background:#fff;
}

/* Only BODY scrolls */
.modal-body{
  overflow:auto;
  -webkit-overflow-scrolling:touch;
  min-height:0;    /* prevents flex/grid overflow issues */
}

/* Optional: make long <pre> wrap nicely */
.modal-body pre{
  white-space:pre-wrap; word-break:break-word;
}
 </style>
</head>
<body class="bg-gray-100">
<?php include "header.php"; ?>

<div class="flex flex-col md:flex-row min-h-screen">
  <div class="min-h-screen bg-gray-100 md:pl-64">
    <?php if (file_exists(__DIR__ . '/side_bar.php')) include "side_bar.php"; ?>

    <main class="px-4 sm:px-6 py-6">
      <div class="container mx-auto bg-white p-4 md:p-6 shadow-lg rounded-lg">
        <div class="flex items-center justify-between mb-4">
          <h2 class="text-xl md:text-2xl font-bold text-gray-700">Tickets</h2>
        </div>

        <div class="overflow-x-auto">
          <table class="min-w-full border-collapse border border-gray-200">
            <thead class="bg-[#CD7F32] text-white">
              <tr>
                <th class="p-2 md:p-3 border text-left text-sm md:text-base">#</th>
                <th class="p-2 md:p-3 border text-left text-sm md:text-base">Ticket No</th>
                <th class="p-2 md:p-3 border text-left text-sm md:text-base">Subject</th>
                <th class="p-2 md:p-3 border text-left text-sm md:text-base">Type</th>
                <th class="p-2 md:p-3 border text-left text-sm md:text-base">Priority</th>
                <th class="p-2 md:p-3 border text-left text-sm md:text-base">Status</th>
                <th class="p-2 md:p-3 border text-left text-sm md:text-base">Email</th>
                <th class="p-2 md:p-3 border text-left text-sm md:text-base">Created</th>
                <th class="p-2 md:p-3 border text-left text-sm md:text-base">Action</th>
              </tr>
            </thead>
            <tbody id="tickets-body">
              <tr><td class="p-3 border text-center text-gray-500" colspan="9">Loading…</td></tr>
            </tbody>
          </table>
        </div>
      </div>
    </main>
  </div>
</div>

<?php include "footer.php"; ?>

<!-- View Modal -->
<!-- View Modal -->
<div id="viewModal" class="modal-overlay" aria-hidden="true">
  <div class="modal-card relative" role="dialog" aria-modal="true" aria-labelledby="vm-title">

    <!-- Header (sticky) -->
    <div class="modal-header p-5 md:p-6 flex items-start justify-between">
      <div>
        <div class="text-xs uppercase text-gray-500 tracking-wider">Ticket</div>
        <h3 id="vm-title" class="text-xl font-semibold text-gray-800">—</h3>
        <div class="flex items-center gap-2 mt-1">
          <span id="vm-status" class="badge badge-st-open">Open</span>
          <button id="vm-copy" class="btn-sm bg-gray-800 text-white hover:bg-black" type="button">Copy Ticket No</button>
        </div>
      </div>
      <button id="vm-close" class="btn-sm bg-gray-200 hover:bg-gray-300 text-gray-800" aria-label="Close">✕</button>
    </div>

    <!-- Body (the ONLY scroll area) -->
    <div class="modal-body p-5 md:p-6">
      <!-- 🔽 keep your existing fields exactly as-is 🔽 -->
      <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
        <div>
          <div class="text-xs text-gray-500">Ticket No</div>
          <div id="vm-ticketno" class="font-medium text-gray-800 break-all">—</div>
        </div>
        <div>
          <div class="text-xs text-gray-500">Created</div>
          <div id="vm-date" class="font-medium text-gray-800">—</div>
        </div>
        <div>
          <div class="text-xs text-gray-500">Type</div>
          <div id="vm-type" class="font-medium text-gray-800">—</div>
        </div>
        <div>
          <div class="text-xs text-gray-500">Priority</div>
          <div id="vm-priority" class="font-medium text-gray-800">—</div>
        </div>
        <div class="md:col-span-2">
          <div class="text-xs text-gray-500">Email</div>
          <div id="vm-email" class="font-medium text-gray-800 break-all">—</div>
        </div>
      </div>

      <div class="mb-4">
        <div class="text-xs text-gray-500 mb-1">Subject</div>
        <div id="vm-subject" class="p-3 rounded-md bg-gray-50 border text-gray-800">—</div>
      </div>

      <div class="mb-4">
        <div class="text-xs text-gray-500 mb-1">Message</div>
        <pre id="vm-message" class="p-3 rounded-md bg-gray-50 border text-gray-800">—</pre>
      </div>

      <div>
        <div class="text-xs text-gray-500 mb-1">Admin Remark</div>
        <pre id="vm-remark" class="p-3 rounded-md bg-amber-50 border border-amber-200 text-gray-800">—</pre>
      </div>
    </div>

    <!-- Footer (sticky) -->
    <div class="modal-footer p-5 md:p-6 flex items-center justify-end gap-2">
      <!-- If you have a submit/save action, keep it here so it’s always visible -->
       <!--<button class="btn-sm bg-[#CD7F32] text-white hover:opacity-90" type="button">Submit</button> -->
      <button id="vm-close2" class="btn-sm bg-gray-200 hover:bg-gray-300 text-gray-800" type="button">Close</button>
    </div>

  </div>
</div>

<script>
let TICKETS = [];
let VIEW = null;

// ---------- helpers ----------
function escapeHtml(s){ return (s ?? '').toString().replace(/[&<>"']/g, m => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m])); }
function fmtDate(dt){
  if (!dt) return '-';
  const d = new Date(dt.replace(' ', 'T'));
  if (isNaN(d)) return dt;
  const pad = n => String(n).padStart(2,'0');
  return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
}
function badgePriority(p){
  const v = (p||'').toLowerCase();
  if (v==='high')   return '<span class="badge badge-pr-high">High</span>';
  if (v==='low')    return '<span class="badge badge-pr-low">Low</span>';
  return '<span class="badge badge-pr-medium">Medium</span>';
}
function badgeStatusInt(s){
  const i = parseInt(s,10);
  if (i===1) return '<span class="badge badge-st-closed">Closed</span>';
  if (i===2) return '<span class="badge badge-st-progress">In&nbsp;Progress</span>';
  if (i===3) return '<span class="badge badge-st-resolved">Resolved</span>';
  return '<span class="badge badge-st-open">Open</span>';
}
function nextToggleStatusInt(cur){ return (parseInt(cur,10)===0)?1:0; }

// ---------- data load ----------
async function loadList(){
  try {
    const r = await fetch('?api=list', {cache:'no-store'});
    const j = await r.json();
    if (!j.ok) { renderEmpty('Failed to load'); return; }
    TICKETS = j.data || [];
    renderTable();
  } catch (e) { renderEmpty('Network error while loading.'); }
}

function renderEmpty(msg){
  document.getElementById('tickets-body').innerHTML =
    `<tr><td class="p-3 border text-center text-gray-500" colspan="9">${escapeHtml(msg||'No tickets found.')}</td></tr>`;
}

function renderTable(){
  const tb = document.getElementById('tickets-body');
  tb.innerHTML = '';
  if (!TICKETS.length) { renderEmpty('No tickets found.'); return; }

  TICKETS.forEach((t, idx) => {
    const tr = document.createElement('tr');
    tr.className = 'hover:bg-gray-50';
    const nextSt = nextToggleStatusInt(t.status);
    const btnLabel = nextSt === 1 ? 'Close' : 'Reopen';
    const btnColor = nextSt === 1 ? 'bg-red-500 hover:bg-red-600' : 'bg-green-500 hover:bg-green-600';

    tr.innerHTML = `
      <td class="p-2 md:p-3 border">${idx+1}</td>
      <td class="p-2 md:p-3 border">${escapeHtml(t.ticketno)}</td>
      <td class="p-2 md:p-3 border">${escapeHtml(t.subject)}</td>
      <td class="p-2 md:p-3 border">${escapeHtml(t.type)}</td>
      <td class="p-2 md:p-3 border">${badgePriority(t.priority)}</td>
      <td class="p-2 md:p-3 border">${badgeStatusInt(t.status)}</td>
      <td class="p-2 md:p-3 border">${escapeHtml(t.email)}</td>
      <td class="p-2 md:p-3 border">${fmtDate(t.Date)}</td>
      <td class="p-2 md:p-3 border">
        <div class="flex gap-2">
          <button class="btn-sm bg-blue-600 text-white hover:bg-blue-700" onclick="openView(${t.id})">View</button>
          <button class="btn-sm text-white ${btnColor}" onclick="updateStatus(${t.id}, ${nextSt})">${btnLabel}</button>
        </div>
      </td>
    `;
    tb.appendChild(tr);
  });
}

// ---------- modal logic ----------
function $id(x){ return document.getElementById(x); }
function fillModal(t){
  $id('vm-title').textContent = t.subject || 'Ticket';
  $id('vm-status').outerHTML  = badgeStatusInt(t.status); // replace badge
  // Re-bind id after replacement
  const badges = document.querySelectorAll('.badge-st-open,.badge-st-closed,.badge-st-progress,.badge-st-resolved');
  badges[badges.length-1].id = 'vm-status';

  $id('vm-ticketno').textContent = t.ticketno || '—';
  $id('vm-date').textContent     = fmtDate(t.Date);
  $id('vm-type').textContent     = t.type || '—';
  $id('vm-priority').innerHTML   = badgePriority(t.priority);
  $id('vm-email').textContent    = t.email || '—';
  $id('vm-subject').textContent  = t.subject || '—';
  $id('vm-message').textContent  = t.message || '—';
  $id('vm-remark').textContent   = t.AdminRemark || '—';
}

async function openView(id){
  // Use cached data first
  let t = TICKETS.find(x => Number(x.id) === Number(id));
  if (!t) {
    // Fallback to API if not present
    try {
      const r = await fetch(`?api=view&id=${id}`);
      const j = await r.json();
      if (j.ok) t = j.data;
    } catch(e){}
  }
  if (!t) return alert('Ticket not found');
  VIEW = t;
  fillModal(t);
  openModal();
}

function openModal(){
  const m = $id('viewModal');
  m.style.display = 'flex';
  m.setAttribute('aria-hidden','false');
  document.body.style.overflow = 'hidden';
}
function closeModal(){
  const m = $id('viewModal');
  m.style.display = 'none';
  m.setAttribute('aria-hidden','true');
  document.body.style.overflow = '';
}
$id('vm-close').addEventListener('click', closeModal);
$id('vm-close2').addEventListener('click', closeModal);
$id('viewModal').addEventListener('click', (e)=>{ if (e.target.id==='viewModal') closeModal(); });
document.addEventListener('keydown', (e)=>{ if (e.key==='Escape') closeModal(); });
$id('vm-copy').addEventListener('click', ()=>{
  const tn = ($id('vm-ticketno').textContent || '').trim();
  if (!tn) return;
  navigator.clipboard?.writeText(tn);
  $id('vm-copy').textContent = 'Copied!';
  setTimeout(()=>{ $id('vm-copy').textContent='Copy Ticket No'; }, 1200);
});

// ---------- status update ----------
async function updateStatus(id, newStatus){
  try {
    const r = await fetch('?api=set_status', {
      method: 'POST',
      headers: {'Content-Type':'application/json'},
      body: JSON.stringify({id, status:newStatus})
    });
    const j = await r.json();
    if (!j.ok) { alert(j.error || 'Update failed'); return; }
    const ix = TICKETS.findIndex(x => Number(x.id) === Number(id));
    if (ix >= 0) TICKETS[ix] = j.data;
    renderTable();
    // if modal open for same ticket, refresh it
    if ($id('viewModal').style.display === 'flex' && VIEW && Number(VIEW.id) === Number(id)) {
      VIEW = j.data;
      fillModal(VIEW);
    }
  } catch (e) {
    alert('Network error while updating status.');
  }
}

// init
loadList();
</script>
</body>
</html>
