<?php
// require_once("header.php");

require_once("./config/db_config.php");
require_once("./config/QueryBuilder.php");
require_once("./config/gatewayConfig.php");
$gatewayConfig = new GatewayConfig();
$activeGateways = $gatewayConfig->getActiveGateway();
$queryBuilder = new QueryBuilder($conn);
$notificationBody = json_decode(file_get_contents("php://input"), true);
require_once("./config/paymentGatewayLoader.php");
$gatewayLoader = new PaymentGatewayLoader();
include('Logger.php');
Logger::notice("Online Payment - Notification" . DateTime::createFromFormat('U.u', microtime(true))->format('Y-m-d H:i:s.u'));
Logger::info(serialize(file_get_contents("php://input")));
Logger::info(serialize($_REQUEST));
function getRedisData($key, $value)
{
    global $redis;
    if ($redis->exists($key)) {
        return $redis->get($key); // Get from cache
    }
}

function setRedisData($key, $value, $ttl = 600)
{
    global $redis;
    $redis->set($key, $value, $ttl); // Set data with a TTL (time to live)
}

function processPaymentNotification($activeGateway,$notificationBody, $conn, $connMain, $queryBuilder,$gatewayLoader)
{
    $eventNameArr = ["THREE_DS_NOT_AUTHENTICATED", "CAPTURED", "AUTHORISED", "guaranteed", "failed", "cancelled", "initiated", "processed","dt.payment.captured", "emi.approved", "emi.disbursed"," emi.backout","emi.rejected","SUCCESS","PAYMENT APPROVED"];
    $notificationCount = 0;
    $txnId = null;
    $notificationStatus = '-';    

    switch (strtolower($activeGateway)) {
        case 'network':
            if (isset($notificationBody['order']['reference']) && in_array($notificationBody['eventName'], $eventNameArr)) {
                $txnId = $notificationBody['order']['reference'];
                if (isset($notificationBody['order']['_embedded']['payment'])) {
                    $len = count($notificationBody['order']['_embedded']['payment']);
                    $notificationStatus = $notificationBody['order']['_embedded']['payment'][$len - 1]['state'] ?? '-';
                }
            }
            break;

        case 'flywire':
            if (isset($notificationBody['event_type']) && in_array($notificationBody['event_type'], $eventNameArr)) {
                $txnId = $notificationBody['data']['external_reference'];
                $notificationStatus = $notificationBody['event_type'] ?? '-';
            }
            break;
        case 'mips':
            if (isset($notificationBody['crypted_callback']) && $notificationBody['crypted_callback']) {
                $txnId = $notificationBody['id_order'];
                $notificationStatus = $notificationBody['crypted_callback'] ?? '-';
            }
            break;
        case 'authorizedotnet':
            if (isset($notificationBody['payload']['invoiceNumber']) && $notificationBody['payload']['invoiceNumber']) {
                $txnId = $notificationBody['payload']['invoiceNumber'];
                $notificationStatus = $notificationBody['payload']['id'] ?? '-';
            }
            break;
        case 'grayquest':
            if (isset($notificationBody['reference_id']) && in_array($notificationBody['event'], $eventNameArr)) {
                $txnId = $notificationBody['reference_id'];
                $notificationStatus = $notificationBody['event'] ?? '-';
                
                // Save notification to grayquest_notification table
                $where = ['txnId' => $txnId];
                $paymentRequest = $queryBuilder->selectById('payment_request', 'paymentId', $where);                
                 if ($paymentRequest) {
                    // Check for existing notification in grayquest_notification                     
                    $exist = $queryBuilder->selectById('grayquest_notification', 'id', [
                        'txnId' => $txnId,
                        'status' => $notificationStatus
                    ]);
                    
                    if ($exist) {
                        Logger::notice("Duplicate GrayQuest Notification Skipped - " . $txnId . " - " . $notificationStatus);
                    } else {
                        $notificationData = [
                            'onlinePaymentId' => $paymentRequest['paymentId'],
                            'txnId' => $txnId,
                            'notification_data' => json_encode($notificationBody),
                            'status' => $notificationBody['event']
                        ];
                        $queryBuilder->insert('grayquest_notification', $notificationData);
                        Logger::info("GrayQuest Notification Stored - " . $txnId . " - " . $notificationStatus);

                        // Trigger receipt generation for emi.disbursed
                        if ($notificationStatus === 'emi.disbursed') {
                            $paymentRequestFull = $queryBuilder->selectById('payment_request', '*', $where);
                            if ($paymentRequestFull) {
                                $paymentRequestFull['notificationBody'] = $notificationBody;
                                $gatewayLoader->loadReceiptFunctions($activeGateway, $connMain, $conn, $paymentRequestFull);                              
                            }
                        }
                    }
                }          
                
            }
            break;
        case'doku':
            if (isset($notificationBody['transaction']) && in_array($notificationBody['transaction']['status'], $eventNameArr) && in_array($notificationBody['card_payment']['response_message'], $eventNameArr)) {
                $txnId = $notificationBody['order']['invoice_number'];
                $notificationStatus = $notificationBody['transaction']['status'] ?? '-';
            }
            break;       

        // Add more gateways here as needed
        default:
            echo "Unknown Gateway";
            return;
    }

    // Redis duplicate check
    if ($txnId) {
        $redisKey = $txnId . '-' . $notificationStatus;
        $redisValue = $txnId;
        $redisData = getRedisData($redisKey, $redisValue);
        if ($redisData && $redisData == $txnId) {
            $notificationCount = 1;
        } else {
            setRedisData($redisKey, $redisValue, 600); 
        }
    }

    if ($notificationCount == 0 && $txnId && $activeGateway !== 'grayquest') {
        Logger::notice("Single Request Getting-" . $txnId);
        Logger::info(serialize($txnId));

        $where = ['txnId' => $txnId];
        $paymentRequest = $queryBuilder->selectById('payment_request', '*', $where);
       
        $paymentRequest['notificationBody'] = $notificationBody;       
        $gatewayLoader->loadReceiptFunctions($activeGateway,$connMain , $conn, $paymentRequest);
                
    } else {
        Logger::notice("Duplicate Request Getting-" . $txnId);
        Logger::info(serialize($txnId));
        echo "Duplicate Request Getting";
    }
}
// Main code to process the notification
try {
    if ($activeGateways) {
        // Loop over the active gateways and process the notification for each
        $gateWayToProcess = ['flywire','network','mips','authorizedotnet','grayquest','doku'];
        foreach ($activeGateways as $gateway) {
            // Process notification for each active gateway
            if(in_array($gateway['value'] , $gateWayToProcess))
            {
                processPaymentNotification($gateway['value'], $notificationBody, $conn, $connMain, $queryBuilder , $gatewayLoader);
            }
        }
    } else {
        Logger::error("No active gateways found");
        echo "No active gateways found";
    }

} catch (Exception $e) {
    echo $e->getMessage();
    echo '<div class="col-md-12 text-center alert alert-warning">
            <h4>Unfortunately, Your transaction could not be processed. Please try again1.</h4>
          </div>';
}