<?php
require_once '../config.php';
require_once '../middleware.php';

header('Content-Type: application/json');

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Get the encrypted payload
    $encrypted_payload = file_get_contents('php://input');
    if (empty($encrypted_payload)) {
        sendResponse(400, 'Empty request body');
    }

    // Decrypt the payload
    $data = decryptRequestPayload($encrypted_payload);
    if (!$data) {
        sendResponse(400, 'Invalid request body');
    }

    $device_id = $_SERVER['HTTP_DEVICE_ID'] ?? '';
    $session_token = $_SERVER['HTTP_SESSION_TOKEN'] ?? '';

    // Validation for required fields
    if (empty($data['user_id']) || empty($data['refercode'])) {
        sendResponse(400, 'Missing user_id or refercode');
    }

    validateInput($data, ['user_id', 'refercode']);
    $user_id = $data['user_id'];
    $refercode = $data['refercode'];

    // Validate refercode format (alphanumeric, 8 characters)
    if (!preg_match('/^[a-zA-Z0-9]{8}$/', $refercode)) {
        sendResponse(400, 'Invalid referral code format. Code must be 8 characters long and contain only letters and numbers.');
    }

    authenticateSession($user_id, $device_id, $session_token);
    rateLimit($user_id);
    $new_session_token = generateNewSessionToken($user_id, $device_id);

    $conn = getDbConnection();

    // Check if user has already applied a refercode
    $stmt = $conn->prepare("SELECT referred_by, refercode FROM users WHERE id = ?");
    $stmt->bind_param("i", $user_id);
    $stmt->execute();
    $result = $stmt->get_result();
    $user = $result->fetch_assoc();

    if (!$user) {
        sendResponse(404, 'User not found');
    }

    if ($user['referred_by']) {
        $new_session_token = generateNewSessionToken($user_id, $device_id);
        sendResponse(400, 'You have already used a referral code. You cannot use another one.', [], $new_session_token);
    }

    // Check if user is trying to use their own refercode
    if ($user['refercode'] === $refercode) {
        $new_session_token = generateNewSessionToken($user_id, $device_id);
        sendResponse(400, 'You cannot use your own referral code. Please use a different referral code.', [], $new_session_token);
    }

    // Find the referrer by refercode
    $stmt = $conn->prepare("SELECT id, coins FROM users WHERE refercode = ? AND id != ?");
    $stmt->bind_param("si", $refercode, $user_id);
    $stmt->execute();
    $result = $stmt->get_result();

    if ($result->num_rows === 0) {
        $new_session_token = generateNewSessionToken($user_id, $device_id);
        sendResponse(400, 'Invalid referral code. Please check the code and try again.', [], $new_session_token);
    }

    $referrer = $result->fetch_assoc();
    $referrer_id = $referrer['id'];

    // Get referral reward settings from app_settings
    $stmt = $conn->prepare("SELECT referrer_coins, referred_coins FROM app_settings WHERE id = 1");
    $stmt->execute();
    $result = $stmt->get_result();
    $settings = $result->fetch_assoc();

    if (!$settings) {
        sendResponse(500, 'Unable to retrieve referral settings');
    }

    $referrer_coins_award = $settings['referrer_coins'];
    $referred_coins_award = $settings['referred_coins'];

    // Start transaction to ensure data consistency
    $conn->begin_transaction();

    try {
        // Update the user's referred_by field
        $stmt = $conn->prepare("UPDATE users SET referred_by = ? WHERE id = ?");
        $stmt->bind_param("ii", $referrer_id, $user_id);
        $stmt->execute();

        if ($stmt->affected_rows === 0) {
            throw new Exception('Failed to update user referral status');
        }

        // Commit transaction
        $conn->commit();

        // Prepare response data
        $response_data = [
            'message' => "Referral code applied successfully! You will receive your referral reward after your first successful redeem."
        ];

        sendResponse(200, 'Referral code applied successfully', $response_data, $new_session_token);

    } catch (Exception $e) {
        // Rollback transaction on error
        $conn->rollback();
        sendResponse(500, 'Failed to apply referral code: ' . $e->getMessage());
    } finally {
        $stmt->close();
        $conn->close();
    }
} else {
    sendResponse(405, 'Method not allowed');
}
?>