<?php

require __DIR__ . '/../bootstrap.php';

use KeyLair\Auth;
use KeyLair\Csrf;
use KeyLair\Database;
use KeyLair\DemoMask;
use KeyLair\Helpers;
use KeyLair\AuditLog;
use KeyLair\I18n;

Auth::requireLogin();
$admin = Auth::user();
$isDemo = $admin['role'] === 'demo';
$pdo = Database::connection();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    Auth::requireEditAccess();
    Csrf::requireValid();
    $action = $_POST['form_action'] ?? '';
    $id = (int) ($_POST['id'] ?? 0);

    if ($action === 'toggle_status') {
        $pdo->prepare("UPDATE claim_links SET status = IF(status='active','disabled','active') WHERE id = :id")->execute(['id' => $id]);
        AuditLog::log($admin['id'], 'claim_link_toggled', (string) $id);
    } elseif ($action === 'delete') {
        $pdo->prepare('DELETE FROM claim_links WHERE id = :id')->execute(['id' => $id]);
        AuditLog::log($admin['id'], 'claim_link_deleted', (string) $id);
    }
    Helpers::redirect('claim_links.php');
}

// Optional: arriving from a specific user's "Claim links" count on the
// Users page links here filtered down to just their own links, instead
// of the full unfiltered list.
$userFilter = (int) ($_GET['user_id'] ?? 0);
$userFilterName = null;
if ($userFilter) {
    $userFilterStmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
    $userFilterStmt->execute(['id' => $userFilter]);
    $userFilterRow = $userFilterStmt->fetch();
    if (!$userFilterRow) {
        http_response_code(404);
        die('User not found.');
    }
    $userFilterName = $userFilterRow['name'] ?? ('User #' . $userFilter);
}

$linksStmt = $pdo->prepare(
    'SELECT l.*, c.name AS campaign_name, u.name AS user_name, u.email AS user_email,
        (SELECT COUNT(*) FROM claim_link_products clp WHERE clp.claim_link_id = l.id) AS product_count,
        (SELECT COALESCE(SUM(clp.claims_used),0) FROM claim_link_products clp WHERE clp.claim_link_id = l.id) AS total_claimed
     FROM claim_links l
     LEFT JOIN campaigns c ON c.id = l.campaign_id
     LEFT JOIN users u ON u.id = l.user_id
     ' . ($userFilter ? 'WHERE l.user_id = :user_filter' : '') . '
     ORDER BY l.created_at DESC'
);
if ($userFilter) {
    $linksStmt->execute(['user_filter' => $userFilter]);
} else {
    $linksStmt->execute();
}
$links = $linksStmt->fetchAll();

// One query for every link's products, grouped in PHP below, instead of a
// per-row query per link (N+1) -- this page can list many links at once.
$productsByLink = [];
$productRows = $pdo->query(
    'SELECT clp.claim_link_id, p.slug, p.name
     FROM claim_link_products clp
     JOIN products p ON p.id = clp.product_id
     ORDER BY clp.id'
)->fetchAll();
foreach ($productRows as $pr) {
    $productsByLink[$pr['claim_link_id']][] = $pr;
}

$baseUrl = Helpers::baseUrl();

