<?php
declare(strict_types=1);

/**
 * /admin/users/resend_activation.php
 * Адмін: повторно надіслати лист активації.
 *
 * Підтримує різні схеми БД:
 * - is_active / active / verified / email_verified ...
 * - activation_token_hash (хеш sha256) або activation_token / verify_token (сирий токен)
 *
 * Якщо в БД є *_hash — зберігаємо sha256(token), а в листі відправляємо сирий token.
 *
 * ОНОВЛЕНО:
 * - SEO noindex (адмінка) + X-Robots-Tag
 * - safe backUrl: back з POST (пріоритет) або referer, але тільки /admin/users/ або /admin/users.php
 * - 303 redirect
 * - без leak $e->getMessage()
 * - якщо користувач вже активований — не ресендимо, показуємо “Вже активований”
 * - більш акуратне визначення active/token/activated_at/sent_at колонок (через admin_* якщо є)
 */

require_once __DIR__ . '/../../includes/start.php';
require_role(['admin']);

require_once __DIR__ . '/../_helpers.php';
require_once __DIR__ . '/../_csrf.php';
require_once __DIR__ . '/../../includes/mailer.php';

$pdo = db();

/* =========================
   SEO: адмінка НЕ індексується
========================= */
$meta_robots = 'noindex, nofollow, noarchive, nosnippet';
if (!headers_sent()) {
    header('X-Robots-Tag: noindex, nofollow, noarchive, nosnippet', true);
}

/* fallback h() */
if (!function_exists('h')) {
    function h(?string $s): string { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
}

/* =========================
   Helpers: safe back url
========================= */
if (!function_exists('admin_norm_local_url')) {
    function admin_norm_local_url(string $raw): string {
        $raw = trim($raw);
        if ($raw === '') return '';

        // якщо абсолютний URL — лишаємо тільки path+query
        if (preg_match('~^https?://~i', $raw)) {
            $p = parse_url($raw);
            $path = (string)($p['path'] ?? '');
            $q = isset($p['query']) && (string)$p['query'] !== '' ? ('?' . (string)$p['query']) : '';
            $raw = $path . $q;
        }

        if ($raw === '' || $raw[0] !== '/') return '';
        if (str_starts_with($raw, '//')) return '';

        return $raw;
    }
}

function admin_users_back_url(): string {
    $default = '/admin/users/';

    // 1) back з POST
    $postBack = admin_norm_local_url((string)($_POST['back'] ?? ''));
    if ($postBack !== '') {
        $path = (string)parse_url($postBack, PHP_URL_PATH);
        if ($path === '/admin/users/' || $path === '/admin/users.php') return $postBack;
    }

    // 2) referer fallback
    $ref = admin_norm_local_url((string)($_SERVER['HTTP_REFERER'] ?? ''));
    if ($ref !== '') {
        $path = (string)parse_url($ref, PHP_URL_PATH);
        if ($path === '/admin/users/' || $path === '/admin/users.php') return $ref;
    }

    return $default;
}
$backUrl = admin_users_back_url();

/* =========================
   Method + CSRF + input
========================= */
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    http_response_code(405);
    exit('Method Not Allowed');
}

if (!admin_csrf_verify()) {
    admin_flash_set('danger', admin_tt('csrf_bad', 'CSRF помилка', 'CSRF ошибка', 'CSRF error'));
    header('Location: ' . $backUrl, true, 303);
    exit;
}

$id = (int)($_POST['id'] ?? 0);
if ($id <= 0) {
    admin_flash_set('danger', admin_tt('admin_bad_id', 'Невірний ID', 'Неверный ID', 'Bad ID'));
    header('Location: ' . $backUrl, true, 303);
    exit;
}

/* =========================
   DB helpers (compat)
========================= */
if (!function_exists('db_has_column')) {
    function db_has_column(PDO $pdo, string $table, string $col): bool {
        try {
            $st = $pdo->prepare('SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ? AND column_name = ? LIMIT 1');
            $st->execute([$table, $col]);
            return (bool)$st->fetchColumn();
        } catch (Throwable $e) {
            return false;
        }
    }
}
if (!function_exists('col_exists')) {
    function col_exists(PDO $pdo, string $table, string $col): bool {
        if (function_exists('admin_column_exists')) {
            return (bool)admin_column_exists($pdo, $table, $col);
        }
        return db_has_column($pdo, $table, $col);
    }
}

