<?php

declare(strict_types=1);

/**
 * Community moderation dashboard — "/admin". Admin/moderator only.
 * Lets a moderator edit the marketing-site link, flip the anti-bot registration
 * lock, and suspend / reactivate member accounts. All writes are CSRF-guarded
 * and use Post-Redirect-Get so a refresh never re-runs an action.
 */

require __DIR__ . '/_shell.php';
require __DIR__ . '/_update.php';

use PpPhp\Core\Security;
use PpPhp\Core\DB;

$b = forum_base();

// ── Gate ──────────────────────────────────────────────────────────────
if (!forum_logged_in()) {
    header('Location: ' . $b . '/login');
    exit;
}
if (!forum_is_admin()) {
    forum_head('Admin — PPPHP Community', '<meta name="robots" content="noindex,nofollow">');
    echo '<div class="fx-empty"><i class="bi bi-shield-lock" style="font-size:34px;opacity:.4"></i>'
        . '<p>You don\'t have access to the moderation area.</p>'
        . '<p><a class="fx-tag" href="' . $b . '/">← Back to the community</a></p></div>';
    forum_foot();
    exit;
}

// ── POST actions (CSRF + Post-Redirect-Get) ───────────────────────────
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
    $flash = '';
    if (!Security::CSRF()->Check((string) ($_POST['_token'] ?? ''))) {
        $flash = 'Your session expired — please try again.';
    } else {
        $act = (string) ($_POST['act'] ?? '');
        if ($act === 'save_settings') {
            $murl = trim((string) ($_POST['marketing_url'] ?? ''));
            if ($murl !== '' && !preg_match('#^https?://#i', $murl)) {
                $murl = 'https://' . $murl;                 // be forgiving about the scheme
            }
            forum_set_setting('marketing_url', $murl);
            forum_set_setting('marketing_label', trim((string) ($_POST['marketing_label'] ?? '')) ?: 'Explore PPPHP');
            forum_set_setting('registration_locked', isset($_POST['registration_locked']) ? '1' : '0');
            // Unified analytics: report this forum's traffic to a PPPHP Visitor console.
            $asite = trim((string) ($_POST['analytics_site'] ?? ''));
            forum_set_setting('analytics_site', preg_match('/^st_[a-z0-9]+$/i', $asite) ? $asite : '');
            $aurl = trim((string) ($_POST['analytics_url'] ?? ''));
            if ($aurl !== '' && !preg_match('#^https?://#i', $aurl)) $aurl = 'https://' . $aurl;
            forum_set_setting('analytics_url', $aurl);
            $flash = 'Settings saved.';
        } elseif ($act === 'update_upload') {
            @set_time_limit(0);
            @ignore_user_abort(true);
            $res = forum_update_apply_upload($_FILES['update_pkg'] ?? []);
            $_SESSION['__fx_update'] = $res;
            $flash = (string) ($res['message'] ?? 'Update finished.');
        } elseif ($act === 'suspend' || $act === 'activate') {
            $target = dbRow('SELECT id, username, role FROM qa_users WHERE id = ?', [(int) ($_POST['user_id'] ?? 0)]);
            if (!$target) {
                $flash = 'That member no longer exists.';
            } elseif (strcasecmp((string) $target['username'], forum_current_username()) === 0) {
                $flash = "You can't change your own status.";
            } elseif ($act === 'suspend' && in_array((string) $target['role'], ['admin', 'superadmin'], true)) {
                $flash = "Admins and superadmins can't be suspended.";
            } else {
                DB::Query('UPDATE qa_users SET status = ? WHERE id = ?', [$act === 'suspend' ? 'suspended' : 'active', (int) $target['id']]);
                $flash = ($act === 'suspend' ? 'Suspended @' : 'Reactivated @') . $target['username'] . '.';
            }
        } elseif ($act === 'del_question' || $act === 'restore_question') {
            // Soft-delete: hides the question everywhere (deleted_at IS NULL gates every
            // public query) but keeps the row so it can be restored. NOW() keeps the
            // timestamp on the DB clock (PHP↔MySQL skew never enters the comparison).
            $qid = (int) ($_POST['qid'] ?? 0);
            if ($qid > 0) {
                DB::Query('UPDATE qa_questions SET deleted_at = ' . ($act === 'del_question' ? 'NOW()' : 'NULL') . ' WHERE id = ?', [$qid]);
                $flash = $act === 'del_question' ? 'Question removed from the community.' : 'Question restored.';
            }
        } elseif ($act === 'del_answer' || $act === 'restore_answer') {
            $aid = (int) ($_POST['aid'] ?? 0);
            if ($aid > 0) {
                DB::Query('UPDATE qa_answers SET deleted_at = ' . ($act === 'del_answer' ? 'NOW()' : 'NULL') . ' WHERE id = ?', [$aid]);
                $flash = $act === 'del_answer' ? 'Answer removed.' : 'Answer restored.';
            }
        }
    }
    $_SESSION['__fx_admin_flash'] = $flash;
    header('Location: ' . $b . '/admin');
    exit;
}

