<?php

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

use KeyLair\Auth;
use KeyLair\Csrf;
use KeyLair\Database;
use KeyLair\Helpers;
use KeyLair\ClaimLinkFactory;
use KeyLair\I18n;
use KeyLair\UserFactory;

Auth::requireEditAccess();
$pdo = Database::connection();

$linkId = (int) ($_GET['id'] ?? $_POST['id'] ?? 0);
$link = null;
$linkProducts = []; // productId => ['max_claims' => int, 'claims_used' => int]
if ($linkId > 0) {
    $linkStmt = $pdo->prepare('SELECT l.*, c.name AS campaign_name, c.default_max_claims, u.name AS user_name, u.email AS user_email FROM claim_links l LEFT JOIN campaigns c ON c.id = l.campaign_id LEFT JOIN users u ON u.id = l.user_id WHERE l.id = :id');
    $linkStmt->execute(['id' => $linkId]);
    $link = $linkStmt->fetch();
    if (!$link) {
        http_response_code(404);
        die('Claim link not found.');
    }
    $lpStmt = $pdo->prepare('SELECT product_id, max_claims, claims_used FROM claim_link_products WHERE claim_link_id = :id');
    $lpStmt->execute(['id' => $linkId]);
    foreach ($lpStmt->fetchAll() as $row) {
        $linkProducts[(int) $row['product_id']] = $row;
    }
}

$campaigns = $pdo->query('SELECT * FROM campaigns WHERE status = "active" ORDER BY name ASC')->fetchAll();
$creatorGroups = $pdo->query('SELECT * FROM creator_groups ORDER BY name ASC')->fetchAll();
// Every existing user, for the picker -- deliberately not deduplicated by
// name/email (two different people can share either), so the same name
// can appear more than once here; only the id actually tells them apart.
$allUsers = $pdo->query('SELECT id, name, email FROM users ORDER BY name ASC, id ASC')->fetchAll();
// Editing an existing link should still show products it already has, even
// if one was archived/disabled since the link was created.
$products = $link
    ? $pdo->query('SELECT * FROM products WHERE status = "active" OR id IN (' . implode(',', array_map('intval', array_keys($linkProducts) ?: [0])) . ') ORDER BY name ASC')->fetchAll()
    : $pdo->query('SELECT * FROM products WHERE status = "active" ORDER BY name ASC')->fetchAll();

$created = null;
$errors = [];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    Csrf::requireValid();

    $campaignId = !empty($_POST['campaign_id']) ? (int) $_POST['campaign_id'] : null;
    $creatorGroupId = !empty($_POST['creator_group_id']) ? (int) $_POST['creator_group_id'] : null;
    // Either an existing user was picked (user_id posted, non-empty) or
    // "+ Create new user" was left selected, in which case a fresh user
    // row is created from whatever name/email were typed (both optional --
    // neither is required to identify a user, the new id is).
    $pickedUserId = (int) ($_POST['user_id'] ?? 0);
    if ($pickedUserId > 0) {
        $userCheck = $pdo->prepare('SELECT id FROM users WHERE id = :id');
        $userCheck->execute(['id' => $pickedUserId]);
        if (!$userCheck->fetch()) {
            $pickedUserId = 0;
        }
    }
    $userId = $pickedUserId;
    if ($userId === 0) {
        $userId = UserFactory::create($_POST['new_user_name'] ?? null, $_POST['new_user_email'] ?? null);
    }
    // A plain text field now (see the field's own comment), not
    // input[type=date] -- the browser no longer guarantees this arrives
    // as a real, well-formed date, so it's validated here instead.
    $expiresAtRaw = trim($_POST['expires_at'] ?? '');
    $expiresAt = null;
    if ($expiresAtRaw !== '') {
        $parsedExpiry = DateTime::createFromFormat('Y-m-d', $expiresAtRaw);
        if (!$parsedExpiry || $parsedExpiry->format('Y-m-d') !== $expiresAtRaw) {
            $errors[] = I18n::t('claim_link_form.error_invalid_expires');
        } else {
            $expiresAt = $expiresAtRaw . ' 23:59:59';
        }
    }
    $selectedProducts = $_POST['products'] ?? []; // productId => '1' if checked
    $overrides = $_POST['max_claims_override'] ?? []; // productId => value or ''

    if (empty($selectedProducts)) {
        $errors[] = I18n::t('claim_link_form.error_no_products');
    }

    if (empty($errors)) {
        $productOverrides = [];
        foreach ($selectedProducts as $productId => $checked) {
            $productId = (int) $productId;
            $overrideRaw = trim($overrides[$productId] ?? '');
            $productOverrides[$productId] = $overrideRaw === '' ? null : max(1, (int) $overrideRaw);
        }

        if ($link) {
            $result = ClaimLinkFactory::update($linkId, $userId, $creatorGroupId, $expiresAt, $productOverrides);
            if ($result['ok']) {
                Helpers::redirect('claim_links.php?saved=1');
            }
            $errors[] = $result['error'];
        } else {
            $result = ClaimLinkFactory::create($campaignId, $userId, $creatorGroupId, $expiresAt, $productOverrides);
            if ($result['ok']) {
                $created = Helpers::baseUrl() . '/claim/' . $result['token'];
            } else {
                $errors[] = $result['error'];
            }
        }
    }
}

