<?php
/*
 * Copyright (c) 2025 AltumCode (https://altumcode.com/)
 *
 * This software is licensed exclusively by AltumCode and is sold only via https://altumcode.com/.
 * Unauthorized distribution, modification, or use of this software without a valid license is not permitted and may be subject to applicable legal actions.
 *
 * 🌍 View all other existing AltumCode projects via https://altumcode.com/
 * 📧 Get in touch for support or general queries via https://altumcode.com/contact
 * 📤 Download the latest version via https://altumcode.com/downloads
 *
 * 🐦 X/Twitter: https://x.com/AltumCode
 * 📘 Facebook: https://facebook.com/altumcode
 * 📸 Instagram: https://instagram.com/altumcode
 */

namespace Altum\Controllers;

use Altum\Date;
use Altum\Models\Payments;

defined('ALTUMCODE') || die();

class WebhookPayu extends Controller {

    public function index() {

        if(!in_array(settings()->license->type, ['Extended License', 'extended'])) {
            redirect('not-found');
        }

        if((strtoupper($_SERVER['REQUEST_METHOD']) != 'POST')) {
            redirect('not-found');
        }

        /* Get the headers */
        $headers = getallheaders();

        /* Get the payload */
        $payload = trim(@file_get_contents('php://input'));

        /* Log for debugging purposes */
        debug_log('[' . \Altum\Router::$controller . '] ' . print_r(['headers' => $headers, 'payload' => $payload], true));

        if(empty($payload)) {
            die();
        }

        try {
            \OpenPayU_Configuration::setEnvironment(settings()->payu->mode);
            \OpenPayU_Configuration::setMerchantPosId(settings()->payu->merchant_pos_id);
            \OpenPayU_Configuration::setSignatureKey(settings()->payu->signature_key);
            \OpenPayU_Configuration::setOauthClientId(settings()->payu->oauth_client_id);
            \OpenPayU_Configuration::setOauthClientSecret(settings()->payu->oauth_client_secret);
            \OpenPayU_Configuration::setOauthTokenCache(new \OauthCacheFile(UPLOADS_PATH . 'cache'));

            $result = \OpenPayU_Order::consumeNotification($payload);

            if($result->getResponse()->order->orderId) {

                /* Check if OrderId exists in Merchant Service, update Order data by OrderRetrieveRequest */
                $order = \OpenPayU_Order::retrieve($result->getResponse()->order->orderId);

                if($order->getStatus() == 'SUCCESS') {

                    /* details about the payment */
                    $payment_payment_id = $result->getResponse()->order->extOrderId;
                    $payment = db()->where('payment_id', $payment_payment_id)->where('status', 'pending')->getOne('payments');

                    if(!$payment) {
                        http_response_code(400); die();
                    }

                    /* details about the user who paid */
                    $user = db()->where('user_id', $payment->user_id)->getOne('users');

                    /* plan that the user has paid for */
                    $plan = (new \Altum\Models\Plan())->get_plan_by_id($payment->plan_id);

                    /* Make sure the code that was potentially used exists */
                    $codes_code = db()->where('code', $payment->code)->where('type', 'discount')->getOne('codes');

                    if($codes_code) {
                        /* Check if we should insert the usage of the code or not */
                        if(!db()->where('user_id', $payment->user_id)->where('code_id', $codes_code->code_id)->has('redeemed_codes')) {

                            /* Update the code usage */
                            db()->where('code_id', $codes_code->code_id)->update('codes', ['redeemed' => db()->inc()]);

                            /* Add log for the redeemed code */
                            db()->insert('redeemed_codes', [
                                'code_id'   => $codes_code->code_id,
                                'user_id'   => $user->user_id,
                                'datetime'  => get_date()
                            ]);
                        }
                    }

                    /* Give the plan to the user */
                    $current_plan_expiration_date = $payment->plan_id == $user->plan_id ? $user->plan_expiration_date : '';
                    $modifier = match ($payment->frequency) {
                        'monthly' => '+30 days +12 hours',
                        'quarterly' => '+3 months +12 hours',
                        'biannual' => '+6 months +12 hours',
                        'annual' => '+12 months +12 hours',
                        'lifetime' => '+100 years +12 hours',
                    };
                    $plan_expiration_date = (new \DateTime($current_plan_expiration_date))->modify($modifier)->format('Y-m-d H:i:s');

                    /* Database query */
                    db()->where('user_id', $user->user_id)->update('users', [
                        'plan_id' => $payment->plan_id,
                        'plan_settings' => json_encode($plan->settings),
                        'plan_expiration_date' => $plan_expiration_date,
                        'plan_expiry_reminder' => 0,
                        'payment_processor' => 'payu',
                        'payment_total_amount' => $payment->total_amount,
                        'payment_currency' => $payment->currency,
                    ]);

                    /* Clear the cache */
                    cache()->deleteItemsByTag('user_id=' . $user->user_id);

                    /* Send notification to the user */
                    $email_template = get_email_template(
                        [],
                        l('global.emails.user_payment.subject'),
                        [
                            '{{PAYMENT_ID}}' => $payment->id,
                            '{{NAME}}' => $user->name,
                            '{{PLAN_NAME}}' => $plan->name,
                            '{{PLAN_EXPIRATION_DATE}}' => Date::get($plan_expiration_date, 2),
                            '{{USER_PLAN_LINK}}' => url('account-plan'),
                            '{{USER_PAYMENTS_LINK}}' => url('account-payments'),
                        ],
                        l('global.emails.user_payment.body')
                    );

                    send_mail($user->email, $email_template->subject, $email_template->body, ['anti_phishing_code' => $user->anti_phishing_code, 'language' => $user->language]);

                    /* Currency exchange in case its needed */
                    $total_amount_default_currency = $payment->total_amount;

                    if(settings()->payment->default_currency != $payment->currency && settings()->payment->currency_exchange_api_key) {
                        try {
                            $response = \Unirest\Request::get('https://api.freecurrencyapi.com/v1/latest?apikey=' . settings()->payment->currency_exchange_api_key . '&base_currency=' . $payment->currency . '&currencies=' . settings()->payment->default_currency);

                            if($response->code == 200) {
                                $total_amount_default_currency = $payment->total_amount * $response->body->data->{settings()->payment->default_currency};
                                $total_amount_default_currency = number_format($total_amount_default_currency, 2, '.', '');
                            }
                        } catch (\Exception $exception) {
                            /* :) */
                        }
                    }

                    /* Update the payment */
                    db()->where('id', $payment->id)->update('payments', [
                        'total_amount_default_currency' => $total_amount_default_currency,
                        'status' => 'paid',
                    ]);

                    /* Affiliate */
                    (new Payments())->affiliate_payment_check($payment->id, $total_amount_default_currency, settings()->payment->default_currency, $user);

                    die();
                }
            }
        } catch (\OpenPayU_Exception $exception) {
            if(DEBUG) {
                error_log($exception->getMessage());
            }
            echo $exception->getMessage();
            http_response_code(400); die();
        }

        die('successful');

    }

}
