<?php

namespace App\Service;

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

/**
 * @codeCoverageIgnore
 */
class CloudflareService
{
    private const API_URL = 'https://api.cloudflare.com/client/v4';

    public function __construct(
        private HttpClientInterface $httpClient,
        #[Autowire(env: 'CLOUDFLARE_KEY')] private string $apiKey,
    ) {
    }

    /**
     * Recuperer le zone ID d'un domaine.
     */
    public function getZoneId(string $domain): ?string
    {
        $data = $this->request('GET', '/zones', ['name' => $domain]);

        return $data['result'][0]['id'] ?? null;
    }

    /**
     * Recuperer tous les enregistrements DNS d'une zone.
     *
     * @return list<array<string, mixed>>
     */
    /**
     * Recuperer tous les enregistrements DNS d'une zone (avec pagination).
     *
     * @return list<array<string, mixed>>
     */
    public function getDnsRecords(string $zoneId, int $perPage = 100): array
    {
        $allRecords = [];
        $page = 1;

        do {
            $data = $this->request('GET', '/zones/'.$zoneId.'/dns_records', [
                'per_page' => $perPage,
                'page' => $page,
            ]);

            $records = $data['result'] ?? [];
            $allRecords = array_merge($allRecords, $records);

            $totalPages = $data['result_info']['total_pages'] ?? 1;
            ++$page;
        } while ($page <= $totalPages);

        return $allRecords;
    }

    /**
     * Recuperer les enregistrements DNS d'un type specifique.
     *
     * @return list<array<string, mixed>>
     */
    public function getDnsRecordsByType(string $zoneId, string $type): array
    {
        $data = $this->request('GET', '/zones/'.$zoneId.'/dns_records', ['type' => $type, 'per_page' => 100]);

        return $data['result'] ?? [];
    }

    /**
     * Recuperer les informations d'une zone.
     *
     * @return array<string, mixed>|null
     */
    public function getZone(string $zoneId): ?array
    {
        $data = $this->request('GET', '/zones/'.$zoneId);

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

    /**
     * Lister toutes les zones du compte.
     *
     * @return list<array<string, mixed>>
     */
    public function listZones(): array
    {
        $allZones = [];
        $page = 1;

        do {
            $data = $this->request('GET', '/zones', ['per_page' => 50, 'page' => $page]);
            $zones = $data['result'] ?? [];
            $allZones = array_merge($allZones, $zones);
            $totalPages = $data['result_info']['total_pages'] ?? 1;
            ++$page;
        } while ($page <= $totalPages);

        return $allZones;
    }

    /**
     * Supprimer un enregistrement DNS.
     */
    public function deleteDnsRecord(string $zoneId, string $recordId): bool
    {
        $data = $this->request('DELETE', '/zones/'.$zoneId.'/dns_records/'.$recordId);

        return true === ($data['success'] ?? false);
    }

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

        try {
            $data = $this->request('GET', '/zones', ['per_page' => 1]);

            return true === ($data['success'] ?? false);
        } catch (\Throwable) {
            return false;
        }
    }

    /**
     * @param array<string, mixed> $query
     *
     * @return array<string, mixed>
     */
    private function request(string $method, string $path, array $query = []): array
    {
        $options = [
            'headers' => ['Authorization' => 'Bearer '.$this->apiKey],
        ];

        if ([] !== $query) {
            $options['query'] = $query;
        }

        $response = $this->httpClient->request($method, self::API_URL.$path, $options);

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