$pageTitle = $link ? I18n::t('claim_link_form.page_title_edit') : I18n::t('claim_link_form.page_title_new');
$activeNav = 'claim_links';
$extraAdminCss = 'admin-product-editor';
require __DIR__ . '/includes/layout_header.php';
?>
<div class="topbar"><h1><?= $link ? Helpers::e(I18n::t('claim_link_form.heading_edit')) : Helpers::e(I18n::t('claim_link_form.heading_new')) ?></h1></div>

<?php if (!empty($errors)): ?>
  <div class="form-section" style="border-color:var(--danger); margin-bottom:16px;">
    <?php foreach ($errors as $err): ?><p style="color:var(--danger); font-size:13px; margin:0;"><?= Helpers::e($err) ?></p><?php endforeach; ?>
  </div>
<?php endif; ?>

<?php if ($created): ?>
  <div class="form-section" style="border-color:var(--signal-dim); margin-bottom:16px;">
    <p style="color:var(--signal); font-size:14px; font-weight:600; margin:0 0 10px;"><?= Helpers::e(I18n::t('claim_link_form.created_notice')) ?></p>
    <div style="display:flex; gap:8px; align-items:center;">
      <input type="text" readonly value="<?= Helpers::e($created) ?>" onclick="this.select();"
             style="flex:1; background:var(--bg-void); border:1px solid var(--line); color:var(--text-primary); font-family:var(--font-mono); font-size:12.5px; padding:9px 12px; border-radius:8px;">
      <button type="button" class="btn btn-primary" onclick="navigator.clipboard.writeText('<?= Helpers::e($created) ?>'); this.textContent=<?= json_encode(I18n::t('claim_link_form.copied_label'), JSON_HEX_APOS | JSON_HEX_QUOT) ?>;"><?= Helpers::e(I18n::t('claim_link_form.copy_button')) ?></button>
    </div>
    <p style="margin:12px 0 0;"><a href="claim_links.php" style="color:var(--signal); font-size:13px;"><?= Helpers::e(I18n::t('claim_link_form.view_all_link')) ?></a> · <a href="claim_link_form.php" style="color:var(--signal); font-size:13px;"><?= Helpers::e(I18n::t('claim_link_form.create_another_link')) ?></a></p>
  </div>
<?php elseif (!$link && empty($products)): ?>
  <div class="panel">
    <p style="color:var(--text-muted); font-size:13px;">
      <?= Helpers::e(I18n::t('claim_link_form.no_products_notice')) ?>
      <a href="product_form.php" style="color:var(--signal);"><?= Helpers::e(I18n::t('claim_link_form.create_product_link')) ?></a>
    </p>
  </div>
