<?php
require_once '../db.php';
require_once '../auth/customer_auth_common.php';
require_once './mailer.php';
require_once './terms_definition.php';
require_once '../notifications/admin_notifier.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(["success" => false, "message" => "Method not allowed"]);
    exit;
}

$rawBody = file_get_contents("php://input");
$jsonInput = json_decode($rawBody, true);
if (!is_array($jsonInput)) {
    $jsonInput = [];
}

function reservationInput(array $jsonInput, string $camelKey, string $snakeKey = "", $default = "")
{
    if (isset($_POST[$camelKey])) {
        return $_POST[$camelKey];
    }
    if ($snakeKey !== "" && isset($_POST[$snakeKey])) {
        return $_POST[$snakeKey];
    }
    if (isset($jsonInput[$camelKey])) {
        return $jsonInput[$camelKey];
    }
    if ($snakeKey !== "" && isset($jsonInput[$snakeKey])) {
        return $jsonInput[$snakeKey];
    }
    return $default;
}

function toBool($value): bool
{
    if (is_bool($value)) {
        return $value;
    }
    if (is_int($value)) {
        return $value === 1;
    }
    $normalized = strtolower(trim((string) $value));
    return in_array($normalized, ["1", "true", "yes", "on"], true);
}

$fullName = trim((string) reservationInput($jsonInput, "fullName", "full_name"));
$email = trim((string) reservationInput($jsonInput, "email"));
$phone = trim((string) reservationInput($jsonInput, "phone"));
$reservationDate = trim((string) reservationInput($jsonInput, "reservationDate", "reservation_date"));
$reservationTime = trim((string) reservationInput($jsonInput, "reservationTime", "reservation_time"));
$guests = (int) reservationInput($jsonInput, "guestCount", "guests", 0);
$notes = trim((string) reservationInput($jsonInput, "notes", "message"));
$foodPreferences = trim((string) reservationInput($jsonInput, "foodPreferences", "food_preferences"));
$allergies = trim((string) reservationInput($jsonInput, "allergies"));
$termsAccepted = toBool(reservationInput($jsonInput, "termsAccepted", "terms_accepted", false));
$emailVerificationToken = trim((string) reservationInput($jsonInput, "emailVerificationToken", "email_verification_token"));
$email = strtolower($email);

$session = customerAuthGetSessionUser($conn, customerAuthExtractBearerToken());
$isAuthenticatedUser = is_array($session);

if ($isAuthenticatedUser) {
    $sessionEmail = strtolower(trim((string) ($session["email"] ?? "")));
    $sessionName = trim((string) ($session["name"] ?? ""));

    if ($sessionEmail !== "") {
        if ($email !== "" && $email !== $sessionEmail) {
            http_response_code(422);
            echo json_encode([
                "success" => false,
                "message" => "Reservation email must match your logged-in account email."
            ]);
            exit;
        }
        $email = $sessionEmail;
    }

    if ($fullName === "" && $sessionName !== "") {
        $fullName = $sessionName;
    }
}

$errors = [];

if ($fullName === "") {
    $errors[] = "Full name is required.";
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $errors[] = "A valid email address is required.";
}
if ($phone === "") {
    $errors[] = "Phone number is required.";
}
if ($guests < 1 || $guests > 20) {
    $errors[] = "Guest count must be between 1 and 20.";
}
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $reservationDate)) {
    $errors[] = "Reservation date must be in YYYY-MM-DD format.";
}
if (!preg_match('/^\d{2}:\d{2}(:\d{2})?$/', $reservationTime)) {
    $errors[] = "Reservation time must be in HH:MM format.";
}
if (!$termsAccepted) {
    $errors[] = "You must accept the Terms and Conditions before booking.";
}
if (!$isAuthenticatedUser && $emailVerificationToken === "") {
    $errors[] = "Please verify your email before submitting a reservation.";
}

if (!empty($errors)) {
    http_response_code(422);
    echo json_encode([
        "success" => false,
        "message" => "Validation failed.",
        "errors" => $errors
    ]);
    exit;
}

