<?php
require_once('config.php');
require_once(__DIR__ . '/bio_sanitize.php');

// --- AJAX endpoint: fetch a single bio by poet id ------------------
// GET ?action=bio&id=NN  ->  {name, bio} (text), 404 if poet not eligible
if (($_GET['action'] ?? '') === 'bio') {
    header('Content-Type: application/json; charset=utf-8');
    $id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

    // Same eligibility filter the directory uses: accepted submission + visible.
    $stmt = $pdo->prepare("
        SELECT b.author_name, b.author_lastname, b.pen_name, b.bio
        FROM sm_poets AS b
        WHERE b.id = :id
          AND b.no_authors_page = 0
          AND EXISTS (
            SELECT 1 FROM sm_submissions s WHERE s.poetid = b.id AND s.status = 1
          )
        LIMIT 1
    ");
    $stmt->bindValue(':id', $id, PDO::PARAM_INT);
    $stmt->execute();
    $row = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$row) {
        http_response_code(404);
        echo json_encode(['error' => 'not found']);
        exit;
    }

    $pen   = trim((string)($row['pen_name'] ?? ''));
    $first = ucfirst((string)($row['author_name'] ?? ''));
    $last  = ucfirst((string)($row['author_lastname'] ?? ''));
    $name  = $pen !== '' ? $pen : trim($last . ($last && $first ? ', ' : '') . $first);
    // Whitelist-sanitized HTML (preserves bold/italic/lists/links from legacy bios)
    $bio   = bio_sanitize((string)($row['bio'] ?? ''));

    echo json_encode([
        'name' => $name,
        'bio'  => $bio,
    ], JSON_UNESCAPED_UNICODE);
    exit;
}

// --- Normal page render --------------------------------------------
include_once('header.php');
include_once('menu.php');

$page  = isset($_GET['p']) && is_numeric($_GET['p']) ? max(1, (int)$_GET['p']) : 1;
$query = isset($_GET['q']) ? trim((string)$_GET['q']) : '';
$limit = 90;
$offset = ($page - 1) * $limit;

$whereExtra = '';
$params = [];
if ($query !== '') {
    $whereExtra = " AND (b.author_name LIKE :q OR b.author_lastname LIKE :q OR b.pen_name LIKE :q OR CONCAT(b.author_name, ' ', b.author_lastname) LIKE :q) ";
    $params[':q'] = '%' . $query . '%';
}

// NOTE: bio column intentionally NOT selected here -- fetched on demand via AJAX.
$sql = "SELECT DISTINCT b.id, b.author_name, b.author_lastname, b.pen_name
        FROM sm_submissions AS a
        INNER JOIN sm_poets AS b ON a.poetid = b.id
        WHERE a.status = 1
          AND b.no_authors_page = 0
          $whereExtra
        ORDER BY b.author_lastname, b.author_name
        LIMIT :offset, :limit";

