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

final readonly class CatalogHubConfiguration
{
    public function __construct(
        private string $hubUrl,
        #[\SensitiveParameter]
        private string $enrollmentToken,
        private string $publicKeyPath,
        private string $jwtIssuer,
        private string $jwtAudience,
        private string $jwtKeyId,
        private bool $allowInsecure,
        private ?CatalogConfigurationProvider $configurationProvider = null,
    ) {}

    public function isEnrollmentReady(): bool
    {
        return $this->hasHubUrl() && '' !== mb_trim($this->resolvedEnrollmentToken());
    }

    public function hasHubUrl(): bool
    {
        return self::isAllowedAbsoluteUrl($this->resolvedHubUrl(), $this->allowInsecure);
    }

    public function hubUrl(): string
    {
        if (!$this->hasHubUrl()) {
            throw new \LogicException('La configuration Commerce doit contenir une URL absolue autorisée pour le hub.');
        }

        return mb_rtrim(mb_trim($this->resolvedHubUrl()), '/');
    }

    public function enrollmentToken(): string
    {
        if (!$this->isEnrollmentReady()) {
            throw new \LogicException('The VitiCore Commerce hub enrollment token is not configured.');
        }

        return mb_trim($this->resolvedEnrollmentToken());
    }

    public function isJwtVerificationReady(): bool
    {
        try {
            return null !== $this->resolvedPublicKeyPem()
                && '' !== $this->jwtIssuer()
                && '' !== $this->jwtAudience()
                && '' !== $this->jwtKeyId();
        } catch (\LogicException) {
            return false;
        }
    }

    public function publicKeyPath(): string
    {
        if ('' === mb_trim($this->publicKeyPath)) {
            throw new \LogicException('The VitiCore Commerce hub JWT public key is not configured.');
        }

        return mb_trim($this->publicKeyPath);
    }

    public function publicKeyPem(): string
    {
        $publicKeyPem = $this->resolvedPublicKeyPem();
        if (null === $publicKeyPem) {
            throw new \LogicException('La clé publique JWT du hub Commerce n’est pas configurée.');
        }

        return $publicKeyPem;
    }

    public function jwtIssuer(): string
    {
        $issuer = $this->configurationProvider instanceof CatalogConfigurationProvider
            ? ($this->configurationProvider->current()?->jwtIssuer ?? '')
            : $this->jwtIssuer;
        if ('' === mb_trim($issuer)) {
            throw new \LogicException('The VitiCore Commerce hub JWT issuer is not configured.');
        }

        return mb_trim($issuer);
    }

    public function jwtAudience(): string
    {
        $audience = $this->configurationProvider instanceof CatalogConfigurationProvider
            ? ($this->configurationProvider->current()?->authAudience ?? '')
            : $this->jwtAudience;
        if ('' === mb_trim($audience)) {
            throw new \LogicException('The VitiCore Commerce hub JWT audience is not configured.');
        }

        return mb_trim($audience);
    }

    public function jwtKeyId(): string
    {
        $keyId = $this->configurationProvider instanceof CatalogConfigurationProvider
            ? ($this->configurationProvider->current()?->jwtKeyId ?? '')
            : $this->jwtKeyId;
        if ('' === mb_trim($keyId)) {
            throw new \LogicException('The VitiCore Commerce hub JWT key id is not configured.');
        }

        return mb_trim($keyId);
    }

    public function allowsInsecureTransport(): bool
    {
        return $this->allowInsecure;
    }

    public static function isAllowedAbsoluteUrl(string $url, bool $allowInsecure): bool
    {
        $url = mb_trim($url);
        if ('' === $url || false === filter_var($url, \FILTER_VALIDATE_URL)) {
            return false;
        }

        $parts = parse_url($url);
        if (!\is_array($parts)
            || '' === (string) ($parts['host'] ?? '')
            || isset($parts['user'])
            || isset($parts['pass'])
            || isset($parts['query'])
            || isset($parts['fragment'])
        ) {
            return false;
        }

        $scheme = mb_strtolower((string) ($parts['scheme'] ?? ''));

        return 'https' === $scheme || ($allowInsecure && 'http' === $scheme);
    }

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

        return $this->hubUrl;
    }

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

        return $this->enrollmentToken;
    }

    private function resolvedPublicKeyPem(): ?string
    {
        if ($this->configurationProvider instanceof CatalogConfigurationProvider) {
            $publicKeyPem = mb_trim($this->configurationProvider->current()?->jwtPublicKeyPem ?? '');

            return '' !== $publicKeyPem ? $publicKeyPem : null;
        }

        $publicKeyPath = mb_trim($this->publicKeyPath);
        if ('' === $publicKeyPath || !is_file($publicKeyPath) || !is_readable($publicKeyPath)) {
            return null;
        }

        $publicKeyPem = file_get_contents($publicKeyPath);

        return false !== $publicKeyPem && '' !== mb_trim($publicKeyPem) ? $publicKeyPem : null;
    }
}