if (!function_exists('abs_url_local')) {
    function abs_url_local(string $path): string {
        if (function_exists('abs_url')) return (string)abs_url($path);

        $https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
        $scheme = $https ? 'https' : 'http';
        $host = (string)($_SERVER['HTTP_HOST'] ?? 'localhost');
        return $scheme . '://' . $host . $path;
    }
}

/* =========================
   Detect columns
========================= */
$activeCol = null;
$tokenCol  = null;

if (function_exists('admin_user_activation_fields')) {
    $fields = (array)admin_user_activation_fields($pdo);
    $activeCol = $fields['active_col'] ?? null;
    $tokenCol  = $fields['token_col'] ?? null;
}

// fallback active
if (!$activeCol) {
    foreach (['is_active','active','verified','email_verified','is_verified'] as $c) {
        if (col_exists($pdo, 'users', $c)) { $activeCol = $c; break; }
    }
}

// fallback token
if (!$tokenCol) {
    foreach (['activation_token_hash','activation_token','verify_token','verification_token','email_token','token'] as $c) {
        if (col_exists($pdo, 'users', $c)) { $tokenCol = $c; break; }
    }
}

$sentAtCol = null;
foreach (['activation_sent_at','verify_sent_at','verification_sent_at'] as $c) {
    if (col_exists($pdo, 'users', $c)) { $sentAtCol = $c; break; }
}

$activatedAtCol = null;
foreach (['activated_at','verified_at','email_verified_at'] as $c) {
    if (col_exists($pdo, 'users', $c)) { $activatedAtCol = $c; break; }
}

if (!$tokenCol) {
    admin_flash_set('warning', admin_tt(
        'admin_no_token_col',
        'Не знайдено колонки токена (activation_token/verify_token/activation_token_hash...)',
        'Не найдена колонка токена',
        'Token column not found'
    ));
    header('Location: ' . $backUrl, true, 303);
    exit;
}

/* =========================
   Load user
========================= */
try {
    $cols = ['id'];
    foreach (['email','username','full_name','lang'] as $c) {
        if (col_exists($pdo, 'users', $c)) $cols[] = $c;
    }
    if ($activeCol) $cols[] = $activeCol;
    $cols[] = $tokenCol;

    $st = $pdo->prepare('SELECT ' . implode(',', array_unique($cols)) . ' FROM users WHERE id=? LIMIT 1');
    $st->execute([$id]);
    $user = $st->fetch(PDO::FETCH_ASSOC) ?: null;
} catch (Throwable $e) {
    $user = null;
}

if (!$user) {
    admin_flash_set('danger', admin_tt('admin_not_found', 'Не знайдено', 'Не найдено', 'Not found'));
    header('Location: ' . $backUrl, true, 303);
    exit;
}

$email = (string)($user['email'] ?? '');
if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
    admin_flash_set('warning', admin_tt(
        'bad_email',
        'У користувача невірний email — лист не відправити.',
        'У пользователя неверный email — письмо не отправить.',
        'User has invalid email — cannot send.'
    ));
    header('Location: ' . $backUrl, true, 303);
    exit;
}

if ($activeCol) {
    $isActive = (int)($user[$activeCol] ?? 0) === 1;
    if ($isActive) {
        admin_flash_set('success', admin_tt('already_active', 'Вже активований', 'Уже активирован', 'Already active'));
        header('Location: ' . $backUrl, true, 303);
        exit;
    }
}

/* =========================
   Create token + update DB
========================= */
$rawToken = bin2hex(random_bytes(32)); // 64 hex chars
$isHashCol = (bool)preg_match('~(_hash|hash)$~i', (string)$tokenCol);
$storeToken = $isHashCol ? hash('sha256', $rawToken) : $rawToken;

try {
    $pdo->beginTransaction();

    $set = [];
    $params = [':token' => $storeToken, ':id' => $id];

    $set[] = "`$tokenCol` = :token";
    if ($sentAtCol) $set[] = "`$sentAtCol` = NOW()";
    if ($activeCol) $set[] = "`$activeCol` = 0";
    if ($activatedAtCol) $set[] = "`$activatedAtCol` = NULL";

    $sql = 'UPDATE users SET ' . implode(', ', $set) . ' WHERE id=:id LIMIT 1';
    $st = $pdo->prepare($sql);
    $st->execute($params);

    $pdo->commit();
} catch (Throwable $e) {
    if ($pdo->inTransaction()) $pdo->rollBack();

    admin_flash_set('danger', admin_tt('admin_save_error', 'Помилка збереження', 'Ошибка сохранения', 'Save error'));
    header('Location: ' . $backUrl, true, 303);
    exit;
}

