<?php

namespace App\Base;

use App\Base\Dto\AppVersionDto;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

final class ConfigResolver
{
    const SEMVER_REGEX = '/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/';

    private array $messages = [];

    public function __construct(
        private readonly DenormalizerInterface $denormalizer,
        private readonly RequestStack $requestStack,

        #[Autowire(param: 'app.url')]
        private readonly ?string $appUrl = null,

        #[Autowire(param: 'app.version')]
        private readonly ?string $appVersion = null,

        #[Autowire(param: 'app.debrid.real_debrid.key')]
        private readonly ?string $realDebridApiKey = null,

        #[Autowire(param: 'app.meta_provider.tmdb.key')]
        private readonly ?string $tmdbApiKey = null,

        #[Autowire(param: 'media.movies_path')]
        private readonly ?string $moviesPath = null,

        #[Autowire(param: 'media.tvshows.path')]
        private readonly ?string $tvshowsPath = null,

        #[Autowire(param: 'auth.method')]
        private readonly ?string $authMethod = null,

        #[Autowire(param: 'auth.oidc.well_known_url')]
        private readonly ?string $authOidcWellKnownUrl = null,

        #[Autowire(param: 'auth.oidc.client_id')]
        private readonly ?string $authOidcClientId = null,

        #[Autowire(param: 'auth.oidc.client_secret')]
        private readonly ?string $authOidcClientSecret = null,

        #[Autowire(param: 'auth.oidc.bypass_form_login')]
        private ?bool $authOidcBypassFormLogin = null,

        #[Autowire(param: 'notification.transport')]
        private ?string $notificationTransport = null,

        #[Autowire(param: 'notification.ntfy.dsn')]
        private ?string $notificationNtfyDsn = null,

        #[Autowire(param: 'sentry.dsn')]
        private ?string $sentryDsn = null,

        #[Autowire(param: 'sentry.environment')]
        private ?string $sentryEnvironment = null,

        #[Autowire(param: 'sentry.javascript_url')]
        private ?string $sentryJavascriptUrl = null,

        #[Autowire(param: 'torrentio.cache_results')]
        private ?bool $torrentioCacheResults = null,
    ) {}

    public function validate(): bool
    {
        $valid = true;

        if (null === $this->realDebridApiKey || "" === $this->realDebridApiKey) {
            $this->messages[] = "Your Real Debrid API key is missing. Please set it to the 'REAL_DEBRID_KEY' environment variable.";
            $valid = false;
        }

        if (null === $this->tmdbApiKey || "" === $this->tmdbApiKey) {
            $this->messages[] = "Your TMDB API key is missing. Please set it to the 'TMDB_API' environment variable.";
            $valid = false;
        }

        if (null !== $this->notificationTransport) {
            if (null === $this->notificationNtfyDsn || "" === $this->notificationNtfyDsn) {
                $this->messages[] = "Your NOTIFICATION_TRANSPORT is set to 'ntfy' but you don't have the NTFY_DSN environment variable set.";
            }
        }

        return $valid;
    }

    public function getMessages(): array
    {
        return $this->messages;
    }

    public function authIs(string $method): bool
    {
        if (strtolower($method) === strtolower($this->getAuthMethod())) {
            return true;
        }
        return false;
    }

    public function getAuthMethod(): string
    {
        return strtolower($this->authMethod);
    }

    public function bypassFormLogin(): bool
    {
        return $this->authOidcBypassFormLogin;
    }

    public function isTorrentioCacheEnabled(): bool
    {
        return $this->torrentioCacheResults;
    }

    public function getAppVersion(): AppVersionDto
    {
        $matches = [];
        preg_match(self::SEMVER_REGEX, $this->appVersion, $matches);
        return $this->denormalizer->denormalize($matches, AppVersionDto::class);
    }

    public function getAuthConfig(): array
    {
        return [
            'method' => $this->authMethod,
            'oidc' => [
                'well_known_url' => $this->authOidcWellKnownUrl,
                'client_id' => $this->authOidcClientId,
                'client_secret' => $this->authOidcClientSecret,
                'bypass_form_login' => $this->authOidcBypassFormLogin,
            ]
        ];
    }

    public function getSentryConfig()
    {
        return [
            'dsn' => $this->sentryDsn,
            'environment' => $this->sentryEnvironment,
            'javascript_url' => $this->sentryJavascriptUrl,
        ];
    }
}
