<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

require_once 'vendor/autoload.php';
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Signer\Ecdsa\Sha256;
use Lcobucci\JWT\Validation\Constraint\SignedWith;

use Google\Client;

// Database configuration (adjust as needed)
$dbHost = '136.112.153.136';
$dbUser = 'lac';
$dbPass = 'kschhiKHSH23243#';
$dbName = 'lac_prod';

$mysqli = mysqli_connect($dbHost, $dbUser, $dbPass, $dbName);
if (mysqli_connect_errno()) {
    error_log("Database connection failed: " . mysqli_connect_error(), 3, $errorLog);
    http_response_code(500);
    die('Database connection failed');
}

// Configuration
$logDir = __DIR__ . '/logs/'; // Script directory: /var/www/html/altb_reports/public/reco-script/
$payloadLog = $logDir . 'rtdn_payload.log';
$decodedLog = $logDir . 'rtdn_decoded.log';
$transactionLog = $logDir . 'transaction.log';
$errorLog = $logDir . 'rtdn_error.log';
$certRawLog = $logDir . 'certificate_raw.log';
$certFormattedLog = $logDir . 'certificate_formatted.log';
$keyDetailsLog = $logDir . 'key_details.log';
$publicKeyLog = $logDir . 'public_key.log';
$jwtHeaderLog = $logDir . 'jwt_header.log';
$chainVerifyLog = $logDir . 'chain_verify.log';
$jwtVerifyLog = $logDir . 'jwt_verify.log';
$subscriptionUpdateLog = $logDir . 'subscription_update.log';

// Check directory writability
if (!is_writable($logDir)) {
    http_response_code(500);
    die('Log directory is not writable: ' . $logDir);
}

// Get JWT from POST body
$rawInput = file_get_contents("php://input");
file_put_contents($logDir . 'debug_raw_input.log', "RAW: " . $rawInput . PHP_EOL, FILE_APPEND);

// Decode JSON input
$data = json_decode($rawInput, true);
if (!isset($data['signedPayload'])) {
    file_put_contents($payloadLog, "Missing signedPayload: $rawInput" . PHP_EOL, FILE_APPEND);
    http_response_code(400);
    echo 'Missing signedPayload';
    exit;
}

$jwt = $data['signedPayload'];
$parts = explode('.', $jwt);
if (count($parts) !== 3) {
    file_put_contents($payloadLog, "Malformed JWT: $jwt" . PHP_EOL, FILE_APPEND);
    http_response_code(400);
    echo 'Malformed JWT';
    exit;
}

list($headerEncoded, $payloadEncoded, $signatureEncoded) = $parts;

// Decode header and payload
$headerRaw = base64_decode(strtr($headerEncoded, '-_', '+/'));
$payloadRaw = base64_decode(strtr($payloadEncoded, '-_', '+/'));
if (!$headerRaw || !$payloadRaw) {
    error_log("Base64 decoding failed for header or payload", 3, $errorLog);
    http_response_code(400);
    echo 'JWT Decode Error';
    exit;
}

$header = json_decode($headerRaw, true);
$payload = json_decode($payloadRaw, true);
if (!$header || !$payload) {
    error_log("JSON decoding failed: header or payload is null", 3, $errorLog);
    http_response_code(400);
    echo 'Invalid JWT';
    exit;
}

// Log decoded payload (exclude sensitive data)
$safePayload = array_diff_key($payload, ['data' => 1]);
file_put_contents($decodedLog, print_r($safePayload, true) . PHP_EOL, FILE_APPEND);

// Log JWT header
file_put_contents($jwtHeaderLog, print_r($header, true) . PHP_EOL, FILE_APPEND);