$verificationRowId = 0;
if (!$isAuthenticatedUser) {
    $verificationLookupStmt = $conn->prepare(
        "SELECT id, verification_expires_at
         FROM reservation_email_verifications
         WHERE email = ?
           AND verified_token = ?
           AND verified_at IS NOT NULL
           AND used_at IS NULL
           AND verification_expires_at IS NOT NULL
         ORDER BY id DESC
         LIMIT 1"
    );

    if (!$verificationLookupStmt) {
        http_response_code(500);
        echo json_encode([
            "success" => false,
            "message" => "Failed to verify email confirmation token."
        ]);
        exit;
    }

    $verificationLookupStmt->bind_param("ss", $email, $emailVerificationToken);
    $verificationLookupStmt->execute();
    $verificationResult = $verificationLookupStmt->get_result();
    $verificationRow = $verificationResult ? $verificationResult->fetch_assoc() : null;
    $verificationLookupStmt->close();

    if (!$verificationRow) {
        http_response_code(422);
        echo json_encode([
            "success" => false,
            "message" => "Email is not verified or verification has expired. Please verify your email again."
        ]);
        exit;
    }

    $verificationRowId = (int) $verificationRow["id"];
    $verificationExpiryTimestamp = strtotime((string) ($verificationRow["verification_expires_at"] ?? ""));
    if ($verificationExpiryTimestamp === false || $verificationExpiryTimestamp < time()) {
        $expireVerificationStmt = $conn->prepare(
            "UPDATE reservation_email_verifications SET used_at = NOW() WHERE id = ?"
        );
        if ($expireVerificationStmt) {
            $expireVerificationStmt->bind_param("i", $verificationRowId);
            $expireVerificationStmt->execute();
            $expireVerificationStmt->close();
        }

        http_response_code(422);
        echo json_encode([
            "success" => false,
            "message" => "Email verification has expired. Please verify your email again."
        ]);
        exit;
    }
}

$timeWithSeconds = strlen($reservationTime) === 5 ? $reservationTime . ":00" : $reservationTime;
$terms = reservationTermsDefinition();
$termsVersion = $terms["version"];
$status = "pending";
$cancellationToken = bin2hex(random_bytes(24));
$termsAcceptedInt = $termsAccepted ? 1 : 0;

$stmt = $conn->prepare(
    "INSERT INTO reservations
        (full_name, email, phone, reservation_date, reservation_time, guests, notes, food_preferences, allergies, status, terms_accepted, terms_version, cancellation_token)
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
);

if (!$stmt) {
    http_response_code(500);
    echo json_encode(["success" => false, "message" => "Failed to prepare reservation query."]);
    exit;
}

$stmt->bind_param(
    "sssssissssiss",
    $fullName,
    $email,
    $phone,
    $reservationDate,
    $timeWithSeconds,
    $guests,
    $notes,
    $foodPreferences,
    $allergies,
    $status,
    $termsAcceptedInt,
    $termsVersion,
    $cancellationToken
);

if (!$stmt->execute()) {
    http_response_code(503);
    echo json_encode(["success" => false, "message" => "Unable to create reservation."]);
    $stmt->close();
    exit;
}

$reservationId = $conn->insert_id;
$stmt->close();

$mailConfig = require __DIR__ . '/mail_config.php';
$cancellationLink = $mailConfig["backend_url"] . "/reservation/cancel_reservation.php?token=" . urlencode($cancellationToken);

$emailResult = sendReservationThankYouEmail([
    "full_name" => $fullName,
    "email" => $email,
    "reservation_date" => $reservationDate,
    "reservation_time" => $timeWithSeconds,
    "guests" => $guests
], $cancellationLink);

if (!$emailResult["success"]) {
    $rollbackStmt = $conn->prepare("DELETE FROM reservations WHERE id = ?");
    if ($rollbackStmt) {
        $rollbackStmt->bind_param("i", $reservationId);
        $rollbackStmt->execute();
        $rollbackStmt->close();
    }

    http_response_code(422);
    echo json_encode([
        "success" => false,
        "message" => "Reservation could not be completed because confirmation email could not be sent. Please use a valid email address and try again.",
        "emailMessage" => $emailResult["message"]
    ]);
    $conn->close();
    exit;
}

if (!$isAuthenticatedUser && $verificationRowId > 0) {
    $consumeVerificationStmt = $conn->prepare(
        "UPDATE reservation_email_verifications SET used_at = NOW() WHERE id = ?"
    );
    if ($consumeVerificationStmt) {
        $consumeVerificationStmt->bind_param("i", $verificationRowId);
        $consumeVerificationStmt->execute();
        $consumeVerificationStmt->close();
    }
}

$adminReservationsUrl = $mailConfig["frontend_url"] . "/admin/reservations";
adminNotifierSendEvent($conn, "New reservation received", [
    "Reservation ID" => (string) $reservationId,
    "Guest Name" => $fullName,
    "Email" => $email,
    "Phone" => $phone,
    "Date" => $reservationDate,
    "Time" => $timeWithSeconds,
    "Guests" => (string) $guests,
    "Status" => $status,
    "Admin Page" => $adminReservationsUrl,
]);

http_response_code(201);
echo json_encode([
    "success" => true,
    "message" => "Reservation submitted successfully.",
    "reservationId" => $reservationId,
    "status" => $status,
    "emailSent" => true,
    "emailMessage" => $emailResult["message"]
]);

$conn->close();