// ── Data for the view ─────────────────────────────────────────────────
$flash = (string) ($_SESSION['__fx_admin_flash'] ?? '');
unset($_SESSION['__fx_admin_flash']);

$mk       = forum_marketing();
$regLock  = forum_registration_locked();
$csrf     = forum_csrf();

$uq = trim((string) ($_GET['u'] ?? ''));
$uWhere = ''; $uParams = [];
if ($uq !== '') {
    $uWhere = 'WHERE (username LIKE ? OR display_name LIKE ? OR email LIKE ?)';
    $like = '%' . $uq . '%';
    $uParams = [$like, $like, $like];
}
// Members — paginated (the list used to hard-cap at 100 with no way to page past it).
$uPage  = max(1, (int) ($_GET['page'] ?? 1));
$uPer   = 25;
$uTotal = (int) (dbRow("SELECT COUNT(*) AS c FROM qa_users {$uWhere}", $uParams)['c'] ?? 0);
$uPage  = min($uPage, max(1, (int) ceil($uTotal / $uPer)));
$uOff   = ($uPage - 1) * $uPer;
$users = dbAll(
    "SELECT id, username, display_name, email, reputation, role, status, created_at
       FROM qa_users {$uWhere}
      ORDER BY (status = 'suspended') DESC, id DESC
      LIMIT {$uPer} OFFSET {$uOff}",
    $uParams
);
$counts = dbRow("SELECT COUNT(*) AS total, SUM(status = 'suspended') AS suspended FROM qa_users") ?: ['total' => 0, 'suspended' => 0];

// Recent content for moderation (newest first, including already-removed rows so they can be restored).
$recentQ = dbAll(
    "SELECT q.id, q.title, q.slug, q.vote_score, q.answer_count, q.created_at, q.deleted_at, u.username
       FROM qa_questions q LEFT JOIN qa_users u ON u.id = q.author_id
      ORDER BY q.created_at DESC LIMIT 12"
) ?: [];
$recentA = dbAll(
    "SELECT a.id, a.question_id, a.vote_score, a.is_accepted, a.created_at, a.deleted_at, u.username, q.title, q.slug
       FROM qa_answers a
       LEFT JOIN qa_users u ON u.id = a.author_id
       LEFT JOIN qa_questions q ON q.id = a.question_id
      ORDER BY a.created_at DESC LIMIT 12"
) ?: [];

forum_head('Moderation — PPPHP Community', '<meta name="robots" content="noindex,nofollow">');
?>
<a class="fx-back" href="<?= $b ?>/"><i class="bi bi-arrow-left"></i> Back to the community</a>
<div class="fx-headrow">
  <div>
    <h1 class="fx-h1"><i class="bi bi-shield-lock"></i> Moderation</h1>
    <p class="fx-sub"><?= number_format((int) $counts['total']) ?> member<?= (int) $counts['total'] === 1 ? '' : 's' ?> · <?= number_format((int) ($counts['suspended'] ?? 0)) ?> suspended</p>
  </div>
</div>

<?php if ($flash !== ''): ?><div class="fx-flash"><i class="bi bi-check-circle"></i> <?= forum_e($flash) ?></div><?php endif; ?>

