<?php

declare(strict_types=1);

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Commerce\Catalog\Configuration;

use Ramsey\Uuid\Uuid;
use Symfony\Component\Intl\Currencies;

final readonly class CatalogIntegrationConfiguration
{
    public function __construct(
        private bool $enabled,
        private string $instanceId,
        #[\SensitiveParameter]
        private string $apiTokenHash,
        private string $currency,
        private ?CatalogConfigurationProvider $configurationProvider = null,
    ) {}

    public function isEnabled(): bool
    {
        if ($this->configurationProvider instanceof CatalogConfigurationProvider) {
            return $this->configurationProvider->current()?->enabled ?? false;
        }

        return $this->enabled;
    }

    public function isHubConnectionEnabled(): bool
    {
        if ($this->configurationProvider instanceof CatalogConfigurationProvider) {
            $snapshot = $this->configurationProvider->current();

            return null !== $snapshot && ($snapshot->enabled || $snapshot->monitoringEnabled);
        }

        return $this->enabled;
    }

    public function isMonitoringEnabled(): bool
    {
        return $this->configurationProvider instanceof CatalogConfigurationProvider
            && ($this->configurationProvider->current()?->monitoringEnabled ?? false);
    }

    public function isApiReady(): bool
    {
        return $this->isEnabled()
            && $this->hasValidInstanceId()
            && 1 === preg_match('/^[a-f0-9]{64}$/i', $this->apiTokenHash);
    }

    public function hasValidInstanceId(): bool
    {
        return Uuid::isValid($this->resolvedInstanceId());
    }

    public function matchesApiToken(#[\SensitiveParameter] string $token): bool
    {
        if (!$this->isApiReady() || '' === $token) {
            return false;
        }

        return hash_equals(mb_strtolower($this->apiTokenHash), hash('sha256', $token));
    }

    public function instanceId(): string
    {
        $instanceId = $this->resolvedInstanceId();
        if (!Uuid::isValid($instanceId)) {
            throw new \LogicException('La configuration Commerce doit contenir un UUID d’instance valide.');
        }

        return Uuid::fromString($instanceId)->toString();
    }

    public function currency(): string
    {
        $currency = $this->configurationProvider instanceof CatalogConfigurationProvider
            ? ($this->configurationProvider->current()?->currency ?? 'EUR')
            : $this->currency;
        $currency = mb_strtoupper($currency);
        if (1 !== preg_match('/^[A-Z]{3}$/', $currency) || !Currencies::exists($currency)) {
            throw new \LogicException('La configuration Commerce doit contenir un code monétaire ISO 4217.');
        }

        return $currency;
    }

    public function minorUnitExponent(): int
    {
        return Currencies::getFractionDigits($this->currency());
    }

    private function resolvedInstanceId(): string
    {
        if ($this->configurationProvider instanceof CatalogConfigurationProvider) {
            return $this->configurationProvider->current()?->instanceId ?? '';
        }

        return $this->instanceId;
    }
}
