<?php

declare(strict_types=1);

require_once "../db.php";
require_once "./customer_auth_common.php";
require_once "./customer_mailer.php";

error_reporting(E_ERROR | E_PARSE);
ini_set("display_errors", "0");

if (($_SERVER["REQUEST_METHOD"] ?? "") !== "POST") {
    customerAuthJsonResponse(405, [
        "success" => false,
        "message" => "Method not allowed",
    ]);
}

$input = customerAuthReadJsonInput();
$email = strtolower(customerAuthGetInputValue($input, "email"));
$fullName = customerAuthGetInputValue($input, "fullName", "name");
$mode = strtolower(customerAuthGetInputValue($input, "mode", "authMode"));

if ($mode === "") {
    $mode = "signup";
}

if (!in_array($mode, ["signup"], true)) {
    customerAuthJsonResponse(422, [
        "success" => false,
        "message" => "OTP verification is available only for signup.",
    ]);
}

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    customerAuthJsonResponse(422, [
        "success" => false,
        "message" => "Please enter a valid email address.",
    ]);
}

$userLookupStmt = $conn->prepare("SELECT id FROM users WHERE email = ? LIMIT 1");
if (!$userLookupStmt) {
    customerAuthJsonResponse(500, [
        "success" => false,
        "message" => "Unable to prepare user lookup.",
    ]);
}

$userLookupStmt->bind_param("s", $email);
$userLookupStmt->execute();
$userLookupResult = $userLookupStmt->get_result();
$existingUser = $userLookupResult ? $userLookupResult->fetch_assoc() : null;
$userLookupStmt->close();

if ($existingUser) {
    customerAuthJsonResponse(409, [
        "success" => false,
        "message" => "Account already exists. Please login instead.",
    ]);
}

customerAuthEnsureOtpTable($conn);

$cooldownSeconds = 60;
$cooldownStmt = $conn->prepare(
    "SELECT TIMESTAMPDIFF(SECOND, created_at, NOW()) AS elapsed_seconds
     FROM customer_email_otps
     WHERE email = ?
     ORDER BY id DESC
     LIMIT 1"
);

if ($cooldownStmt) {
    $cooldownStmt->bind_param("s", $email);
    $cooldownStmt->execute();
    $cooldownResult = $cooldownStmt->get_result();
    $cooldownRow = $cooldownResult ? $cooldownResult->fetch_assoc() : null;
    $cooldownStmt->close();

    if ($cooldownRow && isset($cooldownRow["elapsed_seconds"])) {
        $elapsed = (int) $cooldownRow["elapsed_seconds"];
        if ($elapsed >= 0 && $elapsed < $cooldownSeconds) {
            $remaining = $cooldownSeconds - $elapsed;
            customerAuthJsonResponse(429, [
                "success" => false,
                "message" => "Please wait {$remaining} seconds before requesting another code.",
            ]);
        }
    }
}

$disableOldStmt = $conn->prepare(
    "UPDATE customer_email_otps
     SET used_at = NOW()
     WHERE email = ? AND used_at IS NULL AND verified_at IS NULL"
);
if ($disableOldStmt) {
    $disableOldStmt->bind_param("s", $email);
    $disableOldStmt->execute();
    $disableOldStmt->close();
}

$otpCode = customerAuthGenerateOtpCode();
$otpHash = hash("sha256", $otpCode);
$otpToken = bin2hex(random_bytes(24));
$expiresAt = date("Y-m-d H:i:s", time() + (10 * 60));

$insertStmt = $conn->prepare(
    "INSERT INTO customer_email_otps (email, full_name, otp_hash, otp_token, expires_at)
     VALUES (?, NULLIF(?, ''), ?, ?, ?)"
);
if (!$insertStmt) {
    customerAuthJsonResponse(500, [
        "success" => false,
        "message" => "Unable to prepare OTP request.",
    ]);
}

$insertStmt->bind_param("sssss", $email, $fullName, $otpHash, $otpToken, $expiresAt);
if (!$insertStmt->execute()) {
    $error = $insertStmt->error;
    $insertStmt->close();
    customerAuthJsonResponse(500, [
        "success" => false,
        "message" => "Unable to generate OTP request.",
        "error" => $error,
    ]);
}

$otpRowId = (int) $conn->insert_id;
$insertStmt->close();

$mailResult = sendCustomerOtpEmail($email, $otpCode);
if (!$mailResult["success"]) {
    $rollbackStmt = $conn->prepare("DELETE FROM customer_email_otps WHERE id = ?");
    if ($rollbackStmt) {
        $rollbackStmt->bind_param("i", $otpRowId);
        $rollbackStmt->execute();
        $rollbackStmt->close();
    }

    customerAuthJsonResponse(422, [
        "success" => false,
        "message" => "Could not send verification code to this email address.",
        "emailMessage" => $mailResult["message"],
    ]);
}

customerAuthJsonResponse(200, [
    "success" => true,
    "message" => "Verification code sent. Please check your email.",
    "otpToken" => $otpToken,
    "mode" => $mode,
    "expiresInSeconds" => 600,
]);