// Verify JWT Signature
try {
    $x5c = $header['x5c'] ?? [];
    if (empty($x5c)) {
        error_log("Missing x5c certificate chain", 3, $errorLog);
        http_response_code(400);
        die('Missing x5c');
    }

    // Verify algorithm
    if (!isset($header['alg']) || $header['alg'] !== 'ES256') {
        error_log("Invalid or missing algorithm: " . ($header['alg'] ?? 'none'), 3, $errorLog);
        http_response_code(400);
        die('Invalid JWT algorithm: ' . ($header['alg'] ?? 'none'));
    }

    // Decode leaf certificate
    $certData = base64_decode($x5c[0], true);
    if ($certData === false) {
        error_log("Invalid Base64 encoding in x5c[0]: " . substr($x5c[0], 0, 50) . "...", 3, $errorLog);
        http_response_code(400);
        die('Invalid Base64 in x5c[0]');
    }

    // Check if decoded data resembles a DER certificate
    if (strlen($certData) < 100 || !preg_match('/^\x30[\x80-\x8f]/', $certData)) {
        error_log("Decoded x5c[0] is not a valid DER certificate, length: " . strlen($certData), 3, $errorLog);
        file_put_contents($certRawLog, $x5c[0] . PHP_EOL, FILE_APPEND);
        http_response_code(400);
        die('Invalid DER certificate in x5c[0]');
    }

    // Log raw x5c[0]
    file_put_contents($certRawLog, $x5c[0] . PHP_EOL, FILE_APPEND);

    // Construct PEM certificate
    $cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split(base64_encode($certData), 64, "\n") . "-----END CERTIFICATE-----";
    file_put_contents($certFormattedLog, $cert . PHP_EOL, FILE_APPEND);

    // Write certificate to file
    $certFile = $logDir . 'test_cert.pem';
    if (!file_put_contents($certFile, $cert)) {
        error_log("Failed to write certificate to $certFile: Permission denied", 3, $errorLog);
        http_response_code(500);
        die('Failed to write certificate file');
    }

    // Validate certificate
    exec("openssl x509 -in " . escapeshellarg($certFile) . " -text -noout 2>&1", $output, $returnCode);
    if ($returnCode !== 0) {
        error_log("Certificate validation failed: " . implode("\n", $output), 3, $errorLog);
        http_response_code(400);
        die('Invalid certificate: ' . implode("\n", $output));
    }

    // Validate certificate chain
    $intermediateCert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($x5c[1], 64, "\n") . "-----END CERTIFICATE-----";
    $rootCert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($x5c[2], 64, "\n") . "-----END CERTIFICATE-----";
    file_put_contents($logDir . 'intermediate_cert.pem', $intermediateCert);
    file_put_contents($logDir . 'root_cert.pem', $rootCert);

    exec("openssl verify -CAfile " . escapeshellarg($logDir . 'intermediate_cert.pem') . " " . escapeshellarg($certFile) . " 2>&1", $verifyOutput, $verifyReturnCode);
    if ($verifyReturnCode !== 0) {
        error_log("Certificate chain validation failed: " . implode("\n", $verifyOutput), 3, $errorLog);
    } else {
        file_put_contents($chainVerifyLog, "Chain validation succeeded: " . implode("\n", $verifyOutput) . PHP_EOL, FILE_APPEND);
    }

    // Get public key
    $publicKey = openssl_pkey_get_public($cert);
    if (!$publicKey) {
        $error = openssl_error_string();
        error_log("Failed to extract public key: $error", 3, $errorLog);
        http_response_code(400);
        die('Failed to extract public key: ' . $error);
    }

    // Get key details
    $keyDetails = openssl_pkey_get_details($publicKey);
    file_put_contents($keyDetailsLog, print_r($keyDetails, true) . PHP_EOL, FILE_APPEND);

    if (!isset($keyDetails['ec']) || !isset($keyDetails['ec']['curve_name']) || $keyDetails['ec']['curve_name'] !== 'prime256v1') {
        error_log("Public key is not an EC key with P-256 curve, found: " . ($keyDetails['ec']['curve_name'] ?? 'none'), 3, $errorLog);
        http_response_code(400);
        die('Public key is not an EC key with P-256 curve');
    }

    // Export public key to PEM format
    $publicKeyPem = $keyDetails['key'];
    file_put_contents($publicKeyLog, $publicKeyPem . PHP_EOL, FILE_APPEND);

    // Verify JWT with lcobucci/jwt
    $signer = new Sha256();
    $config = Configuration::forAsymmetricSigner(
        $signer,
        InMemory::plainText('unused'),
        InMemory::plainText($publicKeyPem)
    );
    $token = $config->parser()->parse($jwt);
    $constraint = new SignedWith($signer, InMemory::plainText($publicKeyPem));
    if (!$config->validator()->validate($token, $constraint)) {
        error_log("Lcobucci JWT verification failed", 3, $errorLog);
        http_response_code(401);
        die('JWT Verification Failed');
    }
    file_put_contents($jwtVerifyLog, "Lcobucci JWT verification succeeded" . PHP_EOL, FILE_APPEND);

    // Direct OpenSSL verification for debugging
    $data = $headerEncoded . '.' . $payloadEncoded;
    $signature = base64_decode(strtr($signatureEncoded, '-_', '+/'));
    if ($signature === false) {
        error_log("Invalid Base64 in JWT signature", 3, $errorLog);
        http_response_code(400);
        die('Invalid Base64 in JWT signature');
    }
    $verified = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256);
    if ($verified !== 1) {
        $error = $verified === 0 ? 'Signature verification failed' : 'OpenSSL error: ' . openssl_error_string();
        error_log("Direct OpenSSL verification failed: $error", 3, $errorLog);
        file_put_contents($logDir . 'openssl_verify.log', "Direct OpenSSL verification failed: $error" . PHP_EOL, FILE_APPEND);
    } else {
        file_put_contents($logDir . 'openssl_verify.log', "Direct OpenSSL verification succeeded" . PHP_EOL, FILE_APPEND);
    }

} catch (Exception $e) {
    error_log("JWT verification failed: " . $e->getMessage(), 3, $errorLog);
    http_response_code(401);
    echo 'JWT Verification Failed: ' . $e->getMessage();
    exit;
}

