<?php
/**
 * 2026 Paysera
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * @author Paysera <plugins@paysera.com>
 * @copyright 2026 Paysera
 * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
 * International Registered Trademark & Property of Paysera
 */

declare(strict_types=1);

namespace Paysera\PrestashopPayments\Installer;

use Paysera\PrestashopPayments\Enum\ConfigurationKey;
use Paysera\PrestashopPayments\Form\PaymentSettingsDataConfiguration;
use Psr\Clock\ClockInterface;
use Psr\Log\LoggerInterface;

if (!defined('_PS_VERSION_')) {
    exit;
}

class ConfigurationInstaller
{
    public function __construct(
        private LoggerInterface $logger,
        private ClockInterface $clock
    ) {
    }

    public function install(): void
    {
        $this->logger->debug('Installing default payment settings');

        $defaults = PaymentSettingsDataConfiguration::getDefaults();

        foreach ($defaults as $field => $value) {
            $this->installSingleSetting($field, $value);
        }

        $this->recordLastUpdated();

        $this->logInstalledSettings($defaults);
    }

    public function recordLastUpdated(): void
    {
        \Configuration::updateValue(
            ConfigurationKey::LAST_UPDATED,
            $this->clock->now()->format('Y-m-d')
        );
    }

    public function uninstall(): void
    {
        $reflection = new \ReflectionClass(ConfigurationKey::class);
        $keys = $reflection->getConstants();

        $preservedCount = 0;

        $this->logger->debug('Clearing module configuration', [
            'key_count' => count($keys),
        ]);

        foreach ($keys as $key) {
            if ($this->shouldPreserveKey($key)) {
                ++$preservedCount;
                continue;
            }
            \Configuration::deleteByName($key);
        }

        $this->logger->debug('Module configuration cleared', [
            'deleted_keys' => count($keys) - $preservedCount,
            'preserved_keys' => $preservedCount,
        ]);
    }

    private function installSingleSetting(string $field, mixed $value): void
    {
        $key = $this->getConfigurationKey($field);

        if ($key === null) {
            return;
        }

        $normalizedValue = $this->normalizeSettingValue($field, $value);
        \Configuration::updateValue($key, $normalizedValue);
    }

    private function normalizeSettingValue(string $field, mixed $defaultValue): string
    {
        $value = $defaultValue;
        if (is_bool($value)) {
            $value = $value ? '1' : '0';
        }

        $result = match ($field) {
            'status_awaiting_payment' => \Configuration::get(ConfigurationKey::CUSTOM_OS_AWAITING_PAYMENT) ? \Configuration::get(ConfigurationKey::CUSTOM_OS_AWAITING_PAYMENT) : $value,
            'status_awaiting_confirmation' => \Configuration::get(ConfigurationKey::CUSTOM_OS_AWAITING_CONFIRMATION) ? \Configuration::get(ConfigurationKey::CUSTOM_OS_AWAITING_CONFIRMATION) : $value,
            default => $value,
        };

        return (string) $result;
    }

    private function logInstalledSettings(array $defaults): void
    {
        $this->logger->info('Default payment settings installed', [
            'settings' => array_merge($defaults, [
                'status_awaiting_payment' => \Configuration::get(ConfigurationKey::STATUS_AWAITING_PAYMENT),
                'status_awaiting_confirmation' => \Configuration::get(ConfigurationKey::STATUS_AWAITING_CONFIRMATION),
                'status_confirmed_payment' => \Configuration::get(ConfigurationKey::STATUS_CONFIRMED_PAYMENT),
            ]),
        ]);
    }

    private function shouldPreserveKey(string $key): bool
    {
        return $key === ConfigurationKey::CUSTOM_OS_AWAITING_PAYMENT
            || $key === ConfigurationKey::CUSTOM_OS_AWAITING_CONFIRMATION;
    }

    private function getConfigurationKey(string $field): ?string
    {
        $constantName = strtoupper($field);
        $fullConstantName = ConfigurationKey::class . '::' . $constantName;

        if (!defined($fullConstantName)) {
            return null;
        }

        return constant($fullConstantName);
    }
}
