<?php

namespace App\Service;

use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
 * @codeCoverageIgnore
 */
class MailcowService
{
    public function __construct(
        private HttpClientInterface $httpClient,
        #[Autowire(env: 'MAILCOW_URL')] private string $baseUrl,
        #[Autowire(env: 'MAILCOW_API_KEY')] private string $apiKey,
    ) {
    }

    /**
     * Lister tous les domaines configures dans Mailcow.
     *
     * @return list<array<string, mixed>>
     */
    public function getDomains(): array
    {
        return $this->request('GET', '/api/v1/get/domain/all');
    }

    /**
     * Recuperer les informations d'un domaine.
     *
     * @return array<string, mixed>|null
     */
    public function getDomain(string $domain): ?array
    {
        $data = $this->request('GET', '/api/v1/get/domain/'.$domain);

        if ([] === $data) {
            return null;
        }

        // L'API retourne soit un objet {}, soit un tableau [{...}]
        return isset($data[0]) ? $data[0] : $data;
    }

    /**
     * Recuperer la configuration DNS attendue par Mailcow pour un domaine.
     * Basee sur la documentation Mailcow: https://docs.mailcow.email/prerequisite/dns/.
     *
     * @return list<array{type: string, name: string, content: string, optional: bool}>
     */
    public function getExpectedDnsRecords(string $domain): array
    {
        $hostname = parse_url($this->baseUrl, \PHP_URL_HOST) ?: 'mail.esy-web.dev';

        return [
            // MX obligatoire - reception des mails
            ['type' => 'MX', 'name' => $domain, 'content' => $hostname, 'optional' => false],
            // CNAME autodiscover - configuration auto Outlook
            ['type' => 'CNAME', 'name' => 'autodiscover.'.$domain, 'content' => $hostname, 'optional' => false],
            // CNAME autoconfig - configuration auto Thunderbird
            ['type' => 'CNAME', 'name' => 'autoconfig.'.$domain, 'content' => $hostname, 'optional' => false],
            // SRV autodiscover - decouverte auto des services
            ['type' => 'SRV', 'name' => '_autodiscover._tcp.'.$domain, 'content' => $hostname, 'optional' => true],
            // TXT _mta-sts - politique de securite du transport mail
            ['type' => 'TXT', 'name' => '_mta-sts.'.$domain, 'content' => 'v=STSv1', 'optional' => true],
            // CNAME mta-sts - page de politique MTA-STS
            ['type' => 'CNAME', 'name' => 'mta-sts.'.$domain, 'content' => $hostname, 'optional' => true],
        ];
    }

    /**
     * Recuperer la cle DKIM d'un domaine depuis Mailcow.
     */
    public function getDkimKey(string $domain): ?string
    {
        $data = $this->request('GET', '/api/v1/get/dkim/'.$domain);

        return $data['dkim_txt'] ?? null;
    }

    /**
     * Recuperer les boites mail d'un domaine.
     *
     * @return list<array<string, mixed>>
     */
    public function getMailboxes(string $domain): array
    {
        return $this->request('GET', '/api/v1/get/mailbox/all/'.$domain);
    }

    /**
     * Recuperer le statut du domaine (actif, quota, nb mailboxes).
     *
     * @return array{active: bool, mailboxes: int, quota: int, used_quota: int}|null
     */
    public function getDomainStatus(string $domain): ?array
    {
        $info = $this->getDomain($domain);
        if (null === $info) {
            return null;
        }

        return [
            'active' => (bool) ($info['active'] ?? false),
            'mailboxes' => (int) ($info['mboxes_in_domain'] ?? 0),
            'quota' => (int) ($info['max_quota_for_domain'] ?? 0),
            'used_quota' => (int) ($info['bytes_total'] ?? 0),
        ];
    }

    /**
     * Verifier si l'API Mailcow est accessible.
     */
    public function isAvailable(): bool
    {
        if ('' === $this->apiKey || '' === $this->baseUrl) {
            return false;
        }

        try {
            $this->request('GET', '/api/v1/get/status/containers');

            return true;
        } catch (\Throwable) {
            return false;
        }
    }

    /**
     * @return array<string|int, mixed>
     */
    private function request(string $method, string $path): array
    {
        $response = $this->httpClient->request($method, rtrim($this->baseUrl, '/').$path, [
            'headers' => [
                'X-API-Key' => $this->apiKey,
                'Content-Type' => 'application/json',
            ],
        ]);

        return $response->toArray(false);
    }
}