/* =========================
   Send email (user language)
========================= */
$lang = (string)($user['lang'] ?? 'uk');
if (!in_array($lang, ['uk','ru','en'], true)) $lang = 'uk';

$copy = [
    'subject' => [
        'uk' => 'Активація акаунта VMEREGI',
        'ru' => 'Активация аккаунта VMEREGI',
        'en' => 'VMEREGI account activation',
    ],
    'title' => [
        'uk' => 'Підтвердження пошти',
        'ru' => 'Подтверждение почты',
        'en' => 'Email verification',
    ],
    'text' => [
        'uk' => 'Натисни кнопку нижче, щоб активувати акаунт.',
        'ru' => 'Нажми кнопку ниже, чтобы активировать аккаунт.',
        'en' => 'Click the button below to activate your account.',
    ],
    'btn' => [
        'uk' => 'Активувати акаунт',
        'ru' => 'Активировать аккаунт',
        'en' => 'Activate account',
    ],
    'fallback' => [
        'uk' => 'Якщо кнопка не працює — відкрий посилання:',
        'ru' => 'Если кнопка не работает — открой ссылку:',
        'en' => 'If the button doesn\'t work, open this link:',
    ],
];

$activateLink = abs_url_local('/activate.php?token=' . urlencode($rawToken));
$subj = (string)($copy['subject'][$lang] ?? $copy['subject']['uk']);

$name = trim((string)($user['full_name'] ?? ''));
if ($name === '') $name = trim((string)($user['username'] ?? ''));
if ($name === '') $name = $email;

$html = '<div style="font-family:Arial,sans-serif;line-height:1.5;color:#111">'
    . '<h2 style="margin:0 0 12px 0;">' . h((string)($copy['title'][$lang] ?? $copy['title']['uk'])) . '</h2>'
    . '<p style="margin:0 0 14px 0;">' . h((string)($copy['text'][$lang] ?? $copy['text']['uk'])) . '</p>'
    . '<p style="margin:18px 0;">'
    . '<a href="' . h($activateLink) . '" style="display:inline-block;padding:12px 18px;border-radius:10px;background:#1f3a5f;color:#fff;text-decoration:none;">'
    . h((string)($copy['btn'][$lang] ?? $copy['btn']['uk']))
    . '</a>'
    . '</p>'
    . '<p style="margin:18px 0 6px 0;color:#555;font-size:13px;">' . h((string)($copy['fallback'][$lang] ?? $copy['fallback']['uk'])) . '</p>'
    . '<div style="font-size:13px;"><a href="' . h($activateLink) . '">' . h($activateLink) . '</a></div>'
    . '</div>';

$text = ($copy['title'][$lang] ?? $copy['title']['uk']) . "\n\n"
    . ($copy['text'][$lang] ?? $copy['text']['uk']) . "\n"
    . $activateLink . "\n";

$sendOk = false;
$sendErr = '';

if (function_exists('mailer_send')) {
    $res = (array)mailer_send($email, $name, $subj, $html, $text);
    $sendOk = (bool)($res['ok'] ?? false);
    $sendErr = (string)($res['error'] ?? '');
} else {
    $sendErr = 'mailer_send not found';
}

if (!$sendOk) {
    // Токен вже оновили — даємо адмінові лінк, але без технічних дампів/exception
    admin_flash_set('warning', admin_tt(
        'admin_activation_not_sent',
        'Токен оновлено, але лист не відправився. Посилання: ' . $activateLink,
        'Токен обновлён, но письмо не отправилось. Ссылка: ' . $activateLink,
        'Token updated, but email not sent. Link: ' . $activateLink
    ));
    header('Location: ' . $backUrl, true, 303);
    exit;
}

admin_flash_set('success', admin_tt('admin_activation_sent', 'Лист активації відправлено', 'Письмо активации отправлено', 'Activation email sent'));
header('Location: ' . $backUrl, true, 303);
exit;