<?php
require_once '../config.php';
require_once '../vendor/autoload.php'; // For Mercado Pago SDK

use MercadoPago\SDK;
use MercadoPago\Payment;

// Log all incoming requests for debugging
$log_file = __DIR__ . '/payment_notification.log';
$request_body = file_get_contents('php://input');
$log_entry = "[ " . date('Y-m-d H:i:s') . " ] Request Method: " . $_SERVER['REQUEST_METHOD'] . "\n";
$log_entry .= "[ " . date('Y-m-d H:i:s') . " ] Request Headers: " . print_r(getallheaders(), true) . "\n";
$log_entry .= "[ " . date('Y-m-d H:i:s') . " ] Request Body: " . $request_body . "\n";

// Determine if it's a Mercado Pago or PayU notification
// Mercado Pago sends JSON, PayU sends form-urlencoded data

if (!empty($request_body) && (json_decode($request_body) !== null)) {
    // Likely Mercado Pago notification
    $data = json_decode($request_body, true);
    $log_entry .= "[ " . date('Y-m-d H:i:s') . " ] Detected as Mercado Pago notification.\n";
    handleMercadoPagoNotification($data, $conn, $mercadopago_access_token, $log_file);
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['referenceCode'])) {
    // Likely PayU notification
    $data = $_POST;
    $log_entry .= "[ " . date('Y-m-d H:i:s') . " ] Detected as PayU notification.\n";
    handlePayuNotification($data, $conn, $payu_api_key, $log_file);
} else {
    $log_entry .= "[ " . date('Y-m-d H:i:s') . " ] Unknown notification type or empty request.\n";
    http_response_code(400); // Bad Request
    echo "Unknown notification type.";
}

file_put_contents($log_file, $log_entry, FILE_APPEND);

function handleMercadoPagoNotification($data, $conn, $mercadopago_access_token, $log_file) {
    SDK::setAccessToken($mercadopago_access_token);

    if (isset($data['type']) && $data['type'] === 'payment' && isset($data['data']['id'])) {
        $payment_id = $data['data']['id'];
        $payment = Payment::find_by_id($payment_id);

        if ($payment) {
            $invoice_id = $payment->external_reference;
            $status = $payment->status;
            $status_detail = $payment->status_detail;

            $log_entry = "[ " . date('Y-m-d H:i:s') . " ] MP Payment ID: {$payment_id}, Invoice ID: {$invoice_id}, Status: {$status}, Detail: {$status_detail}\n";
            file_put_contents($log_file, $log_entry, FILE_APPEND);

            updateInvoiceStatus($conn, $invoice_id, $status, 'MercadoPago', $log_file);
            http_response_code(200);
            echo "Mercado Pago notification processed.";
        } else {
            $log_entry = "[ " . date('Y-m-d H:i:s') . " ] MP Payment not found for ID: {$payment_id}\n";
            file_put_contents($log_file, $log_entry, FILE_APPEND);
            http_response_code(404); // Not Found
            echo "Payment not found.";
        }
    } else {
        $log_entry = "[ " . date('Y-m-d H:i:s') . " ] Invalid Mercado Pago notification data.\n";
        file_put_contents($log_file, $log_entry, FILE_APPEND);
        http_response_code(400); // Bad Request
        echo "Invalid Mercado Pago notification.";
    }
}

function handlePayuNotification($data, $conn, $payu_api_key, $log_file) {
    // PayU Signature Verification
    // string to sign: api_key~merchant_id~reference_code~value~currency~state_pol
    $merchant_id = $data['merchantId'];
    $reference_code = $data['referenceCode'];
    $value = $data['value'];
    $currency = $data['currency'];
    $transaction_state = $data['transactionState'];
    $sign = $data['signature'];

    $string_to_sign = "{$payu_api_key}~{$merchant_id}~{$reference_code}~{$value}~{$currency}~{$transaction_state}";
    $my_signature = md5($string_to_sign);

    $log_entry = "[ " . date('Y-m-d H:i:s') . " ] PayU Ref Code: {$reference_code}, State: {$transaction_state}, Received Sign: {$sign}, My Sign: {$my_signature}\n";
    file_put_contents($log_file, $log_entry, FILE_APPEND);

    if ($my_signature === $sign) {
        // Signature is valid, process the payment status
        $invoice_id = str_replace("INV-", "", $reference_code); // Extract invoice ID
        $status = '';

        switch ($transaction_state) {
            case 'APPROVED':
                $status = 'paid';
                break;
            case 'PENDING':
                $status = 'pending';
                break;
            case 'DECLINED':
            case 'EXPIRED':
            case 'ERROR':
                $status = 'failed';
                break;
            default:
                $status = 'unknown';
                break;
        }

        updateInvoiceStatus($conn, $invoice_id, $status, 'PayU', $log_file);
        http_response_code(200);
        echo "PayU notification processed.";

    } else {
        $log_entry = "[ " . date('Y-m-d H:i:s') . " ] PayU Signature mismatch. Possible tampering.\n";
        file_put_contents($log_file, $log_entry, FILE_APPEND);
        http_response_code(403); // Forbidden
        echo "Signature mismatch.";
    }
}

