<?php

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

namespace Resursbank\MerchantApi\Hook;

use JsonException;
use Order;
use PrestaShopBundle\Service\Routing\Router;
use PrestaShopDatabaseException;
use PrestaShopException;
use ReflectionException;
use Resursbank\Ecom\Exception\ApiException;
use Resursbank\Ecom\Exception\AttributeCombinationException;
use Resursbank\Ecom\Exception\AuthException;
use Resursbank\Ecom\Exception\ConfigException;
use Resursbank\Ecom\Exception\CurlException;
use Resursbank\Ecom\Exception\FilesystemException;
use Resursbank\Ecom\Exception\Validation\EmptyValueException;
use Resursbank\Ecom\Exception\Validation\IllegalTypeException;
use Resursbank\Ecom\Exception\Validation\IllegalValueException;
use Resursbank\Ecom\Exception\ValidationException;
use Resursbank\Ecom\Module\Payment\Widget\PaymentInformation;
use Resursbank\Ecom\Module\Widget\PaymentInformation\Js;
use Resursbank\Ecom\Module\PaymentHistory\Widget\Log;
use Resursbank\Ecom\Module\PaymentMethod\Enum\CurrencyFormat;
use Resursbank\MerchantApi\Repository\PaymentHistory;
use Resursbank\MerchantApi\Repository\ResursbankOrder;
use Resursbank\MerchantApi\Exception\HookException;
use Resursbank\MerchantApi\Service\Order as OrderService;
use Resursbank\MerchantApi\Traits\AdminOrderHook;
use Resursbank\MerchantApi\Util\Log as ErrorLogger;
use Throwable;

/**
 * Inject elements on order view, e.g. the payment information widget.
 */
class DisplayAdminOrderMain
{
    use AdminOrderHook;

    /**
     * @param ResursbankOrder $repository
     * @param Router $router
     */
    public function __construct(
        private readonly ResursbankOrder $repository,
        private readonly Router $router
    ) {
    }

    /**
     * @param array $parameters
     * @return string
     *
     * @throws ApiException
     * @throws AttributeCombinationException
     * @throws AuthException
     * @throws ConfigException
     * @throws CurlException
     * @throws EmptyValueException
     * @throws HookException
     * @throws IllegalTypeException
     * @throws IllegalValueException
     * @throws JsonException
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     * @throws ReflectionException
     * @throws ValidationException
     */
    public function exec(array $parameters): string {
        $orderId = $this->getOrderId(parameters: $parameters);
        $order = $this->getOrder(orderId: $orderId);

        if (!OrderService::isResursbank(orderReference: $order->reference)) {
            return '';
        }

        $resursbankOrder = $this->repository->find(orderId: $orderId);
        $payment = $this->getMapiPayment(
            orderId: $orderId,
            repository: $this->repository
        );

        $result = '';
        try {
            $result .= $this->renderPaymentInformation(
                mapiId: $payment->id,
                order: $order
            );
        } catch (Throwable $error) {
            ErrorLogger::error(message: $error);
        }

        try {
            $result .= $this->renderPaymentHistory(
                mapiId: $payment->id,
                resursbankOrderId: $resursbankOrder->getId(),
            );
        } catch (Throwable $error) {
            ErrorLogger::error(message: $error);
        }

        return $result;
    }

    /**
     * Render payment history widget.
     *
     * @param string $mapiId
     * @param int $resursbankOrderId
     * @return string
     * @throws AttributeCombinationException
     * @throws FilesystemException
     * @throws IllegalTypeException
     * @throws JsonException
     * @throws PrestaShopDatabaseException
     * @throws ReflectionException
     */
    public function renderPaymentHistory(
        string $mapiId,
        int $resursbankOrderId,
    ): string {
        $widget = new Log(
            entries: PaymentHistory::find(
                mapiId: $mapiId,
                resursbankOrderId: $resursbankOrderId
            ),
            renderButton: true
        );

        return '<script>' . $widget->js . '</script><style>' . $widget->css .
            '</style>'. $widget->content;
    }

    /**
     * @param string $mapiId
     * @param Order $order
     * @return string
     * @throws AttributeCombinationException
     * @throws FilesystemException
     * @throws HookException
     * @throws IllegalTypeException
     * @throws JsonException
     * @throws ReflectionException
     * @throws ApiException
     * @throws AuthException
     * @throws ConfigException
     * @throws CurlException
     * @throws ValidationException
     * @throws EmptyValueException
     * @throws IllegalValueException
     */
    public function renderPaymentInformation(
        string $mapiId,
        Order $order
    ): string {
        // HTML & CSS.
        $widget = new PaymentInformation(
            paymentId: $mapiId,
            currencySymbol: $this->getCurrency(order: $order)->symbol,
            currencyFormat: CurrencyFormat::SYMBOL_LAST
        );

        // JS.
        $js = new Js(
            amount: $order->total_paid,
            reloadUrl: $this->router->generate(
                name: 'resursbank_admin_order_reload_payment_information',
                parameters: [
                    'mapi_id' => $mapiId
                ]
            ),
            widgetElement: '.rb-pi',
            amountElement: '#orderTotal',
            observableElements: [
                '#orderTotal'
            ],
            automatic: true
        );

        return '<style>' . $widget->css . '</style>' . $widget->content .
            '<script>' . $js->content . '</script>';
    }
}
