<?php
/**
 * POST /api/auth/login
 *
 * Body: email, password, remember (optional)
 *
 * If OTP_LOGIN_ENABLED=1 → after password OK, send OTP and return otp_required.
 * Otherwise → create session and return redirect.
 */

declare(strict_types=1);
require_once dirname(__DIR__, 2) . '/config/bootstrap.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    jsonError('Method not allowed', 405);
}

$ip = Logger::clientIp();
RateLimit::hit('login:ip:' . $ip, 10, 900, 'Too many login attempts. Try in 15 min.');

$email    = strtolower(Validator::clean((string)($_POST['email'] ?? ''), 190));
$password = (string)($_POST['password'] ?? '');
$remember = !empty($_POST['remember']);

if (!Validator::email($email) || $password === '') {
    jsonError('Invalid credentials.', 401);
}

RateLimit::hit('login:email:' . $email, 5, 900, 'Too many attempts for this email. Try in 15 min.');

$pdo = db();
$stmt = $pdo->prepare("
    SELECT id, password_hash, status, email_verified
    FROM publisher_user
    WHERE email = ? LIMIT 1
");
$stmt->execute([$email]);
$user = $stmt->fetch();

// Generic message — don't reveal which field failed
if (!$user || !password_verify($password, $user['password_hash'])) {
    Logger::audit(null, 'login_failed', 'email', null, ['email' => $email, 'ip' => $ip]);
    jsonError('Invalid credentials.', 401);
}

if ((int)$user['status'] === 0) {
    Logger::audit((int)$user['id'], 'login_blocked');
    jsonError('Your account is blocked. Please contact support.', 403);
}

if ((int)$user['status'] === 2) {
    jsonError('Account not found.', 401);
}

// Email verification check (only if signup OTP was on at the time)
if ((int)$user['email_verified'] === 0 && (int)env('OTP_SIGNUP_ENABLED', 1) === 1) {
    // Re-trigger OTP send → push user to verify-otp page
    Logger::info('Login attempted on unverified account', ['email' => $email]);
    jsonError('Please verify your email first.', 403, [
        'verify_required' => true,
        'redirect'        => '/verify-otp?purpose=signup&email=' . urlencode($email),
    ]);
}

// ───────────────────── 2FA path ─────────────────────
if ((int)env('OTP_LOGIN_ENABLED', 0) === 1) {
    $otpLen = (int)env('OTP_LENGTH', 6);
    $max = (int)str_repeat('9', $otpLen);
    $otp = str_pad((string)random_int(0, $max), $otpLen, '0', STR_PAD_LEFT);
    $otpHash = password_hash($otp, PASSWORD_BCRYPT);
    $expiry = time() + ((int)env('OTP_EXPIRY_MINUTES', 10) * 60);

    // Invalidate previous login OTPs
    $pdo->prepare("DELETE FROM publisher_otp WHERE identifier = ? AND purpose = 'login' AND verified = 0")
        ->execute([$email]);

    $payload = json_encode([
        'publisher_id' => (int)$user['id'],
        'remember'     => $remember,
    ]);
    $pdo->prepare("
        INSERT INTO publisher_otp (identifier, identifier_type, purpose, otp_hash, expires_at, payload, created_at)
        VALUES (?, 'email', 'login', ?, ?, ?, ?)
    ")->execute([$email, $otpHash, $expiry, $payload, time()]);

    Mail::sendOtp($email, $otp, 'login');
    Logger::audit((int)$user['id'], 'login_otp_sent');

    jsonSuccess('OTP sent to your email.', [
        'otp_required' => true,
        'redirect'     => '/verify-otp?purpose=login&email=' . urlencode($email),
        'expires_in'   => (int)env('OTP_EXPIRY_MINUTES', 10) * 60,
    ]);
}

// ───────────────────── Direct login ─────────────────────
Session::create((int)$user['id'], $remember);

$pdo->prepare("UPDATE publisher_user SET last_login_at = NOW(), last_login_ip = ? WHERE id = ?")
    ->execute([$ip, (int)$user['id']]);

RateLimit::reset('login:email:' . $email);
RateLimit::reset('login:ip:' . $ip);
Logger::audit((int)$user['id'], 'login_success');

$next = (string)($_POST['next'] ?? '/dashboard');
if (!str_starts_with($next, '/') || str_contains($next, '://')) $next = '/dashboard';

jsonSuccess('Login successful.', ['redirect' => $next]);
