<?php
// two-factor-verify.php — second-factor challenge after a correct password.
// Reached only when login.php set $_SESSION['2fa_pending']. Verifies an emailed
// code, an authenticator (TOTP) code, or a one-time backup code, then completes
// the sign-in.

session_start();
require_once __DIR__ . '/config/db.php';
require_once __DIR__ . '/includes/twofa.php';

$p = $_SESSION['2fa_pending'] ?? null;

// No pending login, or it's gone stale (15 min) — start over.
if (!$p || empty($p['user_id']) || (time() - (int)($p['ts'] ?? 0)) > 900) {
    unset($_SESSION['2fa_pending']);
    $_SESSION['login_error'] = 'Your sign-in session expired. Please log in again.';
    header('Location: signin.php');
    exit;
}

$uid       = (int) $p['user_id'];
$via_email = !empty($p['via_email']);
$via_totp  = !empty($p['via_totp']);
$email     = (string) $p['email'];
$name      = (string) $p['name'];

$error = '';
$info  = '';

// ── Resend emailed code ─────────────────────────────────────────────────────
if (isset($_GET['resend']) && $via_email) {
    $wait = 0;
    if (twofa_send_login_otp($pdo, $email, $name, $wait)) {
        $info = 'A new code has been sent to your email.';
    } else {
        $info = $wait > 0
            ? "Please wait {$wait} seconds before requesting another code."
            : "We couldn't send the code right now. Please try again in a moment.";
    }
}

// ── Verify submitted code ───────────────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $code = trim($_POST['code'] ?? '');
    if ($code === '') {
        $error = 'Please enter your verification code.';
    } else {
        $ok = false;

        // Authenticator app first (re-read the secret; never trust the session for it).
        if (!$ok && $via_totp) {
            $st = twofa_status($conn, $uid);
            if (twofa_check_totp($st['totp_secret'], $code)) $ok = true;
        }
        // Emailed login code.
        if (!$ok && $via_email && twofa_check_email_otp($pdo, $email, $code)) {
            $ok = true;
        }
        // One-time backup code (works for either method).
        if (!$ok && twofa_check_backup($conn, $uid, $code)) {
            $ok = true;
        }

        if ($ok) {
            // Complete the sign-in (mirrors login.php's success block).
            $redirect = $p['redirect'] ?? 'dashboard.php';
            session_regenerate_id(true);
            $_SESSION['user_id']    = $uid;
            $_SESSION['user_name']  = $name;
            $_SESSION['user_email'] = $email;
            $_SESSION['role']       = $p['role'] ?? 'customer';
            unset($_SESSION['2fa_pending'], $_SESSION['login_error']);

            setcookie('dabil_returning', '1', [
                'expires'  => time() + 60 * 60 * 24 * 365,
                'path'     => '/',
                'secure'   => !empty($_SERVER['HTTPS']),
                'httponly' => true,
                'samesite' => 'Lax',
            ]);

            header('Location: ' . $redirect);
            exit;
        }
        $error = 'That code is incorrect or has expired. Please try again.';
    }
}

// Mask the email for display: a***@domain.com
$masked = $email;
if (strpos($email, '@') !== false) {
    [$u, $d] = explode('@', $email, 2);
    $masked = (strlen($u) <= 1 ? $u : $u[0] . str_repeat('*', max(1, strlen($u) - 1))) . '@' . $d;
}