$stmt = $pdo->prepare($sql);
foreach ($params as $k => $v) $stmt->bindValue($k, $v, PDO::PARAM_STR);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->bindValue(':limit',  $limit,  PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

$countSql = "SELECT COUNT(DISTINCT b.id) AS total
             FROM sm_submissions AS a
             INNER JOIN sm_poets AS b ON a.poetid = b.id
             WHERE a.status = 1
               AND b.no_authors_page = 0
               $whereExtra";
$countStmt = $pdo->prepare($countSql);
foreach ($params as $k => $v) $countStmt->bindValue($k, $v, PDO::PARAM_STR);
$countStmt->execute();
$totalItems = (int)($countStmt->fetchColumn() ?: 0);
$totalPages = $totalItems > 0 ? (int)ceil($totalItems / $limit) : 1;

$buildLink = function (int $p) use ($query): string {
    $params = ['p' => $p];
    if ($query !== '') $params['q'] = $query;
    return 'biographies.php?' . http_build_query($params);
};
?>

<style>
  .bios-wrap {
    max-width: 1000px; margin: 32px auto 56px; padding: 0 24px;
    font-family: Georgia, 'Times New Roman', serif; color: #222;
  }
  .bios-head { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 12px; border-bottom: 1px solid #d8d4cc; padding-bottom: 16px; margin-bottom: 24px; }
  .bios-head h2 { font-weight: 400; font-size: 28px; letter-spacing: 0.5px; margin: 0; }
  .bios-head .meta { color: #888; font-size: 13px; font-style: italic; font-family: Georgia, serif; }

  .bios-search { display: flex; gap: 8px; margin-bottom: 28px; }
  .bios-search input[type=search] {
    flex: 1; padding: 8px 12px; font-size: 15px;
    border: 1px solid #c9c3b8; border-radius: 2px;
    font-family: Georgia, serif; color: #222; background: #fdfcf9;
  }
  .bios-search input[type=search]:focus { outline: 0; border-color: #6b6557; box-shadow: 0 0 0 2px rgba(107,101,87,0.15); }
  .bios-search button {
    padding: 8px 16px; font-size: 14px; cursor: pointer;
    background: #2a2a2a; color: #fff; border: 0; border-radius: 2px;
    font-family: Georgia, serif; letter-spacing: 0.4px;
  }
  .bios-search button:hover { background: #444; }
  .bios-search a.clear { align-self: center; color: #888; font-size: 13px; }

  .bios-grid {
    columns: 220px; column-gap: 36px; column-rule: 1px solid #eae5da;
    list-style: none; padding: 0; margin: 0;
    font-size: 14px; line-height: 1.5;
  }
  .bios-grid li { break-inside: avoid; margin: 0; }
  .bios-grid a.name {
    display: block; padding: 1px 0;
    color: #1f1f1f; text-decoration: none;
    border-bottom: 1px solid transparent;
  }
  .bios-grid a.name:hover { color: #6a4a1f; border-bottom-color: #c9b48a; cursor: pointer; }
  .bios-grid a.name.active { color: #6a4a1f; font-style: italic; }

  .bios-empty { padding: 48px 12px; text-align: center; color: #888; font-style: italic; }

  /* Modal */
  dialog.bio-modal {
    border: 0; border-radius: 3px; padding: 0;
    max-width: 580px; width: 92%;
    box-shadow: 0 12px 48px rgba(0,0,0,0.18);
    font-family: Georgia, 'Times New Roman', serif; color: #222;
  }
  dialog.bio-modal::backdrop { background: rgba(40,35,28,0.55); }
  dialog.bio-modal .bm-inner { padding: 28px 32px 32px; position: relative; min-height: 100px; }
  dialog.bio-modal h3 { margin: 0 0 14px; font-weight: 400; font-size: 22px; letter-spacing: 0.3px; padding-right: 32px; }
  dialog.bio-modal .bio-text { line-height: 1.65; white-space: pre-wrap; font-size: 15px; }
  dialog.bio-modal .bio-text em { color: #999; font-style: italic; }
  dialog.bio-modal .loading { color: #999; font-style: italic; }
  dialog.bio-modal .close {
    position: absolute; top: 10px; right: 14px;
    background: none; border: 0; font-size: 22px; cursor: pointer;
    color: #888; line-height: 1;
  }
  dialog.bio-modal .close:hover { color: #222; }

  .pagination { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: 4px; justify-content: center; margin: 36px 0 0; font-family: Georgia, serif; font-size: 14px; }
  .pagination .page-item .page-link,
  .pagination .page-item span.page-link {
    display: inline-block; padding: 5px 11px; border: 1px solid #d8d4cc; border-radius: 2px;
    text-decoration: none; color: #444; min-width: 32px; text-align: center; background: #fdfcf9;
  }
  .pagination .page-item .page-link:hover { background: #f0ece2; }
  .pagination .page-item.active .page-link { background: #2a2a2a; color: #fff; border-color: #2a2a2a; }
  .pagination .page-item.disabled .page-link { color: #c0bbb0; background: #faf8f3; }
</style>

<div class="bios-wrap">
  <div class="bios-head">
    <h2>Contributor Biographies</h2>
    <div class="meta">
      <?php
        if ($query !== '') {
          echo $totalItems === 1 ? '1 result' : "$totalItems results";
          echo ' for &ldquo;' . htmlspecialchars($query, ENT_QUOTES, 'UTF-8') . '&rdquo;';
        } else {
          echo $totalItems === 1 ? '1 contributor' : number_format($totalItems) . ' contributors';
        }
      ?>
    </div>
  </div>

  <form class="bios-search" method="get" action="biographies.php">
    <input
      type="search"
      name="q"
      placeholder="Search by name…"
      value="<?= htmlspecialchars($query, ENT_QUOTES, 'UTF-8') ?>">
    <button type="submit">Search</button>
    <?php if ($query !== ''): ?>
      <a class="clear" href="biographies.php">clear</a>
    <?php endif; ?>
  </form>

  <?php if (empty($rows)): ?>
    <div class="bios-empty">No contributors found<?= $query !== '' ? ' matching that search.' : '.' ?></div>
  <?php else: ?>
    <ul class="bios-grid" id="biosGrid">
      <?php foreach ($rows as $row):
        $pen   = trim((string)($row['pen_name'] ?? ''));
        $first = ucfirst((string)($row['author_name'] ?? ''));
        $last  = ucfirst((string)($row['author_lastname'] ?? ''));
        $name  = $pen !== '' ? $pen : trim($last . ($last && $first ? ', ' : '') . $first);
      ?>
        <li><a class="name" href="#" data-bio-id="<?= (int)$row['id'] ?>"><?= htmlspecialchars($name, ENT_QUOTES, 'UTF-8') ?></a></li>
      <?php endforeach; ?>
    </ul>
  <?php endif; ?>

  <?php if ($totalPages > 1): ?>
    <ul class="pagination">
      <?php
        if ($page > 1) {
          echo '<li class="page-item"><a class="page-link" href="' . htmlspecialchars($buildLink($page - 1)) . '">&laquo; Prev</a></li>';
        } else {
          echo '<li class="page-item disabled"><span class="page-link">&laquo; Prev</span></li>';
        }

        $siblings = 2;
        $start = max(1, $page - $siblings);
        $end   = min($totalPages, $page + $siblings);
        if ($start > 1) {
          echo '<li class="page-item"><a class="page-link" href="' . htmlspecialchars($buildLink(1)) . '">1</a></li>';
          if ($start > 2) echo '<li class="page-item disabled"><span class="page-link">…</span></li>';
        }
        for ($i = $start; $i <= $end; $i++) {
          if ($i === $page) {
            echo '<li class="page-item active"><span class="page-link">' . $i . '</span></li>';
          } else {
            echo '<li class="page-item"><a class="page-link" href="' . htmlspecialchars($buildLink($i)) . '">' . $i . '</a></li>';
          }
        }
        if ($end < $totalPages) {
          if ($end < $totalPages - 1) echo '<li class="page-item disabled"><span class="page-link">…</span></li>';
          echo '<li class="page-item"><a class="page-link" href="' . htmlspecialchars($buildLink($totalPages)) . '">' . $totalPages . '</a></li>';
        }

        if ($page < $totalPages) {
          echo '<li class="page-item"><a class="page-link" href="' . htmlspecialchars($buildLink($page + 1)) . '">Next &raquo;</a></li>';
        } else {
          echo '<li class="page-item disabled"><span class="page-link">Next &raquo;</span></li>';
        }
      ?>
    </ul>
  <?php endif; ?>
</div>

<dialog class="bio-modal" id="bioModal">
  <div class="bm-inner">
    <button class="close" type="button" aria-label="Close" id="bioClose">&times;</button>
    <h3 id="bioName"></h3>
    <div id="bioText" class="bio-text"></div>
  </div>
</dialog>

<script>
(function () {
  const modal    = document.getElementById('bioModal');
  const bioName  = document.getElementById('bioName');
  const bioText  = document.getElementById('bioText');
  const grid     = document.getElementById('biosGrid');
  let activeLink = null;
  let inflight   = null;  // AbortController for the current request

  function showModal() {
    if (typeof modal.showModal === 'function') modal.showModal();
    else modal.setAttribute('open', '');
  }

  async function openBio(link) {
    const id = link.dataset.bioId;
    if (!id) return;

    // Optimistic UI: open the modal immediately with the name and a loading state.
    bioName.textContent = link.textContent.trim();
    bioText.innerHTML = '<span class="loading">Loading…</span>';
    if (activeLink) activeLink.classList.remove('active');
    link.classList.add('active');
    activeLink = link;
    showModal();

    // Cancel any earlier inflight request (e.g. user clicked another name fast).
    if (inflight) inflight.abort();
    inflight = new AbortController();

    try {
      const r = await fetch('biographies.php?action=bio&id=' + encodeURIComponent(id), {
        signal: inflight.signal,
        cache: 'no-store',
        headers: { 'Accept': 'application/json' },
      });
      if (!r.ok) throw new Error('HTTP ' + r.status);
      const data = await r.json();
      bioName.textContent = data.name || link.textContent.trim();
      if (!data.bio || !data.bio.trim()) {
        bioText.innerHTML = '<em>No biography provided.</em>';
      } else {
        // Server already sanitized via bio_sanitize() with a strict allowlist.
        bioText.innerHTML = data.bio;
      }
    } catch (err) {
      if (err.name === 'AbortError') return;
      bioText.innerHTML = '<em>Could not load biography. Please try again.</em>';
    }
  }

  if (grid) {
    grid.addEventListener('click', (e) => {
      const link = e.target.closest('a.name');
      if (!link) return;
      e.preventDefault();
      openBio(link);
    });
  }

  document.getElementById('bioClose').addEventListener('click', () => modal.close());
  // Click on the backdrop closes the dialog.
  modal.addEventListener('click', (e) => { if (e.target === modal) modal.close(); });
  modal.addEventListener('close', () => {
    if (activeLink) { activeLink.classList.remove('active'); activeLink = null; }
    if (inflight) { inflight.abort(); inflight = null; }
  });
})();
</script>

<?php include_once('footer.php'); ?>
