<?php

use Carbon\Carbon;
use Mtc\Core\Admin\User;
use Mtc\Core\Models\CountryState;
use Mtc\Modules\Members\Classes\Auth;
use Mtc\Modules\Members\Classes\MemberManager;
use Mtc\Modules\Members\Models\Member;
use Mtc\Plugins\Judopay\Classes\Judopay;
use Mtc\Plugins\NewsletterSignup\Classes\Newsletter;
use Mtc\Plugins\RyftPay\Classes\RyftPay;


$path = '../../';
require_once $path . 'core/includes/header.inc.php';

$order_id = $order_id_in_request = request()->input('order_id');

if (!Auth::isLoggedIn()) {
    $order_id = (int) $order_id;
    header('Location: /members/login.php?redirect=' . urlencode('/shop/checkout/basket_overview.php?order_id=' . $order_id));
    exit();
}

if (!$order_id_in_request && ((isset($basket->order_id) && $basket->order_id > 0) || isset($_SESSION['order_id']))) {
    $order_id = $_SESSION['order_id'];
}

$failed_payment = false;

if ($order_id) {
    $order_eloquent = MTC\Shop\Order::find($order_id);

    if (empty($order_eloquent)) {
        header("Location: /shop/checkout/basket.php?order_not_found");
        exit();
    }

    $_SESSION['basket_id'] = $order_eloquent->basket_id;
    $_SESSION['unset_paid_basket'] = false;

    if (!empty($order_eloquent->paid)) {
        header("Location: /shop/checkout/basket.php?order_already_paid");
        exit();
    }

    // If the order is a failed subscription payment, we need to update the basket items to include the subscription items
    if ($order_eloquent->isFailedSubscriptionPayment()) {
        $failed_payment = true;

        $basket = Mtc\Shop\Basket::query()
            ->where('id', $order_eloquent->basket_id)
            ->first();

        // Get the specific subscription linked to this order, validated against logged-in member
        $logged_in_member_id = Auth::getLoggedInMember()->id ?? null;
        $requested_subscription_id = (int) request()->input('subscription_id');
        if ($requested_subscription_id) {
            $subscription = $order_eloquent->subscriptions
                ->where('id', $requested_subscription_id)
                ->where('member_id', $logged_in_member_id)
                ->first();
        }
        if (empty($subscription)) {
            $subscription = $order_eloquent->subscriptions
                ->where('member_id', $logged_in_member_id)
                ->first();
        }
        if (empty($subscription)) {
            header("Location: /shop/checkout/basket.php?invalid_subscription");
            exit();
        }

        if ($subscription) {
            $subItemIds = $subscription->items->pluck('shop_item_id');
        }
        $subscriptionOrderItems = $order_eloquent->items->filter(function ($item) use ($subscription, $subItemIds) {
            if (!$subscription) {
                return !empty($item->has_requested_subscription);
            }
            return $subItemIds->contains($item->item_id);
        });
        if ($subscriptionOrderItems->count() && $basket) {
            $orderItems = $subscriptionOrderItems->map(fn($item) => [
                'item_id' => $item->item_id,
                'bundle_id' => $item->bundle_id,
                'prescription_item_id' => $item->prescription_item_id,
                'has_requested_subscription' => $item->has_requested_subscription,
                'has_requested_subscription_period' => $item->has_requested_subscription_period,
                'assessment_id' => $item->assessment_id,
                'quantity' => $item->quantity,
                'recommended_quantity' => $item->recommended_quantity,
                'size' => $item->size,
                'PLU' => $item->PLU,
                'sizeid' => $item->sizeid,
                'nhs_prescription' => $item->nhs_prescription,
                'refill_date' => Carbon::make($item->reminder_date)?->format('Y-m-d H:i:s') ?? '0000-00-00 00:00:00',
            ])->sortBy('item_id')->values()->all();

            $basketItems = $basket->items->map(fn($item) => [
                'item_id' => $item->item_id,
                'bundle_id' => $item->bundle_id,
                'prescription_item_id' => $item->prescription_item_id,
                'has_requested_subscription' => $item->has_requested_subscription,
                'has_requested_subscription_period' => $item->has_requested_subscription_period,
                'assessment_id' => $item->assessment_id,
                'quantity' => $item->quantity,
                'recommended_quantity' => $item->recommended_quantity,
                'size' => $item->size,
                'PLU' => $item->PLU,
                'sizeid' => $item->sizeid,
                'nhs_prescription' => $item->nhs_prescription,
                'refill_date' => Carbon::make($item->refill_date)?->format('Y-m-d H:i:s') ?? '0000-00-00 00:00:00',
            ])->sortBy('item_id')->values()->all();

            if ($orderItems !== $basketItems) {
                $basket->items()->delete();

                foreach ($orderItems as $itemData) {
                    $basket->items()->create(array_merge($itemData, ['basket_id' => $basket->id]));
                }
            }
        }
        // Ensure the member's basket_id points to this order's basket
        // so the legacy Basket constructor uses the correct basket
        $current_member = Auth::getLoggedInMember();
        if ($current_member && $current_member->basket_id != $order_eloquent->basket_id) {
            $current_member->basket_id = $order_eloquent->basket_id;
            $current_member->save();
        }

        // Store the specific subscription being retried so the OrderPaidEvent listener activates the right one
        $_SESSION['retry_subscription_id'] = $subscription->id;

        $order_eloquent->save();
    }
} else {
    $_SESSION['unset_paid_basket'] = true;
}