// Extract key values
$notificationType = $payload['notificationType'] ?? '';
$subType = $payload['subtype'] ?? '';
$signedTransactionInfo = $payload['data']['signedTransactionInfo'] ?? '';

// Decode and verify signedTransactionInfo
$transactionPayload = [];
if ($signedTransactionInfo) {
    try {
        list($tHeaderEncoded, $tPayloadEncoded, $tSignatureEncoded) = explode('.', $signedTransactionInfo);
        $tHeader = json_decode(base64_decode(strtr($tHeaderEncoded, '-_', '+/')), true);
        $transactionPayload = json_decode(base64_decode(strtr($tPayloadEncoded, '-_', '+/')), true);

        $tX5c = $tHeader['x5c'] ?? [];
        if (empty($tX5c)) {
            error_log("Missing x5c in signedTransactionInfo", 3, $errorLog);
            throw new Exception('Missing x5c in signedTransactionInfo');
        }

        $tCertData = base64_decode($tX5c[0], true);
        if ($tCertData === false) {
            error_log("Invalid Base64 in signedTransactionInfo x5c[0]: " . substr($tX5c[0], 0, 50) . "...", 3, $errorLog);
            throw new Exception('Invalid Base64 in signedTransactionInfo x5c[0]');
        }

        if (strlen($tCertData) < 100 || !preg_match('/^\x30[\x80-\x8f]/', $tCertData)) {
            error_log("Invalid DER certificate in signedTransactionInfo x5c[0]", 3, $errorLog);
            throw new Exception('Invalid DER certificate in signedTransactionInfo x5c[0]');
        }

        $tCert = "-----BEGIN CERTIFICATE-----\n" . chunk_split(base64_encode($tCertData), 64, "\n") . "-----END CERTIFICATE-----";
        file_put_contents($logDir . 'transaction_cert_formatted.log', $tCert . PHP_EOL, FILE_APPEND);

        $tPublicKey = openssl_pkey_get_public($tCert);
        if (!$tPublicKey) {
            $error = openssl_error_string();
            error_log("Failed to extract public key for signedTransactionInfo: $error", 3, $errorLog);
            throw new Exception('Failed to extract public key for signedTransactionInfo: ' . $error);
        }

        $tKeyDetails = openssl_pkey_get_details($tPublicKey);
        file_put_contents($logDir . 'transaction_key_details.log', print_r($tKeyDetails, true) . PHP_EOL, FILE_APPEND);

        if (!isset($tKeyDetails['ec']) || !isset($tKeyDetails['ec']['curve_name']) || $tKeyDetails['ec']['curve_name'] !== 'prime256v1') {
            error_log("Public key for signedTransactionInfo is not an EC key with P-256 curve", 3, $errorLog);
            throw new Exception('Public key for signedTransactionInfo is not an EC key with P-256 curve');
        }

        $tPublicKeyPem = $tKeyDetails['key'];
        file_put_contents($logDir . 'transaction_public_key.log', $tPublicKeyPem . PHP_EOL, FILE_APPEND);

        // Verify signedTransactionInfo with lcobucci/jwt
        $tConfig = Configuration::forAsymmetricSigner(
            new Sha256(),
            InMemory::plainText('unused'),
            InMemory::plainText($tPublicKeyPem)
        );
        $tToken = $tConfig->parser()->parse($signedTransactionInfo);
        $tConstraint = new SignedWith(new Sha256(), InMemory::plainText($tPublicKeyPem));
        if (!$tConfig->validator()->validate($tToken, $tConstraint)) {
            error_log("Lcobucci signedTransactionInfo verification failed", 3, $errorLog);
            throw new Exception('signedTransactionInfo verification failed');
        }
        file_put_contents($logDir . 'transaction_jwt_verify.log', "Lcobucci signedTransactionInfo verification succeeded" . PHP_EOL, FILE_APPEND);

        // Log transaction payload
        file_put_contents($transactionLog, print_r($transactionPayload, true) . PHP_EOL, FILE_APPEND);

        // Process subscription renewal
        $originalTransactionId = $transactionPayload['originalTransactionId'] ?? null;
        $notificationRenwalType = $transactionPayload['transactionReason'] ?? null;
        $appAccountToken = $transactionPayload['appAccountToken'] ?? null;
        $expiresDate = isset($transactionPayload['expiresDate']) ? (int)($transactionPayload['expiresDate'] / 1000) : null;
        $currentDate = (new DateTime('now', new DateTimeZone('Asia/Kolkata')))->getTimestamp(); // IST
        $expiresDateFormatted = $expiresDate ? date('Y-m-d H:i:s', $expiresDate) : null;
        $purchaseDate = isset($transactionPayload['purchaseDate']) ? date('Y-m-d H:i:s', (int)($transactionPayload['purchaseDate'] / 1000)) : null;
        $transactionId = $transactionPayload['transactionId'] ?? null;
        $productId = $transactionPayload['productId'] ?? null;
        $price = isset($transactionPayload['price']) ? number_format($transactionPayload['price'] / 1000, 2, '.', '') : null; // Convert micros to dollars
        $currency = $transactionPayload['currency'] ?? 'USD';
        $isFreeTrial = (($transactionPayload['offerDiscountType'] ?? '') === 'FREE_TRIAL') ? 1 : 0;
        $pgPaymentData = json_encode($transactionPayload);
        
        // echo '<pre>'; print_r($transactionPayload); die('HERE');
        
        if ($originalTransactionId && $expiresDate && $productId && $expiresDate > $currentDate) {
          
            // Fetch latest subscription record
            $query = "SELECT * FROM tbl_customer_subscriptions WHERE gateway_subscription_id = '" . mysqli_real_escape_string($mysqli, $originalTransactionId) . "' AND autorenew='1' ORDER BY created DESC LIMIT 1";
            $result = mysqli_query($mysqli, $query);
            if (!$result) {
                error_log("Query failed: " . mysqli_error($mysqli), 3, $errorLog);
                file_put_contents($subscriptionUpdateLog, "Query failed for gateway_subscription_id=$originalTransactionId: " . mysqli_error($mysqli) . PHP_EOL, FILE_APPEND);
                http_response_code(500);
                die('Database query failed');
            }

            $RenewRow = mysqli_fetch_assoc($result);
            // echo '<pre>'; print_r($RenewRow); die('HERE');
            if ($RenewRow && $RenewRow['status'] == '7') {
                // Insert new renewal record
                $insertRenewalQuery = "INSERT INTO tbl_customer_subscriptions (
                    app_id, order_id, trans_id, pg_ref_id, device_id, gateway_subscription_id, pg_payment_data, channel, package_id, 
                    package_title, package_code, package_type, package_mode, price, basic_amount, tax_amt, subscriber_id, msisdn, 
                    role_type, gateway_type, pg_name, region_type, local_user, state_code, period, period_interval, trial_period, 
                    trial_length, subscription_type, output_video_limit, additional_cost_per_unit, no_videos, no_plays, status, 
                    platform, extended_status, start_date, end_date, autorenew, currency_id, currency, created, 
                    is_cancelled, deactivation_type, recurring, purchase_token, package_name,purchase_type
                ) VALUES (
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['app_id'] ?? '5013') . "',
                    '" . $RenewRow['order_id']."',
                    '" . mysqli_real_escape_string($mysqli, $transactionId) . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['pg_ref_id']) . "',
                    '" . $RenewRow['device_id'] . "',
                    '" . mysqli_real_escape_string($mysqli, $originalTransactionId) . "',
                    '" . mysqli_real_escape_string($mysqli, $pgPaymentData) . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['channel'] ?? '') . "',
                    '" . $RenewRow['package_id'] . "',
                    '" . $RenewRow['package_title'] . "',
                    '" . $RenewRow['package_code'] . "',
                    '" . $RenewRow['package_type'] . "',
                    '" . $RenewRow['package_mode'] . "',
                    '" . mysqli_real_escape_string($mysqli, $price) . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['basic_amount'] ?? $price) . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['tax_amt'] ?? '0.00') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['subscriber_id'] ?? '') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['msisdn'] ?? '') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['role_type'] ?? '') . "',
                    '" . $RenewRow['gateway_type'] . "',
                    '" . $RenewRow['pg_name'] . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['region_type'] ?? '') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['local_user'] ?? '') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['state_code'] ?? '') . "',
                    '" . $RenewRow['period'] . "',
                    '" . $RenewRow['period_interval'] . "',
                    '" . $RenewRow['trial_period'] . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['trial_length'] ?? '0') . "',
                    '" . $RenewRow['subscription_type'] . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['output_video_limit'] ?? '0') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['additional_cost_per_unit'] ?? '0.00') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['no_videos'] ?? '0') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['no_plays'] ?? '0') . "',
                    '2',
                    'webhook',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['extended_status'] ?? '') . "',
                    '" . mysqli_real_escape_string($mysqli, $purchaseDate) . "',
                    '" . mysqli_real_escape_string($mysqli, $expiresDateFormatted) . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['autorenew'] ?? '1') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['currency_id'] ?? '1') . "',
                    '" . mysqli_real_escape_string($mysqli, $currency) . "',
                    '" . mysqli_real_escape_string($mysqli, $purchaseDate) . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['is_cancelled'] ?? '0') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['deactivation_type'] ?? '') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['recurring'] ?? '1') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['purchase_token'] ?? '') . "',
                    '" . mysqli_real_escape_string($mysqli, $RenewRow['package_name'] ?? $productId) . "',
                    'RENEWED'
                )";
                // echo $insertRenewalQuery."<br><br>";
                file_put_contents($subscriptionUpdateLog, "Insert Query: $insertRenewalQuery" . PHP_EOL, FILE_APPEND);
                if (mysqli_query($mysqli, $insertRenewalQuery)) {
                    file_put_contents($subscriptionUpdateLog, "Inserted renewal: gateway_subscription_id=$originalTransactionId, transaction_id=$transactionId, status=2, end_date=$expiresDateFormatted" . PHP_EOL, FILE_APPEND);

                    ################################## FIREBASE NOTIFICATION #########################################
                    $deviceQuery = "SELECT push_device_token, device_type FROM customer_device WHERE user_id='" . $chkOrderDetailRow['subscriber_id'] . "'";
                    $result = mysqli_query($mysqli, $deviceQuery);
                    if ($result && mysqli_num_rows($result) > 0) {
                        while ($deviceRow = mysqli_fetch_assoc($result)) {
                            $DeviceID = $deviceRow['push_device_token'];
                            $device   = $deviceRow['device_type']; // e.g., 'mobile', 'tv', 'ios'
                            if ($DeviceID) {
                                $notificationSent = SendPurchaseSuccessFCMNotification($DeviceID, $device);
                                if ($notificationSent) {
                                    error_log("FCM Purchase Success sent successfully for user ID " . $chkOrderDetailRow['subscriber_id'] . ", device $device\n", 3, $errorLog);
                                } else {
                                    error_log("FCM Purchase Success failed for user ID " . $chkOrderDetailRow['subscriber_id'] . ", device $device\n", 3, $errorLog);
                                }
                            }
                        }
                    } else {
                        error_log("No device found for user ID " . $chkOrderDetailRow['subscriber_id'], 3, $errorLog);
                    }
                    ################################### FIREBASE NOTIFICATION #########################################

                } else {
                    error_log("Insert failed: " . mysqli_error($mysqli), 3, $errorLog);
                    file_put_contents($subscriptionUpdateLog, "Insert failed for gateway_subscription_id=$originalTransactionId: " . mysqli_error($mysqli) . PHP_EOL, FILE_APPEND);
                }
            } else if(isset($appAccountToken) && $appAccountToken != '') {
                $chkOrderSql = "SELECT gateway_consent_id, id, subscriber_id FROM tbl_order WHERE gateway_consent_id='".$appAccountToken."' ORDER BY id DESC LIMIT 1";
                $chkResult = mysqli_query($mysqli, $chkOrderSql);
                $chkOrderRow = mysqli_fetch_assoc($chkResult);
                if(!empty($chkOrderRow)){
                    $chkExistSubsSql = "SELECT order_id, subscriber_id FROM tbl_customer_subscriptions WHERE order_id='".$chkOrderRow['id']."' AND subscriber_id='".$chkOrderRow['subscriber_id']."' AND `status`='2' ORDER BY id DESC LIMIT 1";
                    $chkExistsResult = mysqli_query($mysqli, $chkExistSubsSql);
                    $chkExistSubsRow = mysqli_fetch_assoc($chkExistsResult);
                    if(empty($chkExistSubsRow)){
                       $chkOrderDetailSql = "SELECT * FROM tbl_order_details WHERE order_id='".$chkOrderRow['id']."' ORDER BY id DESC LIMIT 1";
                       $chkOrderDeResult = mysqli_query($mysqli, $chkOrderDetailSql);
                       $chkOrderDetailRow = mysqli_fetch_assoc($chkOrderDeResult);
                       if(!empty($chkOrderDetailRow)){
                        $insertQuery = "INSERT INTO tbl_customer_subscriptions (
                            app_id, order_id, trans_id, pg_ref_id, device_id, gateway_subscription_id, pg_payment_data, channel, package_id, 
                            package_title, package_code, package_type, package_mode, price, basic_amount, tax_amt, subscriber_id, msisdn, 
                            role_type, gateway_type, pg_name, region_type, local_user, state_code, period, period_interval, trial_period, 
                            trial_length, subscription_type, output_video_limit, additional_cost_per_unit, no_videos, no_plays, status, platform,
                            extended_status, start_date, end_date, autorenew, currency_id, currency, created, 
                            is_cancelled, deactivation_type, recurring, purchase_token, package_name
                        ) VALUES (
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['app_id'] ?? '5013') . "',
                            '" . $chkOrderDetailRow['order_id']."',
                            '" . mysqli_real_escape_string($mysqli, $transactionId) . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['pg_ref_id']) . "',
                            '" . mysqli_real_escape_string($mysqli, $isFreeTrial) . "',
                            '" . mysqli_real_escape_string($mysqli, $originalTransactionId) . "',
                            '" . mysqli_real_escape_string($mysqli, $pgPaymentData) . "',
                            '" . mysqli_real_escape_string($mysqli, '0') . "',
                            '" . $chkOrderDetailRow['item_id'] . "',
                            '" . $chkOrderDetailRow['item_name'] . "',
                            '0',
                            '0',
                            '" . $chkOrderDetailRow['package_mode'] . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['total']) . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['total']) . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['tax_amt'] ?? '0.00') . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['subscriber_id'] ?? '') . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['tax_amt'] ?? '') . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['role_type'] ?? '') . "',
                            '" . $chkOrderDetailRow['gateway_type'] . "',
                            '" . $chkOrderDetailRow['pg_name'] . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['region_type'] ?? '') . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['local_user'] ?? '') . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['b_state_code'] ?? '') . "',
                            '" . $chkOrderDetailRow['period'] . "',
                            '" . $chkOrderDetailRow['period_interval'] . "',
                            '0',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['b_city'] ?? '0') . "',
                            '" . $chkOrderDetailRow['subscription_type'] . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['output_video_limit'] ?? '0') . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['additional_cost_per_unit'] ?? '0.00') . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['tax_amt'] ?? '0') . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['tax_amt'] ?? '0') . "',
                            '2',
                            'webhook',
                            '" . mysqli_real_escape_string($mysqli, '0') . "',
                            '" . mysqli_real_escape_string($mysqli, $purchaseDate) . "',
                            '" . mysqli_real_escape_string($mysqli, $expiresDateFormatted) . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['autorenew'] ?? '1') . "',
                            '" . mysqli_real_escape_string($mysqli, $chkOrderDetailRow['currency_id'] ?? '1') . "',
                            '" . mysqli_real_escape_string($mysqli, $currency) . "',
                            '" . mysqli_real_escape_string($mysqli, $purchaseDate) . "',
                            '" . mysqli_real_escape_string($mysqli, '0') . "',
                            '" . mysqli_real_escape_string($mysqli, '') . "',
                            '" . mysqli_real_escape_string($mysqli, '0') . "',
                            '" . mysqli_real_escape_string($mysqli, '') . "',
                            '" . mysqli_real_escape_string($mysqli, '') . "'
                        )";
                        // echo $insertRenewalQuery."<br><br>";
                        file_put_contents($subscriptionUpdateLog, "Insert Query: $insertQuery" . PHP_EOL, FILE_APPEND);
                        if (mysqli_query($mysqli, $insertQuery)) {
                            $updateOrderSql = "UPDATE tbl_order SET payment_status='2', order_status='2' WHERE id='".$chkOrderDetailRow['order_id']."'";
                            mysqli_query($mysqli, $updateOrderSql);

                            ################################## FIREBASE NOTIFICATION #########################################
                            $deviceQuery = "SELECT push_device_token, device_type FROM customer_device WHERE user_id='" . $chkOrderDetailRow['subscriber_id'] . "'";
                            $result = mysqli_query($mysqli, $deviceQuery);
                            if ($result && mysqli_num_rows($result) > 0) {
                                while ($deviceRow = mysqli_fetch_assoc($result)) {
                                    $DeviceID = $deviceRow['push_device_token'];
                                    $device   = $deviceRow['device_type']; // e.g., 'mobile', 'tv', 'ios'
                                    if ($DeviceID) {
                                        $notificationSent = SendPurchaseSuccessFCMNotification($DeviceID, $device);
                                        if ($notificationSent) {
                                            error_log("FCM Purchase Success sent successfully for user ID " . $chkOrderDetailRow['subscriber_id'] . ", device $device\n", 3, $errorLog);
                                        } else {
                                            error_log("FCM Purchase Success failed for user ID " . $chkOrderDetailRow['subscriber_id'] . ", device $device\n", 3, $errorLog);
                                        }
                                    }
                                }
                            } else {
                                error_log("No device found for user ID " . $chkOrderDetailRow['subscriber_id'], 3, $errorLog);
                            }
                            ################################### FIREBASE NOTIFICATION #########################################

                            file_put_contents($subscriptionUpdateLog, "Inserted renewal: gateway_subscription_id=$originalTransactionId, transaction_id=$transactionId, status=2, end_date=$expiresDateFormatted" . PHP_EOL, FILE_APPEND);
                        } else {
                            error_log("Insert failed: " . mysqli_error($mysqli), 3, $errorLog);
                            file_put_contents($subscriptionUpdateLog, "Insert failed for gateway_subscription_id=$originalTransactionId: " . mysqli_error($mysqli) . PHP_EOL, FILE_APPEND);
                        }
                       }
                    }
                }

            } else {
                error_log("No expired subscription found for gateway_subscription_id=$originalTransactionId", 3, $errorLog);
                file_put_contents($subscriptionUpdateLog, "No expired subscription (status=7) found for gateway_subscription_id=$originalTransactionId" . PHP_EOL, FILE_APPEND);
            }
            mysqli_free_result($result);
        } else {
            error_log("Missing required fields or not a valid RENEWAL: originalTransactionId=$originalTransactionId, expiresDate=$expiresDate, productId=$productId, notificationType=$notificationType, expiresDateValid=" . ($expiresDate > $currentDate ? 'true' : 'false'), 3, $errorLog);
            file_put_contents($subscriptionUpdateLog, "Skipped processing: Invalid RENEWAL or fields for transactionId=$originalTransactionId" . PHP_EOL, FILE_APPEND);
        }

    } catch (Exception $e) {
        error_log("signedTransactionInfo error: " . $e->getMessage(), 3, $errorLog);
        file_put_contents($logDir . 'transaction_jwt_verify.log', "signedTransactionInfo error: " . $e->getMessage() . PHP_EOL, FILE_APPEND);
    }
}