<div class="fx-admin-grid">

  <!-- Site settings -->
  <section class="fx-admin-card">
    <h2><i class="bi bi-sliders"></i> Site settings</h2>
    <p class="fx-sub">The marketing-site link shown in the footer, and the anti-bot registration switch.</p>
    <form method="post" action="<?= $b ?>/admin">
      <input type="hidden" name="_token" value="<?= forum_e($csrf) ?>">
      <input type="hidden" name="act" value="save_settings">
      <div class="fx-field">
        <label>Marketing link — button text</label>
        <input class="fx-input" type="text" name="marketing_label" value="<?= forum_e($mk['label']) ?>" placeholder="Explore PPPHP" maxlength="60">
      </div>
      <div class="fx-field">
        <label>Marketing link — URL <span class="hint">shown as a button in the footer</span></label>
        <input class="fx-input" type="url" name="marketing_url" value="<?= forum_e($mk['url']) ?>" placeholder="https://ppradhan.com">
      </div>
      <div class="fx-toggle-row">
        <div class="t"><b>Lock new registrations</b><span>Temporarily stop new sign-ups (use during a bot/spam wave).</span></div>
        <label class="fx-toggle"><input type="checkbox" name="registration_locked" value="1" <?= $regLock ? 'checked' : '' ?>> <?= $regLock ? 'Locked' : 'Open' ?></label>
      </div>
      <div class="fx-field">
        <label>Visitor analytics — Site ID <span class="hint">from your PPPHP Visitor console → Properties → Add property (e.g. <code>st_ab12cd34</code>). Blank = off.</span></label>
        <input class="fx-input" type="text" name="analytics_site" value="<?= forum_e(forum_setting('analytics_site', '')) ?>" placeholder="st_xxxxxxxx" maxlength="40">
      </div>
      <div class="fx-field">
        <label>Visitor analytics — Collector URL <span class="hint">leave blank to use the main licence server</span></label>
        <input class="fx-input" type="url" name="analytics_url" value="<?= forum_e(forum_setting('analytics_url', '')) ?>" placeholder="https://ppphp.ppradhan.com/api/analytics/collect">
      </div>
      <div style="margin-top:16px"><button class="fx-btn primary" type="submit"><i class="bi bi-check-lg"></i> Save settings</button></div>
    </form>
  </section>

  <!-- Software updates -->
  <section class="fx-admin-card">
    <h2><i class="bi bi-box-arrow-in-up"></i> Software updates</h2>
    <p class="fx-sub">Update this community portal in place — no reinstall. Download the signed update package from the PPPHP console (Deliverables → Community Installer), then upload it here. It is verified against the pinned publisher key before anything changes; your members, posts, uploads and config are never touched, and a restore point is saved first.</p>
    <?php $up = $_SESSION['__fx_update'] ?? null; unset($_SESSION['__fx_update']); ?>
    <div class="fx-field" style="gap:6px;margin-bottom:6px">
      <div><b>Installed version:</b> <code><?= forum_e(forum_update_version()) ?></code></div>
    </div>
    <?php if (is_array($up)): ?>
      <div class="fx-flash" style="align-items:flex-start;<?= empty($up['ok']) ? 'background:color-mix(in srgb,#dc2626 12%,transparent);border-color:color-mix(in srgb,#dc2626 30%,transparent)' : '' ?>">
        <i class="bi bi-<?= !empty($up['ok']) ? 'check-circle' : 'exclamation-triangle' ?>"></i>
        <div><?= forum_e((string) ($up['message'] ?? '')) ?></div>
      </div>
    <?php endif; ?>
    <?php if (!forum_update_enabled()): ?>
      <p class="fx-sub" style="margin-top:8px"><i class="bi bi-info-circle"></i>
        Updates aren't enabled for this install (no publisher key is pinned). Download a fresh copy of the portal from the PPPHP console and re-deploy it once — new downloads have updates enabled.</p>
    <?php else: ?>
      <form method="post" action="<?= $b ?>/admin" enctype="multipart/form-data" style="margin-top:10px">
        <input type="hidden" name="_token" value="<?= forum_e($csrf) ?>">
        <input type="hidden" name="act" value="update_upload">
        <div class="fx-field">
          <label>Update package <span class="hint">the signed <code>.zip</code> you downloaded from the console</span></label>
          <input class="fx-input" type="file" name="update_pkg" accept=".zip,application/zip" required>
        </div>
        <div style="margin-top:12px">
          <button class="fx-btn primary" type="submit" onclick="return confirm('Apply this update package? It is verified first, a restore point is saved, and your data is untouched.')"><i class="bi bi-box-arrow-in-up"></i> Upload &amp; apply update</button>
        </div>
      </form>
    <?php endif; ?>
  </section>

  <!-- Members -->
  <!-- Content moderation -->
  <section class="fx-admin-card fx-admin-wide">
    <h2><i class="bi bi-chat-square-text"></i> Content moderation</h2>
    <p class="fx-sub">Remove spam or abusive posts. Removing is a soft-delete — the post disappears from the community everywhere, and you can restore it here.</p>
    <div class="fx-mod-grid">
      <div>
        <h3 class="fx-mod-h">Recent questions</h3>
        <?php if (!$recentQ): ?><p class="fx-sub">No questions yet.</p><?php else: ?>
        <ul class="fx-mod-list">
          <?php foreach ($recentQ as $q): $gone = !empty($q['deleted_at']); ?>
          <li class="fx-mod-item<?= $gone ? ' is-gone' : '' ?>">
            <div class="fx-mod-main">
              <a href="<?= $b ?>/q/<?= (int) $q['id'] ?>/<?= forum_e($q['slug'] ?? '') ?>" target="_blank" rel="noopener"><?= forum_e($q['title'] ?: '(untitled)') ?></a>
              <span class="fx-mod-meta">@<?= forum_e($q['username'] ?: 'unknown') ?> · <?= (int) $q['vote_score'] ?> votes · <?= (int) $q['answer_count'] ?> answers · <?= forum_e(forum_ago($q['created_at'])) ?><?= $gone ? ' · <b>removed</b>' : '' ?></span>
            </div>
            <form method="post" action="<?= $b ?>/admin" style="margin:0">
              <input type="hidden" name="_token" value="<?= forum_e($csrf) ?>">
              <input type="hidden" name="qid" value="<?= (int) $q['id'] ?>">
              <input type="hidden" name="act" value="<?= $gone ? 'restore_question' : 'del_question' ?>">
              <button class="fx-btn fx-btn-sm <?= $gone ? '' : 'danger' ?>" type="submit"<?= $gone ? '' : ' onclick="return confirm(\'Remove this question from the community?\')"' ?>><i class="bi bi-<?= $gone ? 'arrow-counterclockwise' : 'trash' ?>"></i> <?= $gone ? 'Restore' : 'Remove' ?></button>
            </form>
          </li>
          <?php endforeach; ?>
        </ul>
        <?php endif; ?>
      </div>
      <div>
        <h3 class="fx-mod-h">Recent answers</h3>
        <?php if (!$recentA): ?><p class="fx-sub">No answers yet.</p><?php else: ?>
        <ul class="fx-mod-list">
          <?php foreach ($recentA as $a): $gone = !empty($a['deleted_at']); ?>
          <li class="fx-mod-item<?= $gone ? ' is-gone' : '' ?>">
            <div class="fx-mod-main">
              <a href="<?= $b ?>/q/<?= (int) $a['question_id'] ?>/<?= forum_e($a['slug'] ?? '') ?>" target="_blank" rel="noopener"><?= forum_e($a['title'] ?: '(question)') ?></a>
              <span class="fx-mod-meta">@<?= forum_e($a['username'] ?: 'unknown') ?> · <?= (int) $a['vote_score'] ?> votes<?= !empty($a['is_accepted']) ? ' · accepted' : '' ?> · <?= forum_e(forum_ago($a['created_at'])) ?><?= $gone ? ' · <b>removed</b>' : '' ?></span>
            </div>
            <form method="post" action="<?= $b ?>/admin" style="margin:0">
              <input type="hidden" name="_token" value="<?= forum_e($csrf) ?>">
              <input type="hidden" name="aid" value="<?= (int) $a['id'] ?>">
              <input type="hidden" name="act" value="<?= $gone ? 'restore_answer' : 'del_answer' ?>">
              <button class="fx-btn fx-btn-sm <?= $gone ? '' : 'danger' ?>" type="submit"<?= $gone ? '' : ' onclick="return confirm(\'Remove this answer?\')"' ?>><i class="bi bi-<?= $gone ? 'arrow-counterclockwise' : 'trash' ?>"></i> <?= $gone ? 'Restore' : 'Remove' ?></button>
            </form>
          </li>
          <?php endforeach; ?>
        </ul>
        <?php endif; ?>
      </div>
    </div>
  </section>

  <section class="fx-admin-card">
    <h2><i class="bi bi-people"></i> Members</h2>
    <p class="fx-sub">Suspend an abusive or bot account (blocks posting, answering &amp; voting), or reactivate one.</p>
    <form class="fx-admin-filter" method="get" action="<?= $b ?>/admin" role="search">
      <input class="fx-input" type="search" name="u" value="<?= forum_e($uq) ?>" placeholder="Search by name, @username or email…" style="max-width:340px">
      <button class="fx-btn" type="submit"><i class="bi bi-search"></i> Search</button>
      <?php if ($uq !== ''): ?><a class="fx-btn" href="<?= $b ?>/admin">Clear</a><?php endif; ?>
    </form>
    <?php if (!$users): ?>
      <p class="fx-sub">No members match “<?= forum_e($uq) ?>”.</p>
    <?php else: ?>
    <div class="fx-utable-wrap"><table class="fx-utable">
      <thead><tr><th>Member</th><th>Role</th><th>Rep</th><th>Status</th><th style="text-align:right">Action</th></tr></thead>
      <tbody>
      <?php foreach ($users as $u):
        $isSelf  = strcasecmp((string) $u['username'], forum_current_username()) === 0;
        $isAdmin = in_array((string) $u['role'], ['admin', 'superadmin'], true);
        $susp    = (string) $u['status'] === 'suspended';
      ?>
        <tr>
          <td>
            <a class="fx-user" href="<?= $b ?>/u/<?= rawurlencode((string) $u['username']) ?>" style="gap:8px">
              <?= forum_avatar(forum_initials((string) ($u['display_name'] ?: $u['username'])), (string) ($u['email'] ?? ''), 48) ?>
              <span><span class="fx-uname"><?= forum_e($u['display_name'] ?: $u['username']) ?></span><br><span style="font-size:12px;color:var(--fx-muted)">@<?= forum_e($u['username']) ?></span></span>
            </a>
          </td>
          <td><?= forum_e($u['role'] ?: 'member') ?></td>
          <td><?= number_format((int) $u['reputation']) ?></td>
          <td><span class="fx-ustatus <?= $susp ? 'suspended' : 'active' ?>"><?= $susp ? 'Suspended' : 'Active' ?></span></td>
          <td style="text-align:right">
            <?php if ($isSelf): ?>
              <span class="fx-sub" style="margin:0">You</span>
            <?php elseif ($isAdmin && !$susp): ?>
              <span class="fx-sub" style="margin:0">Protected</span>
            <?php else: ?>
              <form method="post" action="<?= $b ?>/admin" style="display:inline">
                <input type="hidden" name="_token" value="<?= forum_e($csrf) ?>">
                <input type="hidden" name="user_id" value="<?= (int) $u['id'] ?>">
                <input type="hidden" name="act" value="<?= $susp ? 'activate' : 'suspend' ?>">
                <button class="fx-btn <?= $susp ? '' : 'danger' ?>" type="submit"<?= $susp ? '' : ' onclick="return confirm(\'Suspend @' . forum_e($u['username']) . '? They won\\\'t be able to post, answer or vote.\')"' ?>>
                  <i class="bi bi-<?= $susp ? 'arrow-counterclockwise' : 'slash-circle' ?>"></i> <?= $susp ? 'Reactivate' : 'Suspend' ?>
                </button>
              </form>
            <?php endif; ?>
          </td>
        </tr>
      <?php endforeach; ?>
      </tbody>
    </table></div>
    <p class="fx-sub" style="margin:.7rem 0 .2rem">Showing <?= count($users) ?> of <?= number_format($uTotal) ?> member<?= $uTotal === 1 ? '' : 's' ?></p>
    <?php forum_pagination($uPage, $uPer, $uTotal, $b . '/admin', $uq !== '' ? ['u' => $uq] : []); ?>
    <?php endif; ?>
  </section>

</div>
<?php forum_foot(); ?>