function updateInvoiceStatus($conn, $invoice_id, $status, $gateway, $log_file) {
    // Prevent multiple updates for the same invoice if already paid
    $sql_check = "SELECT status, ticket_id, userid FROM invoices WHERE id = ?";
    $stmt_check = $conn->prepare($sql_check);
    $stmt_check->bind_param("i", $invoice_id);
    $stmt_check->execute();
    $result_check = $stmt_check->get_result();
    $current_invoice = $result_check->fetch_assoc();
    $stmt_check->close();

    if (!$current_invoice) {
        $log_entry = "[ " . date('Y-m-d H:i:s') . " ] Invoice ID {$invoice_id} not found for update.\n";
        file_put_contents($log_file, $log_entry, FILE_APPEND);
        return;
    }

    if ($current_invoice['status'] === 'paid' && $status !== 'paid') {
        $log_entry = "[ " . date('Y-m-d H:i:s') . " ] Invoice ID {$invoice_id} already paid. Skipping update to {$status}.\n";
        file_put_contents($log_file, $log_entry, FILE_APPEND);
        return;
    }

    $sql_update = "";
    $stmt_update = null;

    if ($status === 'paid') {
        $sql_update = "UPDATE invoices SET status='paid', route=?, paid_at=NOW() WHERE id=?";
        $stmt_update = $conn->prepare($sql_update);
        $stmt_update->bind_param("si", $gateway, $invoice_id);
    } elseif ($status === 'failed') {
        $sql_update = "UPDATE invoices SET status='failed' WHERE id=?";
        $stmt_update = $conn->prepare($sql_update);
        $stmt_update->bind_param("i", $invoice_id);
    } elseif ($status === 'pending') {
        $sql_update = "UPDATE invoices SET status='pending' WHERE id=?";
        $stmt_update = $conn->prepare($sql_update);
        $stmt_update->bind_param("i", $invoice_id);
    } else {
        $log_entry = "[ " . date('Y-m-d H:i:s') . " ] Unknown status '{$status}' for Invoice ID {$invoice_id}.\n";
        file_put_contents($log_file, $log_entry, FILE_APPEND);
        return;
    }

    if ($stmt_update && $stmt_update->execute()) {
        $log_entry = "[ " . date('Y-m-d H:i:s') . " ] Invoice ID {$invoice_id} updated to status: {$status}. Route: {$gateway}\n";
        file_put_contents($log_file, $log_entry, FILE_APPEND);

        // Activate ticket only if status is 'paid' and it wasn't already paid
        if ($status === 'paid' && $current_invoice['status'] !== 'paid') {
            activateTicket($conn, $current_invoice['userid'], $current_invoice['ticket_id'], $log_file);
        }
    } else {
        $log_entry = "[ " . date('Y-m-d H:i:s') . " ] Failed to update Invoice ID {$invoice_id} to status: {$status}. Error: " . ($stmt_update ? $stmt_update->error : "Statement not prepared") . "\n";
        file_put_contents($log_file, $log_entry, FILE_APPEND);
    }
    if ($stmt_update) {
        $stmt_update->close();
    }
}


function activateTicket($conn, $userid, $ticket_id, $log_file) {
    // Check if the ticket is already active for the user
    $sql_check_active = "SELECT COUNT(*) FROM current_tickets WHERE userid = ? AND ticket_id = ? AND end_date > NOW()";
    $stmt_check_active = $conn->prepare($sql_check_active);
    $stmt_check_active->bind_param("ii", $userid, $ticket_id);
    $stmt_check_active->execute();
    $stmt_check_active->bind_result($count_active);
    $stmt_check_active->fetch();
    $stmt_check_active->close();

    if ($count_active > 0) {
        $log_entry = "[ " . date('Y-m-d H:i:s') . " ] Ticket ID {$ticket_id} already active for User ID {$userid}. Skipping activation.\n";
        file_put_contents($log_file, $log_entry, FILE_APPEND);
        return;
    }

    // Fetch ticket duration (e.g., from a `tickets` table, assuming `duration_days` column)
    $sql_ticket_duration = "SELECT duration_days FROM tickets WHERE id = ?";
    $stmt_ticket_duration = $conn->prepare($sql_ticket_duration);
    $stmt_ticket_duration->bind_param("i", $ticket_id);
    $stmt_ticket_duration->execute();
    $stmt_ticket_duration->bind_result($duration_days);
    $stmt_ticket_duration->fetch();
    $stmt_ticket_duration->close();

    if (!$duration_days) {
        $log_entry = "[ " . date('Y-m-d H:i:s') . " ] Could not find duration for Ticket ID {$ticket_id}. Cannot activate.\n";
        file_put_contents($log_file, $log_entry, FILE_APPEND);
        return;
    }

    $start_date = date('Y-m-d H:i:s');
    $end_date = date('Y-m-d H:i:s', strtotime("+{$duration_days} days"));

    $sql_insert_ticket = "INSERT INTO current_tickets (userid, ticket_id, start_date, end_date) VALUES (?, ?, ?, ?)";
    $stmt_insert_ticket = $conn->prepare($sql_insert_ticket);
    $stmt_insert_ticket->bind_param("iiss", $userid, $ticket_id, $start_date, $end_date);

    if ($stmt_insert_ticket->execute()) {
        $log_entry = "[ " . date('Y-m-d H:i:s') . " ] Ticket ID {$ticket_id} activated for User ID {$userid}. End Date: {$end_date}.\n";
        file_put_contents($log_file, $log_entry, FILE_APPEND);
    } else {
        $log_entry = "[ " . date('Y-m-d H:i:s') . " ] Failed to activate Ticket ID {$ticket_id} for User ID {$userid}. Error: " . $stmt_insert_ticket->error . "\n";
        file_put_contents($log_file, $log_entry, FILE_APPEND);
    }
    $stmt_insert_ticket->close();
}

?>