$sub = $via_email
    ? "Enter the 6-digit code we sent to <strong>" . htmlspecialchars($masked) . "</strong>."
    : "Enter the 6-digit code from your authenticator app.";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>Two-step verification — Dabil</title>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
  --primary:#225AE3;--primary-dark:#1a47b8;--primary-bg:#EEF3FD;
  --text:#0F172A;--text-muted:#64748B;--text-light:#94A3B8;
  --bg:#EDF0F5;--border:#E2E8F0;--field-bg:#F7F9FC;
  --font:'Plus Jakarta Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
}
html,body{height:100%;font-family:var(--font);background:var(--bg);color:var(--text);-webkit-text-size-adjust:100%}
a{text-decoration:none}
.auth-wrap{min-height:100%;display:flex;align-items:center;justify-content:center;padding:calc(env(safe-area-inset-top) + 20px) 16px calc(env(safe-area-inset-bottom) + 24px)}
.auth-card{width:100%;max-width:420px;background:#fff;border-radius:24px;padding:28px 22px;box-shadow:0 12px 40px rgba(15,23,42,.08)}
.shield{width:60px;height:60px;border-radius:18px;background:var(--primary);display:flex;align-items:center;justify-content:center;margin:0 auto 16px;color:#fff;box-shadow:0 8px 22px rgba(34,90,227,.3)}
.auth-card h1{font-size:1.5rem;font-weight:800;letter-spacing:-.03em;margin-bottom:6px;text-align:center}
.auth-sub{font-size:.9rem;color:var(--text-muted);margin-bottom:22px;line-height:1.5;text-align:center}
.field{position:relative;margin-bottom:14px}
.field input{width:100%;height:56px;border:1.5px solid var(--border);background:var(--field-bg);border-radius:14px;padding:0 16px;font-size:max(18px,1rem);font-family:var(--font);color:var(--text);outline:none;text-align:center;letter-spacing:.3em;font-weight:700;transition:border-color .2s,box-shadow .2s,background .2s}
.field input:focus{border-color:var(--primary);background:#fff;box-shadow:0 0 0 3px rgba(34,90,227,.1)}
.field input::placeholder{color:var(--text-light);letter-spacing:normal;font-weight:500}
.btn-primary{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;height:56px;border:none;border-radius:16px;background:var(--primary);color:#fff;font-family:var(--font);font-weight:700;font-size:1rem;cursor:pointer;box-shadow:0 8px 22px rgba(34,90,227,.3);transition:background .15s,transform .12s;margin-top:6px}
.btn-primary:active{background:var(--primary-dark);transform:scale(.99)}
.row{text-align:center;font-size:.88rem;color:var(--text-muted);margin-top:18px}
.row a{color:var(--primary);font-weight:700}
.banner{font-size:.85rem;border-radius:12px;padding:12px 14px;margin-bottom:16px;text-align:center}
.banner.err{background:#FEF2F2;border:1px solid #FECACA;color:#B91C1C}
.banner.ok{background:#EEF3FD;border:1px solid #BFD3F7;color:#1a47b8}
.hint{font-size:.78rem;color:var(--text-light);text-align:center;margin-top:14px;line-height:1.5}
</style>
</head>
<body>
<div class="auth-wrap">
  <div class="auth-card">
    <div class="shield">
      <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><polyline points="9 12 11 14 15 10"/></svg>
    </div>
    <h1>Two-step verification</h1>
    <p class="auth-sub"><?php echo $sub; ?></p>

    <?php if ($error): ?><div class="banner err"><?php echo htmlspecialchars($error); ?></div><?php endif; ?>
    <?php if ($info): ?><div class="banner ok"><?php echo htmlspecialchars($info); ?></div><?php endif; ?>

    <form method="POST" autocomplete="one-time-code">
      <div class="field">
        <input type="text" name="code" id="code" inputmode="numeric" autocomplete="one-time-code"
               placeholder="Enter code" autofocus required>
      </div>
      <button type="submit" class="btn-primary">Verify &amp; continue</button>
    </form>

    <?php if ($via_email): ?>
    <p class="row">Didn't get the code? <a href="two-factor-verify.php?resend=1">Resend</a></p>
    <?php endif; ?>

    <p class="hint">You can also enter one of your backup codes if you can't access your <?php echo $via_totp ? 'authenticator' : 'email'; ?>.</p>

    <p class="row"><a href="signin.php" onclick="return cancel2fa()">Back to sign in</a></p>
  </div>
</div>
<script>
  function cancel2fa(){ /* server clears pending on next login */ return true; }
  // Keep numeric entry comfortable but allow alphanumeric backup codes too.
  var c = document.getElementById('code');
  if (c) c.addEventListener('input', function(){ /* no-op: accept what the user types */ });
</script>
</body>
</html>
