<?php

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

declare(strict_types=1);

namespace Resursbank\MerchantApi\Controller\Admin\Config;

use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
use Resursbank\Ecom\Config as EcomConfig;
use Resursbank\Ecom\Exception\AuthException;
use Resursbank\Ecom\Exception\ConfigException;
use Resursbank\Ecom\Exception\HttpException;
use Resursbank\Ecom\Lib\Api\Environment;
use Resursbank\Ecom\Lib\Api\GrantType;
use Resursbank\Ecom\Lib\Api\Scope;
use Resursbank\Ecom\Lib\Model\Network\Auth\Jwt;
use Resursbank\Ecom\Lib\Model\Store\GetStoresRequest;
use Resursbank\Ecom\Lib\Model\Store\Store;
use Resursbank\Ecom\Module\Store\Http\GetStoresController;
use Resursbank\Ecom\Module\Store\Repository as StoreRepository;
use Resursbank\MerchantApi\Config\Config;
use Resursbank\MerchantApi\Util\Log;
use Resursbank\MerchantApi\Util\Translator;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Throwable;

class GetStores extends FrameworkBundleAdminController
{
    public function __construct(
        private readonly Config $config
    ) {
        parent::__construct();
    }

    /**
     * Fetch payment methods from API and sync them to database.
     *
     * @param Request $request
     *
     * @return JsonResponse
     */
    public function execute(
        Request $request
    ): JsonResponse {
        try {
            $requestData = $this->getRequestData();
            $env = $requestData->environment;

            EcomConfig::setup(
                jwtAuth: new Jwt(
                    clientId: $requestData->clientId,
                    clientSecret: $requestData->clientSecret,
                    grantType: GrantType::CREDENTIALS,
                    scope: $requestData->environment === Environment::PROD ?
                        Scope::MERCHANT_API :
                        Scope::MOCK_MERCHANT_API
                ),
                isProduction: $env === Environment::PROD,
            );

            $stores = StoreRepository::getStores();
            $data = [];

            /** @var Store $store */
            foreach ($stores as $store) {
                $data[$store->id] = $store->name;
            }
        } catch (AuthException) {
            $data = ['error' => Translator::translate('api-connection-failed-bad-credentials')];
        } catch (Throwable $error) {
            Log::error(message: $error);
            $data = ['error' => Translator::translate('get-stores-could-not-fetch')];
        }

        return new JsonResponse(data: $data);
    }

    /**
     * Resolve and convert data from HTTP request to fetch stores.
     *
     * @throws HttpException
     * @throws ConfigException
     */
    public function getRequestData(): GetStoresRequest
    {
        $result = null;
        $controller = new GetStoresController();
        $data = $controller->getInputDataAsStdClass();

        try {
            // When saved the secret is encrypted. Meaning the form input will
            // be empty if unchanged.
            if (!isset($data->clientSecret) || $data->clientSecret === '') {
                $data->clientSecret = $this->config->getClientSecret(
                    environment: Environment::from($data->environment)
                );
            }

            /*// Convert environment value.
            if (isset($data->environment)) {
                $data->environment = $data->environment->value;
            }*/

            // Create model with request data from converted values.
            $result = $controller->getRequestModel(
                model: GetStoresRequest::class,
                data: $data
            );
        } catch (Throwable $error) {
            Log::error(message: $error);
        }

        if (!$result instanceof GetStoresRequest) {
            throw new HttpException(
                message: $controller->translateError(
                    phraseId: 'invalid-post-data'
                ),
                code: 415
            );
        }

        return $result;
    }
}