<?php else: ?>
<form method="post" class="form-shell">
  <?= Csrf::field() ?>
  <?php if ($link): ?><input type="hidden" name="id" value="<?= (int) $linkId ?>"><?php endif; ?>

  <div class="form-section">
    <p class="form-section-title"><?= Helpers::e(I18n::t('claim_link_form.section_recipient')) ?></p>
    <div class="field-row">
      <div class="field">
        <label><?= Helpers::e(I18n::t('claim_link_form.campaign_label')) ?> <span style="color:var(--text-faint); font-weight:400;"><?= Helpers::e(I18n::t('claim_link_form.optional_suffix')) ?></span></label>
        <?php if ($link): ?>
          <p style="font-size:13.5px; margin:8px 0 0;"><?= $link['campaign_name'] !== null ? Helpers::e($link['campaign_name']) : Helpers::e(I18n::t('claim_link_form.no_campaign')) ?> <span style="color:var(--text-faint);"><?= Helpers::e(I18n::t('claim_link_form.fixed_at_creation')) ?></span></p>
        <?php else: ?>
          <select name="campaign_id">
            <option value=""><?= Helpers::e(I18n::t('claim_link_form.no_campaign')) ?></option>
            <?php foreach ($campaigns as $c): ?>
              <option value="<?= (int) $c['id'] ?>"><?= Helpers::e($c['name']) ?> <?= Helpers::e(sprintf(I18n::t('claim_link_form.campaign_option_limit'), (int) $c['default_max_claims'])) ?></option>
            <?php endforeach; ?>
          </select>
        <?php endif; ?>
      </div>
      <div class="field" style="position:relative;">
        <label><?= Helpers::e(I18n::t('claim_link_form.user_label')) ?></label>
        <?php
          $createNewUserLabel = I18n::t('claim_link_form.create_new_user_option');
          $userOptions = [];
          $selectedUserLabel = $createNewUserLabel;
          foreach ($allUsers as $u) {
              $userLabel = $u['name'] !== null ? $u['name'] : I18n::t('claim_link_form.unnamed_user');
              $userLabel .= $u['email'] !== null ? ' (' . $u['email'] . ')' : '';
              $userLabel .= ' — #' . $u['id'];
              $userOptions[] = ['id' => (int) $u['id'], 'label' => $userLabel];
              if ($link && (int) ($link['user_id'] ?? 0) === (int) $u['id']) {
                  $selectedUserLabel = $userLabel;
              }
          }
        ?>
        <input type="hidden" name="user_id" id="user-picker-value" value="<?= $link ? (int) ($link['user_id'] ?? 0) : '' ?>">
        <input type="text" id="user-picker-search" autocomplete="off" placeholder="<?= Helpers::e(sprintf(I18n::t('claim_link_form.user_search_placeholder'), $createNewUserLabel)) ?>" value="<?= Helpers::e($selectedUserLabel) ?>">
        <div id="user-picker-list" style="display:none; position:absolute; z-index:20; top:100%; left:0; right:0; margin-top:4px; max-height:240px; overflow-y:auto; background:var(--bg-panel); border:1px solid var(--line); border-radius:8px; box-shadow:0 8px 24px rgba(0,0,0,0.35);"></div>
      </div>
    </div>
    <div class="field-row" id="new-user-fields" style="<?= ($link && !empty($link['user_id'])) ? 'display:none;' : '' ?>">
      <div class="field">
        <label><?= Helpers::e(I18n::t('claim_link_form.new_user_name_label')) ?> <span style="color:var(--text-faint); font-weight:400;"><?= Helpers::e(I18n::t('claim_link_form.optional_suffix')) ?></span></label>
        <input type="text" name="new_user_name" placeholder="<?= Helpers::e(I18n::t('claim_link_form.new_user_name_placeholder')) ?>">
      </div>
      <div class="field">
        <label><?= Helpers::e(I18n::t('claim_link_form.new_user_email_label')) ?> <span style="color:var(--text-faint); font-weight:400;"><?= Helpers::e(I18n::t('claim_link_form.optional_suffix')) ?></span></label>
        <input type="email" name="new_user_email" placeholder="<?= Helpers::e(I18n::t('claim_link_form.new_user_email_placeholder')) ?>">
      </div>
    </div>
    <div class="field-row">
      <div class="field">
        <label><?= Helpers::e(I18n::t('claim_link_form.creator_group_label')) ?> <?= Helpers::e(I18n::t('claim_link_form.optional_suffix')) ?></label>
        <select name="creator_group_id">
          <option value=""><?= Helpers::e(I18n::t('claim_link_form.creator_group_none')) ?></option>
          <?php foreach ($creatorGroups as $g): ?>
            <option value="<?= (int) $g['id'] ?>" <?= ($link && (int) $link['creator_group_id'] === (int) $g['id']) ? 'selected' : '' ?>><?= Helpers::e($g['name']) ?><?= $g['default_max_claims'] !== null ? ' ' . Helpers::e(sprintf(I18n::t('claim_link_form.creator_group_option_limit'), (int) $g['default_max_claims'])) : '' ?></option>
          <?php endforeach; ?>
        </select>
      </div>
      <div class="field">
        <label><?= Helpers::e(I18n::t('claim_link_form.expires_label')) ?> <?= Helpers::e(I18n::t('claim_link_form.optional_suffix')) ?></label>
        <!-- input[type=date] again -- stays a real date field with the
             native picker, per instruction, not the plain text field
             tried in between. Three earlier attempts at fitting it to
             the same box as every other field (max-width, an
             overflow:hidden wrapper, a smaller font) still weren't
             enough on the browser this was tested on. appearance:none
             is a different lever than any of those -- it asks the
             browser to stop drawing its own native chrome sizing for
             this control at all (closer to how a text input renders),
             rather than trying to constrain that native chrome's box
             from the outside. line-height alone (tried next) still
             wasn't enough either -- empty still rendered shorter than
             filled, so whatever's actually driving the taller filled
             height (likely the calendar icon's own fixed size) is taller
             than that line-height, meaning only the empty state was ever
             bound by it. An explicit height, !important since input
             elements' UA styles fight a plain height here otherwise,
             pins both states to the same number no matter what's
             inside. -->
        <div style="display:flex; gap:8px; align-items:center;">
          <input type="date" name="expires_at" id="expires-at-input" style="-webkit-appearance:none; appearance:none; height:41px !important; box-sizing:border-box; flex:1;" value="<?= $link && $link['expires_at'] ? Helpers::e(substr($link['expires_at'], 0, 10)) : '' ?>">
          <!-- Mobile browsers don't show a native "clear" control on
               input[type=date] the way desktop ones do -- tapping the
               field only ever opens the picker, with no way to get back
               to empty ("no expiration") once a date's been set. -->
          <button type="button" class="btn btn-ghost" style="flex-shrink:0; padding:10px 14px;" onclick="document.getElementById('expires-at-input').value='';"><?= Helpers::e(I18n::t('claim_link_form.clear_button')) ?></button>
        </div>
      </div>
    </div>
  </div>

  <div class="form-section">
    <p class="form-section-title"><?= Helpers::e(I18n::t('claim_link_form.section_products')) ?></p>
    <p class="form-section-hint"><?= Helpers::e(I18n::t('claim_link_form.products_hint')) ?> <?= $link ? Helpers::e(I18n::t('claim_link_form.products_hint_edit_suffix')) : '' ?></p>
    <?php foreach ($products as $p): ?>
      <?php
        $existing = $linkProducts[(int) $p['id']] ?? null;
        $removeConfirmAttr = '';
        if ($existing && (int) $existing['claims_used'] > 0) {
            $removeConfirmAttr = 'onclick="return confirm(' . json_encode(I18n::t('claim_link_form.remove_claimed_product_confirm_js'), JSON_HEX_APOS | JSON_HEX_QUOT) . ');"';
        }
      ?>
      <div style="display:flex; align-items:center; gap:12px; padding:10px 0; border-bottom:1px solid var(--line);">
        <label style="display:flex; align-items:center; gap:8px; flex:1; cursor:pointer; margin:0;">
          <input type="checkbox" name="products[<?= (int) $p['id'] ?>]" value="1" style="width:auto;" <?= $existing ? 'checked' : '' ?> <?= $removeConfirmAttr ?>>
          <span style="font-size:13.5px; color:var(--text-primary);"><?= Helpers::e($p['name']) ?></span>
          <?php if ($existing): ?><span style="font-size:11px; color:var(--text-faint);"><?= Helpers::e(sprintf(I18n::t('claim_link_form.claims_used_suffix'), (int) $existing['claims_used'])) ?></span><?php endif; ?>
        </label>
        <input type="number" name="max_claims_override[<?= (int) $p['id'] ?>]" min="1" placeholder="<?= Helpers::e(I18n::t('claim_link_form.override_placeholder')) ?>" value="<?= $existing ? (int) $existing['max_claims'] : '' ?>" style="width:100px; margin:0;">
      </div>
    <?php endforeach; ?>
  </div>

  <div class="form-actions">
    <a href="claim_links.php" class="btn btn-ghost" style="text-decoration:none;"><?= Helpers::e(I18n::t('claim_link_form.cancel_button')) ?></a>
    <button type="submit" class="btn btn-primary"><?= $link ? Helpers::e(I18n::t('claim_link_form.save_changes_button')) : Helpers::e(I18n::t('claim_link_form.create_link_button')) ?></button>
  </div>
</form>
<?php endif; ?>

<script>
(function () {
  var users = <?= json_encode($userOptions) ?>;
  var createOption = { id: '', label: <?= json_encode($createNewUserLabel, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?> };
  var search = document.getElementById('user-picker-search');
  var value = document.getElementById('user-picker-value');
  var list = document.getElementById('user-picker-list');
  var newUserFields = document.getElementById('new-user-fields');
  var highlighted = -1;
  var rendered = [];

  function applySelection(option) {
    value.value = option.id;
    search.value = option.label;
    newUserFields.style.display = option.id === '' ? 'flex' : 'none';
    closeList();
  }

  function closeList() {
    list.style.display = 'none';
    highlighted = -1;
  }

  function render(query) {
    var q = query.trim().toLowerCase();
    rendered = [createOption].concat(users).filter(function (u) {
      return q === '' || u.label.toLowerCase().indexOf(q) !== -1;
    });
    list.innerHTML = '';
    if (rendered.length === 0) {
      list.style.display = 'none';
      return;
    }
    rendered.forEach(function (u, i) {
      var row = document.createElement('div');
      row.textContent = u.label;
      row.dataset.index = i;
      row.style.cssText = 'padding:8px 12px; font-size:13px; color:var(--text-primary); cursor:pointer;' + (u.id === '' ? ' color:var(--signal);' : '');
      row.addEventListener('mousedown', function (e) {
        // mousedown (not click) fires before the search input's blur, so
        // the list is still open and readable when this handler runs.
        e.preventDefault();
        applySelection(u);
      });
      row.addEventListener('mouseenter', function () { setHighlight(i); });
      list.appendChild(row);
    });
    setHighlight(0);
    list.style.display = 'block';
  }

  function setHighlight(i) {
    if (rendered[highlighted]) {
      list.children[highlighted].style.background = 'transparent';
    }
    highlighted = i;
    if (rendered[highlighted]) {
      list.children[highlighted].style.background = 'var(--bg-void)';
    }
  }

  // Selects the whole field on focus so the first keystroke replaces the
  // current label (e.g. "+ Create new user", or a previously picked
  // user's name) instead of appending to it -- without this, typing a
  // search term while the field still reads "+ Create new user" produces
  // a query like "+ create new userbatch" that matches nothing.
  search.addEventListener('focus', function () { search.select(); render(''); });
  search.addEventListener('input', function () { render(search.value); });
  search.addEventListener('blur', function () { closeList(); });
  search.addEventListener('keydown', function (e) {
    if (list.style.display === 'none') return;
    if (e.key === 'ArrowDown') { e.preventDefault(); setHighlight(Math.min(highlighted + 1, rendered.length - 1)); }
    else if (e.key === 'ArrowUp') { e.preventDefault(); setHighlight(Math.max(highlighted - 1, 0)); }
    else if (e.key === 'Enter') { e.preventDefault(); if (rendered[highlighted]) applySelection(rendered[highlighted]); }
    else if (e.key === 'Escape') { closeList(); }
  });
})();
</script>

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