<?php

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

declare(strict_types=1);

namespace Resursbank\MerchantApi\Service;

use Configuration;
use Country;
use Currency;
use JsonException;
use Language;
use Module;
use ReflectionException;
use Resursbank\Ecom\Config;
use Resursbank\Ecom\Exception\AttributeCombinationException;
use Resursbank\Ecom\Lib\Api\Environment;
use Resursbank\Ecom\Lib\Api\GrantType;
use Resursbank\Ecom\Lib\Api\Scope;
use Resursbank\Ecom\Lib\Locale\Language as EcomLanguage;
use Resursbank\Ecom\Lib\Locale\Location as EcomLocation;
use Resursbank\Ecom\Lib\Log\FileLogger;
use Resursbank\Ecom\Lib\Model\Config\Network;
use Resursbank\Ecom\Lib\Model\Network\Auth\Jwt;
use Resursbank\Ecom\Module\PaymentMethod\Enum\CurrencyFormat;
use Resursbank\MerchantApi\Config\Config as PrestaConfig;
use Resursbank\MerchantApi\Util\Log;
use Throwable;

/**
 * Ecom SDK configuration service.
 */
class Ecom
{
    private PrestaConfig $config;

    /**
     * Constructor.
     *
     * @param PrestaConfig $config Module configuration wrapper.
     */
    public function __construct(PrestaConfig $config)
    {
        $this->config = $config;
    }

    /**
     * Resolve the PrestaShop default language and map it to EcomLanguage.
     */
    public function getLanguage(): EcomLanguage
    {
        try {
            $psLanguageId = (int)Configuration::get(key: 'PS_LANG_DEFAULT');
            $psLanguage = new Language(id: $psLanguageId);
            return EcomLanguage::from(value: strtolower(string: $psLanguage->iso_code));
        } catch (Throwable $e) {
            Log::error(message: 'Failed to resolve language: ' . $e->getMessage());
            return EcomLanguage::EN;
        }
    }

    /**
     * Resolve the PrestaShop default country and map it to EcomLocation.
     */
    public function getLocation(): EcomLocation
    {
        try {
            $psCountryId = (int)Configuration::get(key: 'PS_COUNTRY_DEFAULT');
            $psCountry = new Country(id: $psCountryId);
            return EcomLocation::from(value: strtoupper(string: $psCountry->iso_code));
        } catch (Throwable $e) {
            Log::error(message: 'Failed to resolve location: ' . $e->getMessage());
            return EcomLocation::SE;
        }
    }

    /**
     * Build a FileLogger instance with fallback paths.
     *
     * The logger constructor may throw exceptions if the directory does not exist,
     * is not writable or fails validation. This method ensures safe fallback.
     */
    private function buildLogger(): ?FileLogger
    {
        $path = _PS_ROOT_DIR_ . '/var/logs';

        try {
            return new FileLogger(path: $path);
        } catch (Throwable $e) {
            Log::error(
                message: 'Failed to initialize FileLogger at "' . $path . '": ' . $e->getMessage()
            );
            return null;
        }
    }

    /**
     * Build a JWT authentication object based on module configuration.
     */
    public function buildJwt(Environment $env): ?Jwt
    {
        try {
            $clientId = $this->config->getClientId(environment: $env);

            if ($clientId === '') {
                return null;
            }

            return new Jwt(
                clientId: $clientId,
                clientSecret: $this->config->getClientSecret(environment: $env),
                grantType: GrantType::CREDENTIALS,
            );
        } catch (Throwable $e) {
            Log::error(message: 'Failed to create JWT: ' . $e->getMessage());
            return null;
        }
    }

    /**
     * Initialize and configure the Ecom SDK.
     *
     * This prepares API environment, logging, currency settings,
     * language, location and other relevant configuration inputs.
     *
     * @return void
     * @throws AttributeCombinationException
     * @throws JsonException
     * @throws ReflectionException
     */
    public function configure(): void
    {
        Config::setup(
            logger: $this->buildLogger(),
            jwtAuth: $this->buildJwt(env: $this->config->getEnvironment()),
            paymentHistoryDataHandler: new PaymentHistory(),
            storeId: $this->config->getStoreId(),
            isProduction: $this->config->getEnvironment() === Environment::PROD,
            currencySymbol: (new Currency((int)Configuration::get('PS_CURRENCY_DEFAULT')))->symbol,
            currencyFormat: CurrencyFormat::SYMBOL_LAST,
            language: $this->getLanguage(),
            location: $this->getLocation(),
            network: $this->getNetwork()
        );
    }

    /**
     * @return Network
     * @throws AttributeCombinationException
     * @throws JsonException
     * @throws ReflectionException
     */
    public function getNetwork(): Network
    {
        return new Network(
            userAgent: $this->getUserAgent()
        );
    }

    /**
     * @return string
     */
    public function getUserAgent(): string
    {
        $module = Module::getInstanceByName('resursbank');

        return sprintf(
            '%s %s | PrestaShop %s |',
            'ResursBank-PrestaShop',
            $module->version ?? 'unknown',
            _PS_VERSION_
        );
    }

}
