<?php

$path = '../../';
$noauth = true;
require_once $path . 'core/includes/header.inc.php';

use Mtc\Core\Admin\TotpService;
use Mtc\Core\RateLimit;

$adminuser = new AdminUser();

// Already fully authenticated — go to admin
if (!empty($_SESSION['adminId']) && $_SESSION['adminId'] > 0) {
    header('Location: /admin');
    exit();
}

// Must have a pending 2FA session
if (empty($_SESSION['admin_2fa_pending_id'])) {
    header('Location: /admin/login.php');
    exit();
}

// Pending session expires after 5 minutes
if (empty($_SESSION['admin_2fa_pending_at']) || (time() - $_SESSION['admin_2fa_pending_at']) > 300) {
    unset($_SESSION['admin_2fa_pending_id'], $_SESSION['admin_2fa_pending_at'], $_SESSION['admin_2fa_setup_secret']);
    header('Location: /admin/login.php');
    exit();
}

$errors = [];
$locked = false;
$page_meta['title'] = 'Two-Factor Authentication';
$pendingId = (int) $_SESSION['admin_2fa_pending_id'];
$rateLimitKey = '2fa_verify_' . $pendingId;
$maxAttempts = 5;
$lockoutSeconds = 120;

if (RateLimit::isLocked($rateLimitKey, $lockoutSeconds, $maxAttempts)) {
    $locked = true;
    $timeRemaining = RateLimit::getTimeRemaining($rateLimitKey, $lockoutSeconds, true);
    $minutes = max(1, ceil($timeRemaining / 60));
    $errors[] = 'Too many failed attempts. Please wait ' . $minutes . ' minute' . ($minutes > 1 ? 's' : '') . ' before trying again.';
}

if (!$locked && isset($_POST['verify_2fa'])) {
    if (!CSRF::checkToken('admin_2fa_verify')) {
        $errors[] = 'Verification failed, please try again.';
    }

    $code = preg_replace('/\s+/', '', $_POST['totp_code'] ?? '');

    if (empty($code)) {
        $errors[] = 'Please enter your authentication code.';
    }

    if (empty($errors)) {
        $adminUser = \Mtc\Core\AdminUser::query()->find($pendingId);
        $service = new TotpService();

        $timestamp = $adminUser
            ? $service->verifyCode($adminUser->totp_secret, $code, $adminUser->totp_last_used_at)
            : false;

        if ($timestamp !== false) {
            // Save the timestamp to reject replay of this code
            $adminUser->forceFill(['totp_last_used_at' => $timestamp])->save();

            // Promote to full session
            unset($_SESSION['admin_2fa_pending_id']);
            unset($_SESSION['admin_2fa_pending_at']);
            session_regenerate_id(true);
            $_SESSION['adminId'] = $pendingId;
            $_SESSION['mtcadminarea'] = true;
            \Mtc\Core\AdminUser::query()
                ->where('id', $pendingId)
                ->update(['session_id' => session_id()]);

            $redirect = !empty($_POST['redir']) ? urldecode($_POST['redir']) : '/admin/index.php';
            if (!preg_match('#^/(?!/)#', $redirect)) {
                $redirect = '/admin/index.php';
            }
            anti_phish_redirect($redirect);
        } else {
            // Log failed attempt (account-level, ignores IP)
            RateLimit::logAttempt($rateLimitKey);

            if (RateLimit::isLocked($rateLimitKey, $lockoutSeconds, $maxAttempts)) {
                $locked = true;
                $errors[] = 'Too many failed attempts. Please wait 2 minutes before trying again.';
            } else {
                $remaining = $maxAttempts - RateLimit::where('key', $rateLimitKey)
                    ->where('created_at', '>=', now()->subSeconds($lockoutSeconds))
                    ->count();
                $errors[] = 'Invalid code. ' . $remaining . ' attempt' . ($remaining !== 1 ? 's' : '') . ' remaining.';
            }
        }
    }
}

$redir = $_REQUEST['redir'] ?? '';

require_once $path . 'core/admin/templates/adminheader.html.php';
?>

<div class="tfa-container">
    <div class="tfa-card">
        <div class="tfa-icon">
            <i class="fa fa-shield"></i>
        </div>
        <h1>Two-Factor Authentication</h1>
        <p>Enter the 6-digit code from your authenticator app.</p>

        <?php
        if (!empty($errors)) {
            showerrors($errors);
        }
        ?>

        <?php if (!$locked) { ?>
        <form action="2fa_verify.php" method="post" id="tfaForm">
            <div class="tfa-digits" id="tfaDigits">
                <input type="text" class="tfa-digit" data-index="0" inputmode="numeric" maxlength="1" autocomplete="off" autofocus />
                <input type="text" class="tfa-digit" data-index="1" inputmode="numeric" maxlength="1" autocomplete="off" />
                <input type="text" class="tfa-digit" data-index="2" inputmode="numeric" maxlength="1" autocomplete="off" />
                <div class="tfa-digit-separator"></div>
                <input type="text" class="tfa-digit" data-index="3" inputmode="numeric" maxlength="1" autocomplete="off" />
                <input type="text" class="tfa-digit" data-index="4" inputmode="numeric" maxlength="1" autocomplete="off" />
                <input type="text" class="tfa-digit" data-index="5" inputmode="numeric" maxlength="1" autocomplete="off" />
            </div>
            <input type="hidden" name="totp_code" id="totp_code" value="" />
            <?= CSRF::token('admin_2fa_verify') ?>
            <input type="hidden" name="redir" value="<?= clean_page($redir) ?>" />
            <input type="hidden" name="verify_2fa" value="1" />
        </form>

        <p class="tfa-help"><i class="fa fa-mobile"></i> Open your authenticator app to view your code</p>
        <?php } else { ?>
        <p class="tfa-help"><i class="fa fa-lock"></i> You can try again after the lockout period, or contact an administrator to reset your 2FA.</p>
        <?php } ?>
    </div>
</div>

<?php
require_once $path . 'core/admin/templates/adminfooter.html.php';
