<?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\Provider;

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

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

class SettingsProvider
{
    public function __construct(
        private LoggerInterface $logger
    ) {
    }

    public function getSandboxMode(): string
    {
        $value = \Configuration::get(ConfigurationKey::SANDBOX_MODE);

        if ($value === false || $value === '') {
            return 'disabled';
        }

        return (string) $value;
    }

    public function setSandboxMode(string $mode): void
    {
        $oldMode = $this->getSandboxMode();

        \Configuration::updateValue(ConfigurationKey::SANDBOX_MODE, $mode);

        $this->logger->info('Sandbox mode changed', [
            'old_mode' => $oldMode,
            'new_mode' => $mode,
        ]);
    }

    public function toggleSandboxMode(): string
    {
        $newMode = $this->getSandboxMode() === 'enabled' ? 'disabled' : 'enabled';
        $this->setSandboxMode($newMode);

        return $newMode;
    }

    public function isPaymentsEnabled(): bool
    {
        $value = $this->getConfigValueWithDefault(
            ConfigurationKey::ENABLE_PAYMENTS,
            PaymentSettingsDataConfiguration::DEFAULT_ENABLE_PAYMENTS
        );

        if (is_bool($value)) {
            return $value;
        }

        return $value === '1';
    }

    public function getPaymentTitle(): string
    {
        return (string) $this->getConfigValueWithDefault(
            ConfigurationKey::PAYMENT_TITLE,
            PaymentSettingsDataConfiguration::DEFAULT_PAYMENT_TITLE
        );
    }

    public function getPaymentWindowMode(): string
    {
        return (string) $this->getConfigValueWithDefault(
            ConfigurationKey::PAYMENT_WINDOW_MODE,
            PaymentSettingsDataConfiguration::DEFAULT_PAYMENT_WINDOW_MODE
        );
    }

    public function getStatusAwaitingConfirmation(): ?int
    {
        return $this->getStatusWithFallback(
            ConfigurationKey::STATUS_AWAITING_CONFIRMATION,
            ConfigurationKey::CUSTOM_OS_AWAITING_CONFIRMATION
        );
    }

    public function getStatusConfirmedPayment(): ?int
    {
        return $this->getStatusWithFallback(
            ConfigurationKey::STATUS_CONFIRMED_PAYMENT,
            'PS_OS_PAYMENT'
        );
    }

    public function getStatusFailed(): int
    {
        return (int) \Configuration::get('PS_OS_ERROR');
    }

    public function getStatusCancelled(): int
    {
        return (int) \Configuration::get('PS_OS_CANCELED');
    }

    public function getStatusAwaitingPayment(): ?int
    {
        return $this->getStatusWithFallback(
            ConfigurationKey::STATUS_AWAITING_PAYMENT,
            ConfigurationKey::CUSTOM_OS_AWAITING_PAYMENT
        );
    }

    public function setPaymentsEnabled(bool $enabled): void
    {
        $oldValue = $this->isPaymentsEnabled();

        \Configuration::updateValue(
            ConfigurationKey::ENABLE_PAYMENTS,
            $enabled ? '1' : '0'
        );

        $this->logger->info('Payment enabled setting changed', [
            'old_value' => $oldValue,
            'new_value' => $enabled,
        ]);
    }

    public function setPaymentTitle(string $title): void
    {
        \Configuration::updateValue(
            ConfigurationKey::PAYMENT_TITLE,
            $title
        );
    }

    public function setPaymentWindowMode(string $mode): void
    {
        if (!in_array($mode, PaymentSettingsDataConfiguration::ALLOWED_PAYMENT_WINDOW_MODES, true)) {
            $this->logger->error('Invalid payment window mode attempted', [
                'attempted_mode' => $mode,
                'allowed_modes' => PaymentSettingsDataConfiguration::ALLOWED_PAYMENT_WINDOW_MODES,
            ]);

            throw new \InvalidArgumentException(sprintf('Invalid payment window mode: %s', $mode));
        }

        $oldMode = $this->getPaymentWindowMode();

        \Configuration::updateValue(
            ConfigurationKey::PAYMENT_WINDOW_MODE,
            $mode
        );

        $this->logger->info('Payment window mode changed', [
            'old_mode' => $oldMode,
            'new_mode' => $mode,
        ]);
    }

    public function setStatusAwaitingConfirmation(string $status): void
    {
        \Configuration::updateValue(
            ConfigurationKey::STATUS_AWAITING_CONFIRMATION,
            $status
        );
    }

    public function setStatusConfirmedPayment(string $status): void
    {
        \Configuration::updateValue(
            ConfigurationKey::STATUS_CONFIRMED_PAYMENT,
            $status
        );
    }

    public function setStatusAwaitingPayment(string $status): void
    {
        \Configuration::updateValue(
            ConfigurationKey::STATUS_AWAITING_PAYMENT,
            $status
        );
    }

    private function getConfigValueWithDefault(string $key, mixed $default): mixed
    {
        $value = \Configuration::get($key);

        return ($value === false || $value === '') ? $default : $value;
    }

    private function getStatusWithFallback(string $primaryKey, string $fallbackKey): ?int
    {
        $value = \Configuration::get($primaryKey);

        if ($value !== false && $value !== '' && is_numeric($value)) {
            return (int) $value;
        }

        $customValue = \Configuration::get($fallbackKey);

        if ($customValue !== false && $customValue !== '' && is_numeric($customValue)) {
            return (int) $customValue;
        }

        return null;
    }
}