function SendPurchaseSuccessFCMNotification($DeviceID, $device) {
    $serviceAccountFile = __DIR__ . '/drama-shorts-abb61-firebase-adminsdk-fbsvc-44b0f0865f.json';

    // Initialize Google Client
    $client = new Client();
    $client->setAuthConfig($serviceAccountFile);
    $client->setScopes(['https://www.googleapis.com/auth/firebase.messaging']);

    // Get access token
    $tokenArray = $client->fetchAccessTokenWithAssertion();
    if (!isset($tokenArray['access_token'])) {
        echo "Failed to get access token\n";
        return false;
    }
    $accessToken = $tokenArray['access_token'];

    // Build message payload
  
    $payloadData = [
        'trigger_type' => 'user',
        'trigger_action' => 'purchase_success'
    ];

    $payloadJSON = json_encode($payloadData);

    // Android / TV
    if ($device === 'mobile' || $device === 'tv') {
        $payload = [
            'message' => [
                'token' => $DeviceID,
                'data' => [
                    'title' => 'Purchase Success',
                    'body'  => $payloadJSON
                ]
            ]
        ];
    } else {
        // iOS / APNS
        $payload = [
            'message' => [
                'token' => $DeviceID,
                'apns' => [
                    'payload' => [
                        'aps' => [
                            'content-available' => true
                        ],
                        'customData' => [
                            'title' => 'Purchase Success',
                            'body'  => $payloadJSON
                        ]
                    ]
                ]
            ]
        ];
    }

    // Get project ID from JSON
    $credentials = json_decode(file_get_contents($serviceAccountFile), true);
    $projectId = $credentials['project_id'];

    // Send FCM via HTTP v1 API
    $ch = curl_init("https://fcm.googleapis.com/v1/projects/$projectId/messages:send");
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . $accessToken,
        'Content-Type: application/json'
    ]);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);

    $response = curl_exec($ch);
    if ($response === false) {
        echo "FCM curl error: " . curl_error($ch);
        curl_close($ch);
        return false;
    }

    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    echo "FCM HTTP Code: $httpCode, Response: $response\n";

    return $httpCode === 200;
}


// Return 200 OK to Apple
http_response_code(200);
echo 'OK';
?>