$pageTitle = I18n::t('claim_links.page_title');
$activeNav = 'claim_links';
$extraAdminCss = 'admin-product-editor';
require __DIR__ . '/includes/layout_header.php';
?>
<div class="topbar">
  <h1><?= Helpers::e(I18n::t('claim_links.page_title')) ?></h1>
  <div style="display:flex; gap:10px; flex-wrap:wrap;">
    <?php if (Auth::canEdit()): ?>
    <a href="claim_link_form.php" class="campaign-select" style="text-decoration:none; color:var(--signal); border-color:var(--signal-dim);"><?= Helpers::e(I18n::t('claim_links.new_link_button')) ?></a>
    <a href="claim_links_batch.php" class="campaign-select" style="text-decoration:none; color:var(--text-muted);"><?= Helpers::e(I18n::t('claim_links.batch_create_button')) ?></a>
    <?php if (!empty($links)): ?>
    <button type="button" class="campaign-select" onclick="kvExportClaimLinks(0);" style="color:var(--text-muted);"><?= Helpers::e(I18n::t('claim_links.export_csv_button')) ?></button>
    <?php endif; ?>
    <?php elseif ($isDemo): ?>
    <span class="campaign-select" style="text-decoration:none; color:var(--text-faint); border-color:var(--signal-dim); cursor:not-allowed;"><?= Helpers::e(I18n::t('claim_links.new_link_button')) ?></span>
    <span class="campaign-select" style="text-decoration:none; color:var(--text-faint); border-color:var(--signal-dim); cursor:not-allowed;"><?= Helpers::e(I18n::t('claim_links.batch_create_button')) ?></span>
    <?php endif; ?>
  </div>
</div>

<?php if (!empty($_GET['saved'])): ?>
  <div class="panel" style="border-color:var(--signal-dim); margin-bottom:16px;">
    <p style="color:var(--signal); font-size:13px; margin:0;"><?= Helpers::e(I18n::t('claim_links.saved_notice')) ?></p>
  </div>
<?php endif; ?>

<?php if ($userFilter): ?>
  <div class="panel" style="margin-bottom:16px; display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap;">
    <p style="font-size:13px; margin:0;"><?= sprintf(I18n::t('claim_links.filter_showing'), Helpers::e($userFilterName)) ?></p>
    <a href="claim_links.php" style="color:var(--signal); font-size:13px; text-decoration:none;"><?= Helpers::e(I18n::t('claim_links.clear_filter')) ?></a>
  </div>
<?php endif; ?>