if (!empty($order_id)) {
    $adminUser = User::getAdminUser();
    if (!empty($adminUser)) {
        $order_eloquent = MTC\Shop\Order::query()
            ->find($order_id);
        if (!Auth::isLoggedIn()) {
            // Login admin as this member
            MemberManager::loginAsMember($order_eloquent->member ?? null);
        } else {
            // Only log in as member if currently logged in as another
            if (Auth::getLoggedInMember()->id != $order_eloquent->member) {
                MemberManager::loginAsMember($order_eloquent->member ?? null);
            }
        }
    } else {
        if (!Auth::isLoggedIn()) {
            $redirect = route('members-login', [
                'redirect' => urlencode('/shop/checkout/basket_overview.php?order_id=' . $order_id),
            ], false);

            header('Location: ' . $redirect);
            exit();
        }
        $order_eloquent = MTC\Shop\Order::query()
            ->where('member', Auth::getLoggedInMember()->id)
            ->find($order_id);
    }
    if (empty($order_eloquent)) {
        header("Location: /shop/checkout/basket.php?order_not_found");
        exit();
    }
    if (!empty($order_eloquent->paid)) {
        header("Location: /shop/checkout/basket.php?order_already_paid");
        exit();
    }
    $_SESSION['basket_id'] = $order_eloquent->basket_id;
}

$basket = Basket::getCurrent();
$basket_state_list = $basket->getBasketStateList();
$basket_has_postcodes = $basket->getBasketHasPostcodes();
$basket_placeholder_image = false;
if (!empty($placeholder_images['item_small']['value'])) {
    $basket_placeholder_image = '/' . $image_folders['product_folders']['thumbs']['path']
        . '/' . $placeholder_images['item_small']['value'];
}

$initial_payload = [
    'basket' => $basket,
    'titles' => Member::$titles,
    'genders' => Member::$genders,
    'countries' => $basket_countries,
    'currencies' => $GLOBALS['enabled_currencies'],
    'state_list' => $basket_state_list,
    'has_postcodes' => $basket_has_postcodes,
    'basket_placeholder_image' => $basket_placeholder_image,
    'how_did_you_hear_about_us_choices' => explode("\n", BASKET_HOW_DID_YOU_HEAR_ABOUT_US_CHOICES),
];

$page_meta['title'] = $page_title = 'Payment | ' . config('app.name');
$description = '';
$keywords = '';
$_SESSION['phone_order_id'] = null;
$_SESSION['discounted_order_id'] = null;

$error = '';

if (!empty($_REQUEST['error'])) {
    $error = $_REQUEST['error'];
}

if (MEMBERS_SECTION === true && empty($member->isphoneacc)) {
    $member->isphoneacc = false;
}

if (sizeof($basket->items) == 0) {
    header('Location: basket.php?no-items');
    exit();
}

$state_list = CountryState::getCountryStateList();

// Check if there are any issues with basket validation
$request = [
    'basket' => json_decode(json_encode($basket), true),
    'terms' => 1,
    'ship_to_billing_address' => empty($_SESSION['ship_to_billing_address']) ? 1 : $_SESSION['ship_to_billing_address']
];
$errors = $basket->validate($request, $basket_countries, $state_list);
if (!empty($errors)) {
    header('Location: basket.php');
    exit();
}

if (!empty($_COOKIE['ref']) || !empty($_COOKIE['keywords'])) {
    \Mtc\Shop\Basket::query()
        ->where('id', $_SESSION['basket_id'])
        ->update([
            'ref' => $_COOKIE['ref'],
            'keywords' => $_COOKIE['keywords'],
        ]);
}


// Do not create a new order if we are coming from the failed payment page or if we have order_id in the request
if ($failed_payment || $order_id_in_request) {
    $newbasket = $basket;
    $newbasket->order_id = $order_eloquent->id;
} else {
    $newbasket = MTC\Shop\Order::newOrder($basket);
}

