<?php
require_once dirname(__DIR__, 2) . '/skyrealms.php';
$SERVER_IP   = SR_SERVER_IP;
$DISCORD_URL = SR_DISCORD_URL;
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Bans — SkyRealms</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&family=Fredoka+One&display=swap" rel="stylesheet">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link rel="stylesheet" href="../style.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
  <style>
    /* ── Full-width body but content capped + side padding like JailbreakMC ── */
    .p-body .p-body-inner { display: block }

    .bans-wrap {
      max-width: 1100px;
      margin: 0 auto;
      padding: 0 24px 60px;
    }

    .bans-header-block {
      background: rgba(0,0,0,0.15);
      border-radius: 4px;
      border-bottom: 3px solid rgba(0,0,0,0.1);
      padding: 18px 18px 16px;
      margin-bottom: 20px;
      display: flex; align-items: center; gap: 12px;
    }
    .bans-header-block h2 { font-size: 18px; color: white; margin: 0 }
    .bans-header-block .material-icons { color: #c04040; font-size: 22px }
    .bans-header-block .bans-desc { font-size: 13px; color: var(--text-muted); margin: 3px 0 0 }

    .appeal-notice {
      background: rgba(245,166,35,0.08);
      border-left: 3px solid var(--orange);
      padding: 12px 16px;
      border-radius: 0 4px 4px 0;
      margin-bottom: 20px;
      font-size: 13px; color: var(--text);
    }
    .appeal-notice strong { color: var(--orange) }
    .appeal-notice a { color: var(--orange); text-decoration: underline }

    /* Stat strip — Blocky font numbers like JailbreakMC */
    .bans-stats-strip {
      display: flex;
      margin-bottom: 20px;
      border-radius: 4px;
      overflow: hidden;
    }
    .bans-stats-strip .stat-pill {
      flex: 1; padding: 14px 16px; text-align: center;
      background: rgba(0,0,0,0.2);
      border-right: 1px solid rgba(255,255,255,0.04);
    }
    .bans-stats-strip .stat-pill:last-child { border-right: none }
    .bans-stats-strip .num {
      display: block; font-size: 26px; font-weight: bold;
      font-family: "Blocky", monospace; line-height: 1;
      margin-bottom: 4px;
    }
    .bans-stats-strip .lbl {
      display: block; font-size: 11px; text-transform: uppercase;
      letter-spacing: 1px; color: var(--text-muted);
    }
    .bans-stats-strip .stat-pill--red  .num { color: #f77 }
    .bans-stats-strip .stat-pill--gold .num { color: var(--orange) }
    .bans-stats-strip .stat-pill--blue .num { color: #88aaff }
    .bans-stats-strip .stat-pill--green .num { color: #88cc88 }

    .bans-filter-bar {
      background: rgba(0,0,0,0.25);
      border-radius: 4px;
      padding: 10px 16px;
      margin-bottom: 20px;
      display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
    }
    .bans-filter-bar label {
      font-size: 11px; color: var(--text-muted); font-weight: 800;
      text-transform: uppercase; letter-spacing: 1px; flex-shrink: 0;
    }
    .bans-filter-bar input,
    .bans-filter-bar select {
      background: rgba(0,0,0,0.25); border: 1px solid rgba(255,255,255,0.1);
      border-radius: 3px; color: white; font-family: 'Nunito', sans-serif;
      font-size: 13px; padding: 6px 10px; outline: none; transition: border-color .2s;
    }
    .bans-filter-bar input:focus,
    .bans-filter-bar select:focus { border-color: var(--orange) }
    .bans-filter-bar input { width: 200px }
    .bans-filter-bar select { min-width: 120px; color: #ccc }
    .bans-filter-bar select option { background: #1a2a3a }
    .filter-spacer { flex: 1 }
    .bans-count { font-size: 12px; color: var(--text-muted); font-style: italic }

    .bans-table-wrap { overflow-x: auto; border-radius: 4px }
    .bans-table { width: 100%; border-collapse: collapse; font-size: 13px }
    .bans-table thead tr { background: rgba(0,0,0,0.25) }
    .bans-table th {
      padding: 12px 16px; text-align: left; color: rgba(200,220,240,0.5);
      font-weight: 800; font-size: 11px; text-transform: uppercase; letter-spacing: 1px;
      border-bottom: 2px solid rgba(255,255,255,0.06); white-space: nowrap; user-select: none;
    }
    .bans-table th.sortable { cursor: pointer }
    .bans-table th.sortable:hover { color: white }
    .bans-table th .sort-icon { font-size: 14px; vertical-align: middle; opacity: .4; margin-left: 2px }
    .bans-table th.sort-asc .sort-icon,
    .bans-table th.sort-desc .sort-icon { opacity: 1; color: var(--orange) }
    .bans-table td {
      padding: 10px 16px; border-bottom: 1px solid rgba(255,255,255,0.04);
      color: rgba(200,220,240,0.5); vertical-align: middle;
    }
    .bans-table tbody tr { transition: background .15s }
    .bans-table tbody tr:hover td { background: rgba(255,255,255,0.025) }
    .bans-table tbody tr:last-child td { border-bottom: none }

    /* Player cell: Minecraft head + name */
    .player-cell { display: flex; align-items: center; gap: 10px }
    .player-head {
      width: 32px; height: 32px;
      border-radius: 3px; overflow: hidden; flex-shrink: 0;
      background: rgba(0,0,0,0.3);
      image-rendering: pixelated;
      display: block;
    }
    .player-head-wrap {
      position: relative; flex-shrink: 0;
      width: 32px; height: 32px;
    }
    /* Fallback letter shown until image loads */
    .player-head-fallback {
      position: absolute; inset: 0;
      display: flex; align-items: center; justify-content: center;
      border-radius: 3px;
      font-size: 13px; font-weight: 800; color: white;
    }
    .player-name { color: #cde; font-weight: 700; font-size: 13px }
    .staff-name  { color: var(--orange); font-weight: 700 }
    .reason-text { color: #bbb; max-width: 300px }

    .ban-badge {
      display: inline-flex; align-items: center; gap: 4px;
      padding: 3px 8px; border-radius: 3px;
      font-size: 11px; font-weight: 800; text-transform: uppercase;
      letter-spacing: .5px; white-space: nowrap;
    }
    .ban-badge .material-icons { font-size: 12px }
    .ban-badge--permanent { background: rgba(200,50,50,.18);  color: #f77;          border: 1px solid rgba(200,50,50,.3) }
    .ban-badge--temporary  { background: rgba(220,140,50,.18); color: var(--orange); border: 1px solid rgba(220,140,50,.3) }
    .ban-badge--mute       { background: rgba(80,120,200,.18); color: #88aaff;       border: 1px solid rgba(80,120,200,.3) }
    .ban-badge--kick       { background: rgba(100,180,100,.15);color: #88cc88;       border: 1px solid rgba(100,180,100,.25) }
    .ban-badge--warning    { background: rgba(180,180,50,.15); color: #dddd66;       border: 1px solid rgba(180,180,50,.25) }

    .expiry-permanent { color: #f77; font-size: 12px }
    .expiry-date      { color: var(--orange); font-size: 12px }
    .expiry-expired   { color: #555; font-size: 12px; text-decoration: line-through }
    .date-cell        { font-size: 12px; white-space: nowrap }

    .ban-detail-row { display: none }
    .ban-detail-row.open { display: table-row }
    .ban-detail-inner {
      padding: 14px 16px 14px 64px;
      background: rgba(0,0,0,0.15);
      border-bottom: 1px solid rgba(255,255,255,0.04);
    }
    .ban-detail-inner dl { display: grid; grid-template-columns: 120px 1fr; gap: 6px 12px; font-size: 13px }
    .ban-detail-inner dt { color: var(--text-muted); font-weight: 700 }
    .ban-detail-inner dd { color: #ccc }

    .bans-empty { text-align: center; padding: 60px 20px; color: var(--text-muted) }
    .bans-empty .material-icons { font-size: 48px; display: block; margin: 0 auto 12px; color: #333 }
    .bans-empty p { font-size: 14px }

    .bans-pagination {
      display: flex; justify-content: center; align-items: center;
      gap: 4px; margin-top: 20px; flex-wrap: wrap;
    }
    .page-btn {
      min-width: 34px; height: 34px;
      display: inline-flex; align-items: center; justify-content: center;
      border-radius: 3px; font-size: 13px; font-weight: 800;
      color: rgba(255,255,255,.4); background: rgba(255,255,255,.05);
      border: none; cursor: pointer; font-family: 'Nunito', sans-serif;
      transition: .15s; padding: 0 8px;
    }
    .page-btn:hover { background: rgba(255,255,255,.1); color: white }
    .page-btn.active { background: var(--orange); color: #3a2000 }
    .page-btn:disabled { opacity: .3; cursor: default }
    .page-btn .material-icons { font-size: 16px }

    @media (max-width: 700px) {
      .bans-table th:nth-child(4), .bans-table td:nth-child(4),
      .bans-table th:nth-child(6), .bans-table td:nth-child(6) { display: none }
      .bans-filter-bar input { width: 130px }
    }
    @media (max-width: 480px) {
      .bans-table th:nth-child(3), .bans-table td:nth-child(3) { display: none }
      .bans-stats-strip { flex-wrap: wrap }
      .bans-stats-strip .stat-pill { flex: 1 1 50% }
      .bans-wrap { padding: 0 12px 40px }
    }
  </style>
</head>
<body>
<div class="p-pageWrapper" id="top">
<div id="page-content">

<div class="p-body">
  <div class="p-body-inner">
    <div class="p-body-content">
      <div class="bans-wrap">

        <div class="p-breadcrumbs">
          <a href="../">Home</a>
          <span class="material-icons">chevron_right</span>
          <span>Punishment History</span>
        </div>

        <div class="bans-header-block">
          <span class="material-icons">gavel</span>
          <div>
            <h2>Punishment History</h2>
            <p class="bans-desc">A public record of all bans, mutes, kicks and warnings issued on SkyRealms.</p>
          </div>
        </div>

        <div class="appeal-notice">
          <strong>Think your ban was unfair?</strong> You can appeal in our
          <a href="<?= htmlspecialchars($DISCORD_URL) ?>" target="_blank">Discord server</a>
          under the ban-appeals channel.
        </div>

        <div class="bans-stats-strip">
          <div class="stat-pill stat-pill--red">  <span class="num" id="stat-bans">—</span><span class="lbl">Bans</span></div>
          <div class="stat-pill stat-pill--gold"> <span class="num" id="stat-temp">—</span><span class="lbl">Temp Bans</span></div>
          <div class="stat-pill stat-pill--blue"> <span class="num" id="stat-mutes">—</span><span class="lbl">Mutes</span></div>
          <div class="stat-pill stat-pill--green"><span class="num" id="stat-kicks">—</span><span class="lbl">Kicks</span></div>
        </div>

        <div class="bans-filter-bar">
          <label>Search</label>
          <input type="text" id="filterPlayer" placeholder="Player name…" oninput="applyFilters()">
          <label>Type</label>
          <select id="filterType" onchange="applyFilters()">
            <option value="">All types</option>
            <option value="permanent">Permanent Ban</option>
            <option value="temporary">Temp Ban</option>
            <option value="mute">Mute</option>
            <option value="kick">Kick</option>
            <option value="warning">Warning</option>
          </select>
          <label>Staff</label>
          <select id="filterStaff" onchange="applyFilters()">
            <option value="">All staff</option>
          </select>
          <div class="filter-spacer"></div>
          <span class="bans-count" id="bansCount"></span>
        </div>

        <div class="bans-table-wrap">
          <table class="bans-table" id="bansTable">
            <thead><tr>
              <th class="sortable" data-col="player" onclick="sortBy('player')">Player <span class="material-icons sort-icon">unfold_more</span></th>
              <th class="sortable" data-col="type"   onclick="sortBy('type')">Type <span class="material-icons sort-icon">unfold_more</span></th>
              <th>Reason</th>
              <th class="sortable" data-col="staff"  onclick="sortBy('staff')">Banned by <span class="material-icons sort-icon">unfold_more</span></th>
              <th class="sortable" data-col="date"   onclick="sortBy('date')">Date <span class="material-icons sort-icon">unfold_more</span></th>
              <th>Expires</th>
            </tr></thead>
            <tbody id="bansBody"></tbody>
          </table>
          <div class="bans-empty" id="bansEmpty" style="display:none">
            <span class="material-icons">search_off</span>
            <p>No punishments match your search.</p>
          </div>
        </div>

        <div class="bans-pagination" id="pagination"></div>

      </div><!-- /.bans-wrap -->
    </div>
  </div>
</div>

</div><!-- #page-content -->
</div><!-- .p-pageWrapper -->

<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.js"></script>
<script src="../nav.js"></script>
<script>
Nav.init({
  active:     'bans',
  pageTitle:  'Punishment History',
  serverIp:   '<?= htmlspecialchars($SERVER_IP) ?>',
  discordUrl: '<?= htmlspecialchars($DISCORD_URL) ?>',
});

const PER_PAGE = 12;
let allBans = [], filtered = [], currentPage = 1, sortCol = 'date', sortDir = 'desc';

async function fetchBans() {
  try {
    const [bans, mutes, warnings, kicks] = await Promise.all([
      fetch('api.php?type=bans&limit=100').then(r => r.json()),
      fetch('api.php?type=mutes&limit=100').then(r => r.json()),
      fetch('api.php?type=warnings&limit=100').then(r => r.json()),
      fetch('api.php?type=kicks&limit=100').then(r => r.json()),
    ]);
    if (bans.error) throw new Error(bans.error);
    return [
      ...(bans.data     || []),
      ...(mutes.data    || []),
      ...(warnings.data || []),
      ...(kicks.data    || []),
    ].sort((a, b) => b.dateRaw - a.dateRaw);
  } catch(e) {
    console.warn('Bans API unavailable, using sample data:', e);
    return SAMPLE_BANS;
  }
}

async function init() {
  allBans = await fetchBans();
  buildStaffFilter();
  updateStats();
  applyFilters();
}

function updateStats() {
  document.getElementById('stat-bans').textContent  = allBans.filter(b => b.type === 'permanent').length;
  document.getElementById('stat-temp').textContent  = allBans.filter(b => b.type === 'temporary').length;
  document.getElementById('stat-mutes').textContent = allBans.filter(b => b.type === 'mute').length;
  document.getElementById('stat-kicks').textContent = allBans.filter(b => b.type === 'kick').length;
}

function buildStaffFilter() {
  const staffSet = [...new Set(allBans.map(b => b.staff))].sort();
  const sel = document.getElementById('filterStaff');
  staffSet.forEach(s => {
    const o = document.createElement('option');
    o.value = s; o.textContent = s;
    sel.appendChild(o);
  });
}

function applyFilters() {
  const q     = document.getElementById('filterPlayer').value.toLowerCase().trim();
  const type  = document.getElementById('filterType').value;
  const staff = document.getElementById('filterStaff').value;
  filtered = allBans.filter(b => {
    if (q     && !b.player.toLowerCase().includes(q)) return false;
    if (type  && b.type !== type)                     return false;
    if (staff && b.staff !== staff)                   return false;
    return true;
  });
  sortData(); currentPage = 1; render();
}

function sortBy(col) {
  sortDir = sortCol === col ? (sortDir === 'asc' ? 'desc' : 'asc') : 'desc';
  sortCol = col; sortData(); currentPage = 1; render(); updateSortHeaders();
}

function sortData() {
  filtered.sort((a, b) => {
    let av = a[sortCol] ?? '', bv = b[sortCol] ?? '';
    if (sortCol === 'date') { av = new Date(av); bv = new Date(bv); }
    else { av = av.toString().toLowerCase(); bv = bv.toString().toLowerCase(); }
    if (av < bv) return sortDir === 'asc' ? -1 :  1;
    if (av > bv) return sortDir === 'asc' ?  1 : -1;
    return 0;
  });
}

function updateSortHeaders() {
  document.querySelectorAll('.bans-table th[data-col]').forEach(th => {
    th.classList.remove('sort-asc', 'sort-desc');
    const icon = th.querySelector('.sort-icon');
    if (th.dataset.col === sortCol) {
      th.classList.add(sortDir === 'asc' ? 'sort-asc' : 'sort-desc');
      icon.textContent = sortDir === 'asc' ? 'expand_less' : 'expand_more';
    } else {
      icon.textContent = 'unfold_more';
    }
  });
}

function render() {
  const tbody = document.getElementById('bansBody');
  const empty = document.getElementById('bansEmpty');
  document.getElementById('bansCount').textContent =
    `${filtered.length} record${filtered.length !== 1 ? 's' : ''}`;

  if (!filtered.length) {
    tbody.innerHTML = ''; empty.style.display = 'block';
    document.getElementById('pagination').innerHTML = '';
    return;
  }
  empty.style.display = 'none';
  const page = filtered.slice((currentPage - 1) * PER_PAGE, currentPage * PER_PAGE);

  tbody.innerHTML = page.map(ban => {
    const letter = ban.player.charAt(0).toUpperCase();
    const hue    = avatarHue(ban.player);
    const bg     = `hsl(${hue},40%,22%)`;
    const fg     = `hsl(${hue},60%,65%)`;
    // Minotar: free Minecraft head API, pixelated helm render
    const headUrl = `https://minotar.net/helm/${encodeURIComponent(ban.player)}/32`;

    return `
    <tr class="ban-row" onclick="toggleDetail(${ban.id})" style="cursor:pointer" title="Click for details">
      <td>
        <div class="player-cell">
          <div class="player-head-wrap">
            <div class="player-head-fallback" style="background:${bg};color:${fg}">${letter}</div>
            <img class="player-head"
              src="${headUrl}"
              alt="${esc(ban.player)}"
              style="position:absolute;inset:0;border-radius:3px;image-rendering:pixelated"
              onerror="this.style.display='none'">
          </div>
          <span class="player-name">${esc(ban.player)}</span>
        </div>
      </td>
      <td>${typeBadge(ban.type)}</td>
      <td><span class="reason-text">${esc(ban.reason)}</span></td>
      <td><span class="staff-name">${esc(ban.staff)}</span></td>
      <td><span class="date-cell">${fmtDate(ban.date)}</span></td>
      <td>${expiryCell(ban)}</td>
    </tr>
    <tr class="ban-detail-row" id="detail-${ban.id}">
      <td colspan="6">
        <div class="ban-detail-inner"><dl>
          <dt>Player</dt>    <dd>${esc(ban.player)}</dd>
          <dt>Type</dt>      <dd>${typeBadge(ban.type)}</dd>
          <dt>Reason</dt>    <dd>${esc(ban.reason)}</dd>
          <dt>Banned by</dt> <dd><span class="staff-name">${esc(ban.staff)}</span></dd>
          <dt>Date</dt>      <dd>${fmtDate(ban.date)}</dd>
          <dt>Expires</dt>   <dd>${ban.expires
            ? fmtDate(ban.expires)
            : (ban.type === 'kick' || ban.type === 'warning'
                ? 'N/A'
                : '<span class="expiry-permanent">Never (Permanent)</span>')}</dd>
        </dl></div>
      </td>
    </tr>`;
  }).join('');

  renderPagination();
}

function toggleDetail(id) {
  document.getElementById('detail-' + id)?.classList.toggle('open');
}

function renderPagination() {
  const total = Math.ceil(filtered.length / PER_PAGE);
  if (total <= 1) { document.getElementById('pagination').innerHTML = ''; return; }
  let html = `<button class="page-btn" onclick="goPage(${currentPage - 1})" ${currentPage === 1 ? 'disabled' : ''}><span class="material-icons">chevron_left</span></button>`;
  for (let p = 1; p <= total; p++) {
    if (total > 7 && p > 2 && p < total - 1 && Math.abs(p - currentPage) > 1) {
      if (p === 3 || p === total - 2) html += `<button class="page-btn" disabled>…</button>`;
      continue;
    }
    html += `<button class="page-btn ${p === currentPage ? 'active' : ''}" onclick="goPage(${p})">${p}</button>`;
  }
  html += `<button class="page-btn" onclick="goPage(${currentPage + 1})" ${currentPage === total ? 'disabled' : ''}><span class="material-icons">chevron_right</span></button>`;
  document.getElementById('pagination').innerHTML = html;
}

function goPage(p) {
  const total = Math.ceil(filtered.length / PER_PAGE);
  if (p < 1 || p > total) return;
  currentPage = p; render();
  document.querySelector('.bans-table-wrap').scrollIntoView({ behavior: 'smooth', block: 'start' });
}

function typeBadge(type) {
  const map = {
    permanent: ['ban-badge--permanent', 'block',       'Permanent Ban'],
    temporary: ['ban-badge--temporary', 'schedule',    'Temp Ban'],
    mute:      ['ban-badge--mute',      'volume_off',  'Mute'],
    kick:      ['ban-badge--kick',      'exit_to_app', 'Kick'],
    warning:   ['ban-badge--warning',   'warning',     'Warning'],
  };
  const [cls, icon, label] = map[type] || ['', 'help', type];
  return `<span class="ban-badge ${cls}"><span class="material-icons">${icon}</span>${label}</span>`;
}

function expiryCell(ban) {
  if (ban.type === 'kick' || ban.type === 'warning')
    return '<span style="color:#444;font-size:12px">—</span>';
  if (!ban.expires)
    return '<span class="expiry-permanent">Never</span>';
  return new Date(ban.expires) < new Date()
    ? `<span class="expiry-expired">${fmtDate(ban.expires)}</span>`
    : `<span class="expiry-date">${fmtDate(ban.expires)}</span>`;
}

function fmtDate(iso) {
  if (!iso) return '—';
  return new Date(iso).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' });
}

function esc(s) {
  return String(s)
    .replace(/&/g, '&amp;').replace(/</g, '&lt;')
    .replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

// Consistent color per username for the fallback letter tile
function avatarHue(name) {
  let h = 0;
  for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) & 0xFFFFFF;
  return h % 360;
}

const SAMPLE_BANS = [
  { id:1, player:'xXSkyKingXx',  type:'permanent', reason:'Hacking / Kill-aura client',          staff:'Admin',     date:'2025-01-15', expires: null },
  { id:2, player:'IslandGriefr', type:'temporary', reason:"Griefing another player's island",    staff:'Moderator', date:'2025-01-10', expires:'2025-02-10' },
  { id:3, player:'SkyDupeBot',   type:'permanent', reason:'Exploiting item duplication glitch',  staff:'Admin',     date:'2025-01-08', expires: null },
  { id:4, player:'SpammerPro',   type:'mute',      reason:'Excessive spam in global chat',       staff:'Helper',    date:'2025-01-07', expires:'2025-01-14' },
  { id:5, player:'AFKFarmer99',  type:'kick',      reason:'AFK farming in PvP zone',             staff:'Moderator', date:'2025-01-05', expires: null },
];

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