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

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

declare(strict_types=1);

use Resursbank\Ecom\Exception\ApiException;
use Resursbank\Ecom\Exception\AttributeCombinationException;
use Resursbank\Ecom\Exception\AuthException;
use Resursbank\Ecom\Exception\CacheException;
use Resursbank\Ecom\Exception\ConfigException;
use Resursbank\Ecom\Exception\CurlException;
use Resursbank\Ecom\Exception\FilesystemException;
use Resursbank\Ecom\Exception\HttpException as EcomHttpException;
use Resursbank\Ecom\Exception\TranslationException;
use Resursbank\Ecom\Exception\Validation\EmptyValueException;
use Resursbank\Ecom\Exception\Validation\IllegalTypeException;
use Resursbank\Ecom\Exception\Validation\IllegalValueException;
use Resursbank\Ecom\Exception\Validation\MissingKeyException;
use Resursbank\Ecom\Exception\ValidationException;
use Resursbank\Ecom\Lib\Http\Controller as EcomController;
use Resursbank\Ecom\Lib\Model\PaymentMethod\PartPayment\InfoResponse;
use Resursbank\MerchantApi\Service\PartPayment;
use Resursbank\MerchantApi\Util\Log;

/**
 * Wrapper class for Part payment widget javascript.
 */
// phpcs:disable
class ResursbankPartPaymentModuleFrontController extends ModuleFrontController
// phpcs:enable
{
    /**
     * Process input and initialize widget object.
     *
     * @return void
     */
    public function postProcess(): void
    {
        try {
            $amount = $this->getAmount();

            if ($amount === 0.0) {
                throw new Exception('Invalid amount');
            }

            header('Content-Type: application/json');
            echo json_encode(value: $this->getResponse(amount: $amount));
            exit;
        } catch (Throwable $error) {
            Log::error(message: $error);
        }
    }

    /**
     * Get amount from actual request body.
     *
     * @return float
     * @throws ConfigException
     * @throws EcomHttpException
     */
    private function getAmount(): float
    {
        // Read raw input data, cause PrestaShop will overwrite our "amount"
        // property in the incoming request with its own value taken from its
        // context, meaning that when we attempt to fetch updated part payment
        // widget HTML, it will always be based on the price of the product
        // unless we read the raw input data.
        $data = (new EcomController())->getInputDataAsStdClass();

        return isset($data->amount) ? (float) $data->amount : 0.0;
    }

    /**
     * Resolve response data.
     *
     * @param float $amount
     * @return InfoResponse
     * @throws AttributeCombinationException
     * @throws ConfigException
     * @throws JsonException
     * @throws ReflectionException
     * @throws Throwable
     * @throws ApiException
     * @throws AuthException
     * @throws CacheException
     * @throws CurlException
     * @throws FilesystemException
     * @throws TranslationException
     * @throws ValidationException
     * @throws EmptyValueException
     * @throws IllegalTypeException
     * @throws IllegalValueException
     * @throws MissingKeyException
     */
    public function getResponse(float $amount): InfoResponse
    {
        $widget = PartPayment::getWidget(
            context: Context::getContext(),
            amount: $amount
        );

        return new InfoResponse(
            startingAt: $widget->cost->monthlyCost,
            html: $widget->content,
            readMoreHtml: $widget->readMore->content,
        );
    }
}