// If the ID check failed during creating the order we need to redirect back and ask for more info
if (!empty($_SESSION['ID_CHECK_STATUS']) && $_SESSION['ID_CHECK_STATUS'] === \Mtc\Plugins\LexisNexisIDU\Classes\IDService::ID_CHECK_FAILED) {
    header('Location: /shop/checkout/basket.php?ID-Verification');
    exit();
}

// store Google Analytics cookie value
if (!empty($_COOKIE['_ga'])) {
    \Mtc\Shop\Order::query()
        ->where('id', $newbasket->order_id)
        ->update([
            'ga_ga' => $_COOKIE['_ga'],
        ]);
}


if (!empty($_SESSION['ID_CHECK_STATUS']) && $_SESSION['ID_CHECK_STATUS'] === \Mtc\Plugins\LexisNexisIDU\Classes\IDService::ID_CHECK_FAILED_CASCADE) {
    $failed_id_check = true;
    Mtc\Shop\Order::query()
        ->where('id', $newbasket->order_id)
        ->update([
            'failed_id_check' => Carbon::now()->format('Y-m-d H:i:s')
        ]);
}

ob_start();

if ($basket->cost_total >= 0.01) {

    if (DEV_MODE || config('ecom.test_mode')) {
        require_once $path . 'shop/checkout/phone_order/order_part3_phone.php';
    }

    if (defined('PAYPAL') && PAYPAL === true) {
        require_once $path . 'shop/checkout/paypal/order_part3_paypal.php';
    }

    if (defined('SAGEPAY') && SAGEPAY === true) {
        require_once $path . 'shop/checkout/sagepay/order_part3_protx.php';
    } elseif (SAGEPAY_SERVER === true) {
        require_once $path . 'shop/checkout/server/payment-form.php';
    }

    if (defined('WORLDPAY') && WORLDPAY == true) {
        require_once $path . 'shop/checkout/worldpay/order_part3_worldpay.php';
    }

    if (defined('STRIPE') && STRIPE === true) {
        require_once $path . 'shop/checkout/stripe/stripe.form.php';
    }

    if (defined('BARCLAYCARD') && BARCLAYCARD) {
        require_once($path . 'shop/checkout/barclaycard/order_part3_barclaycard.php');
    }

    if (defined('BANK_OF_IRELAND') && BANK_OF_IRELAND == true) {
        require_once $path . 'shop/checkout/bank_of_ireland/form.php';
    }

    if (config('judopay.enabled')) {
        Judopay::form();
    }

    if (config('ryftpay.enabled')) {
        RyftPay::form($newbasket);
    }

    /*
     * To allow more dynamic approach of adding payment gateways we are triggering an event to allow
     * registering them. This is a lot cleaner than hard-coding each payment gateway here.
     * Each payment gateway must return a rendered html template of the payment gateway form
     */
    $additional_gateways = Illuminate\Support\Facades\Event::dispatch('shop.checkout.load_payment_gateways', $newbasket);

    // Loop through and echo gateways;
    foreach ($additional_gateways as $gateway) {
        echo $gateway;
    }

} else {
    require_once $path . 'shop/checkout/discounted/order_part3_discounted.php';
}

$payment_form = ob_get_clean();

$shop_data = [
    'basket' => isset($basket) ? $basket : null,
];

$data = [
    'basket_has_subscription' => $basket->has_subscription,
    'failed_id_check_message' => !empty($failed_id_check),
    'page_meta' => $page_meta,
    'settings' => $settings,
    'shop' => $shop_data,
    'payment_form' => $payment_form,
    'hide_inputs' => true,
    'billing_country' => $basket_countries[$basket->address['billing']['country']],
    'shipping_country' => $basket_countries[$basket->address['shipping']['country']],
    'order_id' => $newbasket->order_id,
    'error' => $error,
    'disable_vue' => false,
    'initial_payload' => $initial_payload,
];

if (isset($state_list[$basket->address['billing']['country']][$basket->address['billing']['state']])) {
    $data['billing_state'] = $state_list[$basket->address['billing']['country']][$basket->address['billing']['state']];
} else {
    $data['billing_state'] = null;
}

if (isset($state_list[$basket->address['shipping']['country']][$basket->address['shipping']['state']])) {
    $data['shipping_state'] = $state_list[$basket->address['shipping']['country']][$basket->address['shipping']['state']];
} else {
    $data['shipping_state'] = null;
}

$data['is_consultation'] = !$basket->has_physical_items;


echo $twig->render('shop/basket/overview.twig', $data);