<div class="panel">
  <?php if (empty($links)): ?>
    <p style="color:var(--text-faint); font-size:13px;"><?= Helpers::e($userFilter ? I18n::t('claim_links.empty_state_filtered') : I18n::t('claim_links.empty_state_unfiltered')) ?></p>
  <?php else: ?>
  <table id="claim-links-table">
    <thead><tr><th><?= Helpers::e(I18n::t('claim_links.col_creator')) ?></th><th><?= Helpers::e(I18n::t('claim_links.col_campaign')) ?></th><th><?= Helpers::e(I18n::t('claim_links.col_products')) ?></th><th><?= Helpers::e(I18n::t('claim_links.col_claimed')) ?></th><th><?= Helpers::e(I18n::t('claim_links.col_status')) ?></th><th><?= Helpers::e(I18n::t('claim_links.col_links')) ?></th><th></th></tr></thead>
    <tbody>
      <?php foreach ($links as $l):
        $overviewUrl = DemoMask::claimUrl($baseUrl . '/claim/' . $l['token'], $l['token'], true);
        $userDisplay = $l['user_name'] !== null ? DemoMask::name($l['user_name']) : sprintf(I18n::t('claim_links.user_placeholder'), (int) $l['user_id']);
        $statusLabel = $l['status'] === 'active' ? I18n::t('claim_links.status_active') : I18n::t('claim_links.status_disabled');
      ?>
      <tr>
        <td class="creator" data-label="<?= Helpers::e(I18n::t('claim_links.col_creator')) ?>"><?= Helpers::e($userDisplay) ?></td>
        <td data-label="<?= Helpers::e(I18n::t('claim_links.col_campaign')) ?>"><?= $l['campaign_name'] !== null ? Helpers::e($l['campaign_name']) : '<span style="color:var(--text-faint);">—</span>' ?></td>
        <td class="time-cell" data-label="<?= Helpers::e(I18n::t('claim_links.col_products')) ?>"><?= (int) $l['product_count'] ?></td>
        <td class="time-cell" data-label="<?= Helpers::e(I18n::t('claim_links.col_claimed')) ?>"><?= (int) $l['total_claimed'] ?></td>
        <td data-label="<?= Helpers::e(I18n::t('claim_links.col_status')) ?>">
          <span class="plat-tag" style="<?= $l['status'] !== 'active' ? 'background:rgba(136,144,164,0.12); color:var(--text-muted);' : '' ?>">
            <?= Helpers::e($statusLabel) ?>
          </span>
        </td>
        <td data-label="<?= Helpers::e(I18n::t('claim_links.col_links')) ?>">
          <div class="link-cell">
            <div class="link-row">
              <span class="link-label"><?= Helpers::e(I18n::t('claim_links.link_label_all_products')) ?></span>
              <a href="<?= Helpers::e($overviewUrl) ?>" target="_blank" rel="noopener" class="claim-link-a" title="<?= Helpers::e($overviewUrl) ?>"><?= Helpers::e($overviewUrl) ?></a>
              <button type="button" class="link-copy-btn" data-copy="<?= Helpers::e($overviewUrl) ?>"><?= Helpers::e(I18n::t('claim_links.copy_button')) ?></button>
            </div>
            <?php foreach ($productsByLink[$l['id']] ?? [] as $pr):
              $productUrl = DemoMask::claimUrl($baseUrl . '/claim/' . $l['token'] . '/' . $pr['slug'], $l['token']);
            ?>
            <div class="link-row">
              <span class="link-label"><?= Helpers::e($pr['name']) ?>:</span>
              <a href="<?= Helpers::e($productUrl) ?>" target="_blank" rel="noopener" class="claim-link-a" title="<?= Helpers::e($productUrl) ?>"><?= Helpers::e($productUrl) ?></a>
              <button type="button" class="link-copy-btn" data-copy="<?= Helpers::e($productUrl) ?>"><?= Helpers::e(I18n::t('claim_links.copy_button')) ?></button>
            </div>
            <?php endforeach; ?>
          </div>
        </td>
        <td style="white-space:nowrap;">
          <?php if (Auth::canEdit() || $isDemo): ?>
          <?php if (Auth::canEdit()): ?>
          <a href="claim_link_form.php?id=<?= (int) $l['id'] ?>" style="color:var(--text-muted); font-size:12px; text-decoration:none; margin-right:10px;"><?= Helpers::e(I18n::t('claim_links.edit_link')) ?></a>
          <button type="button" onclick="kvExportClaimLinks(<?= (int) $l['id'] ?>);" style="background:none; border:none; color:var(--text-muted); font-size:12px; cursor:pointer; padding:0; margin-right:10px;"><?= Helpers::e(I18n::t('claim_links.csv_link')) ?></button>
          <?php else: ?>
          <span style="color:var(--text-faint); font-size:12px; text-decoration:none; margin-right:10px; cursor:not-allowed;"><?= Helpers::e(I18n::t('claim_links.edit_link')) ?></span>
          <?php endif; ?>
          <fieldset <?= $isDemo ? 'disabled' : '' ?> style="border:0; margin:0; padding:0; display:inline;">
          <form method="post" style="display:inline;">
            <?= Csrf::field() ?>
            <input type="hidden" name="form_action" value="toggle_status">
            <input type="hidden" name="id" value="<?= (int) $l['id'] ?>">
            <button type="submit" style="background:none; border:none; color:var(--signal); font-size:12px; cursor:pointer; padding:0; margin-right:10px;"><?= $l['status'] === 'active' ? Helpers::e(I18n::t('claim_links.disable_button')) : Helpers::e(I18n::t('claim_links.enable_button')) ?></button>
          </form>
          <form method="post" style="display:inline;" onsubmit="return confirm(<?= json_encode(I18n::t('claim_links.delete_confirm_js'), JSON_HEX_APOS | JSON_HEX_QUOT) ?>);">
            <?= Csrf::field() ?>
            <input type="hidden" name="form_action" value="delete">
            <input type="hidden" name="id" value="<?= (int) $l['id'] ?>">
            <button type="submit" style="background:none; border:none; color:var(--danger); font-size:12px; cursor:pointer; padding:0;"><?= Helpers::e(I18n::t('claim_links.delete_button')) ?></button>
          </form>
          </fieldset>
          <?php endif; ?>
        </td>
      </tr>
      <?php endforeach; ?>
    </tbody>
  </table>
  <div id="claim-links-pagination" style="display:flex; justify-content:center; align-items:center; gap:14px; flex-wrap:wrap; margin-top:16px;">
    <button type="button" class="btn btn-ghost" id="claim-links-prev-btn" onclick="kvClaimLinksChangePage(-1);" style="padding:7px 14px; font-size:12.5px;"><?= Helpers::e(I18n::t('claim_links.prev_button')) ?></button>
    <span id="claim-links-page-info" style="color:var(--text-muted); font-size:13px; white-space:nowrap;"></span>
    <button type="button" class="btn btn-ghost" id="claim-links-next-btn" onclick="kvClaimLinksChangePage(1);" style="padding:7px 14px; font-size:12.5px;"><?= Helpers::e(I18n::t('claim_links.next_button')) ?></button>
    <select id="claim-links-page-size" onchange="kvClaimLinksChangePageSize();" style="background:var(--bg-panel); border:1px solid var(--line); color:var(--text-primary); font-size:12.5px; padding:7px 12px; border-radius:8px;">
      <?php foreach ([10, 20, 50, 100, 200] as $pageSizeOption): ?>
      <option value="<?= $pageSizeOption ?>" <?= $pageSizeOption === 50 ? 'selected' : '' ?>><?= Helpers::e(sprintf(I18n::t('claim_links.page_size_option'), $pageSizeOption)) ?></option>
      <?php endforeach; ?>
      <option value="all"><?= Helpers::e(I18n::t('claim_links.show_all_option')) ?></option>
    </select>
  </div>
  <?php if (count($links) > 20): ?>
  <?php // Same fixed jump-to-first/last-row buttons as Keys/Codes and
  // Users -- the only fast way back to either end once there are
  // thousands of links and "Show all" is selected. ?>
  <div style="position:fixed; right:20px; bottom:20px; display:flex; flex-direction:column; gap:8px; z-index:50;">
    <button type="button" class="btn btn-ghost" onclick="kvScrollToRow('first');" title="<?= Helpers::e(I18n::t('claim_links.jump_first_title')) ?>" style="width:40px; height:40px; padding:0; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:16px; background:var(--bg-panel); box-shadow:0 2px 8px rgba(0,0,0,0.3);">↑</button>
    <button type="button" class="btn btn-ghost" onclick="kvScrollToRow('last');" title="<?= Helpers::e(I18n::t('claim_links.jump_last_title')) ?>" style="width:40px; height:40px; padding:0; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:16px; background:var(--bg-panel); box-shadow:0 2px 8px rgba(0,0,0,0.3);">↓</button>
  </div>
  <?php endif; ?>
  <?php endif; ?>
