<?php // phpcs:disable PSR1.Files.SideEffects.FoundWithSymbols

/** @noinspection PhpCSValidationInspection */

/*
 * Copyright © Resurs Bank AB. All rights reserved.
 * See LICENSE for license details.
 */

declare(strict_types=1);

use Resursbank\Ecom\Exception\HttpException;
use Resursbank\Ecom\Lib\Model\Callback\Authorization as AuthorizationModel;
use Resursbank\Ecom\Lib\Model\Callback\CallbackInterface;
use Resursbank\Ecom\Lib\Model\Callback\Enum\Status as CallbackStatus;
use Resursbank\Ecom\Module\Callback\Http\AuthorizationController;
use Resursbank\Ecom\Module\Callback\Repository;
use Resursbank\Ecom\Module\Payment\Repository as PaymentRepository;
use Resursbank\MerchantApi\Repository\ResursbankOrderRepositoryFrontend;
use Resursbank\MerchantApi\Service\Order as OrderService;
use Resursbank\MerchantApi\Util\Log;
use Resursbank\MerchantApi\Util\Translator;

// phpcs:disable
class ResursbankAuthorizationModuleFrontController extends ModuleFrontController
// phpcs:enable
{
    public function postProcess(): void
    {
        try {
            $callback = (new AuthorizationController())->getRequestData();

            if ($callback->paymentId === '') {
                throw new HttpException(
                    message: __('rb-callback-error-no-resource-id')->getText()
                );
            }

            $order = ResursbankOrderRepositoryFrontend::getOrderByMapiId(
                mapiId: $callback->paymentId
            );

            if ($order === null) {
                throw new HttpException(
                    message: Translator::translate(phraseId: 'rb-callback-error-order-not-found'),
                    code: 503
                );
            }

            if (!Repository::isReady(paymentId: $callback->paymentId)) {
                throw new HttpException(
                    message: Translator::translate(phraseId: 'rb-called-error-order-not-ready'),
                    code: 503
                );
            }

            $code = Repository::process(
                callback: $callback,
                process: static function (
                    CallbackInterface $callback
                ): void {
                    if (!($callback instanceof AuthorizationModel)) {
                        return;
                    }

                    $payment = PaymentRepository::get(paymentId: $callback->paymentId);
                    $order = ResursbankOrderRepositoryFrontend::getOrderByMapiId(
                        mapiId: $callback->paymentId
                    );

                    // If callback is REJECTED cancel the order.
                    if ($callback->status === CallbackStatus::REJECTED) {
                        // Get the configured "canceled" order state ID from PrestaShop.
                        $canceledStateId = (int)Configuration::get(key: 'PS_OS_CANCELED');

                        // Only cancel if the order is not already canceled and has never been canceled before
                        if (
                            (int)$order->getCurrentState() !== $canceledStateId &&
                            !OrderService::hasEverHadStatus(order: $order, statusId: $canceledStateId)
                        ) {
                            OrderService::cancel(order: $order);
                        }

                        return;
                    }

                    // Update order status to "paid" if payment is captured and
                    // add payment to order.
                    // Also make sure we don't double captured payments.
                    if ($payment->isCaptured()) {
                        if ($order->getCurrentState() != Configuration::get(key: OrderService::ORDER_STATE_PAID)) {
                            // Resync.
                            $order->addOrderPayment(
                                amount_paid: $payment->order->capturedAmount,
                                payment_method: $payment->paymentMethod->name,
                                payment_transaction_id: $payment->id
                            );

                            $order->setCurrentState(id_order_state: Configuration::get(key: OrderService::ORDER_STATE_PAID));
                        }

                        // Fix payment method name for invoice payment
                        /** @var PrestaShopCollection<OrderPaymentCore> $orderPayments */
                        $orderPayments = $order->getOrderPaymentCollection();

                        if ($orderPayments && $orderPayments->count() === 1) {
                            /** @var OrderPaymentCore $orderPayment */
                            foreach ($orderPayments as $orderPayment) {
                                // Update payment method name from a Resurs Payment object.
                                $orderPayment->payment_method = $payment->paymentMethod?->name ?? 'Resurs Bank';
                                $orderPayment->transaction_id = $payment->id;
                                $orderPayment->update();
                            }
                        }
                    }
                    $order->save();
                }
            );
        } catch (Throwable $error) {
            $code = 503;
            Log::error(message: $error);
        }

        http_response_code(response_code: $code);
        exit;
    }
}