</div>

<script>
// Export is a POST (CSRF-protected, same as keys' own CSV export) rather
// than a plain link, so a fetch()+blob download is needed instead of just
// pointing <a href> at the export page -- id 0 exports every link, a
// specific id exports just that one row.
var kvExportFailedTemplate = <?= json_encode(I18n::t('claim_links.export_failed_alert'), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
var kvCopiedLabel = <?= json_encode(I18n::t('claim_links.copied_label'), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
var kvPageInfoTemplate = <?= json_encode(I18n::t('claim_links.page_info'), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;

async function kvExportClaimLinks(id) {
  const formData = new FormData();
  formData.append('csrf_token', <?= json_encode(Csrf::token()) ?>);
  formData.append('id', id);
  const res = await fetch('claim_links_export.php', { method: 'POST', body: formData });
  if (!res.ok) {
    alert(kvExportFailedTemplate.replace('%d', res.status));
    return;
  }
  const blob = await res.blob();
  const disposition = res.headers.get('Content-Disposition') || '';
  const match = disposition.match(/filename="([^"]+)"/);
  const filename = match ? match[1] : 'claim-links.csv';
  const blobUrl = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = blobUrl;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  a.remove();
  URL.revokeObjectURL(blobUrl);
}

document.querySelectorAll('.link-copy-btn').forEach(function (btn) {
  btn.addEventListener('click', function () {
    var text = btn.dataset.copy;
    var original = btn.textContent;
    var showCopied = function () {
      btn.textContent = kvCopiedLabel;
      btn.classList.add('copied');
      setTimeout(function () { btn.textContent = original; btn.classList.remove('copied'); }, 1500);
    };
    // Fallback for a non-HTTPS install, an older browser without the
    // Clipboard API, or a browser that has it but denies the permission
    // (observed in practice, not just theoretical) -- a hidden, selected
    // textarea plus the legacy copy command.
    var legacyCopy = function () {
      var temp = document.createElement('textarea');
      temp.value = text;
      temp.style.position = 'fixed';
      temp.style.opacity = '0';
      document.body.appendChild(temp);
      temp.select();
      document.execCommand('copy');
      document.body.removeChild(temp);
      showCopied();
    };
    if (navigator.clipboard && window.isSecureContext) {
      navigator.clipboard.writeText(text).then(showCopied).catch(legacyCopy);
      return;
    }
    legacyCopy();
  });
});

// Jumps to whichever row is currently first/last among the ones
// pagination leaves visible -- not just the first/last in the DOM, which
// could easily be an off-page row. Same behavior as Keys/Codes and Users.
function kvScrollToRow(which) {
  const rows = [...document.querySelectorAll('#claim-links-table tbody tr')].filter(tr => tr.style.display !== 'none');
  if (rows.length === 0) return;
  const target = which === 'first' ? rows[0] : rows[rows.length - 1];
  target.scrollIntoView({ behavior: 'smooth', block: 'center' });
}

let kvClaimLinksPage = 1;
let kvClaimLinksPageSize = 50;

function kvRenderClaimLinksPage() {
  const rows = [...document.querySelectorAll('#claim-links-table tbody tr')];
  const total = rows.length;
  const pageSize = kvClaimLinksPageSize === 'all' ? Math.max(total, 1) : kvClaimLinksPageSize;
  const totalPages = Math.max(1, Math.ceil(total / pageSize));
  if (kvClaimLinksPage > totalPages) kvClaimLinksPage = totalPages;
  const start = (kvClaimLinksPage - 1) * pageSize;
  const end = kvClaimLinksPageSize === 'all' ? total : start + pageSize;
  const shown = new Set(rows.slice(start, end));
  rows.forEach(tr => { tr.style.display = shown.has(tr) ? '' : 'none'; });

  document.getElementById('claim-links-page-info').textContent = kvPageInfoTemplate.replace('{page}', kvClaimLinksPage).replace('{total}', totalPages);
  document.getElementById('claim-links-prev-btn').disabled = kvClaimLinksPage <= 1;
  document.getElementById('claim-links-next-btn').disabled = kvClaimLinksPage >= totalPages;
}

function kvClaimLinksChangePage(delta) {
  kvClaimLinksPage += delta;
  kvRenderClaimLinksPage();
}

function kvClaimLinksChangePageSize() {
  const val = document.getElementById('claim-links-page-size').value;
  kvClaimLinksPageSize = val === 'all' ? 'all' : parseInt(val, 10);
  kvClaimLinksPage = 1;
  kvRenderClaimLinksPage();
}

if (document.getElementById('claim-links-table')) {
  kvRenderClaimLinksPage();
}
</script>

<?php require __DIR__ . '/includes/layout_footer.php'; ?>
