<?php

namespace App\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Contracts\HttpClient\HttpClientInterface;

#[AsCommand(
    name: 'app:deploy:config',
    description: 'Initialise et déploie la configuration système en extrayant les infos de l\'inventaire Ansible.',
)]
class DeployConfigCommand extends Command
{
    private const LIBRARY_RULE_NAME = "CRM Cache";
    private const CACHE_PHASE = 'http_request_cache_settings';

    public function __construct(
        private readonly ParameterBagInterface $parameterBag,
        private readonly HttpClientInterface $httpClient
    ) {
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $projectDir = $this->parameterBag->get('kernel.project_dir');

        $mainHost = "ludikevent.fr";

        $host = parse_url($mainHost, PHP_URL_HOST) ?: $mainHost;
        $parts = explode('.', $host);
        $fqdn = count($parts) >= 2 ? implode('.', array_slice($parts, -2)) : $host;

        $io->success(sprintf('Hôte principal détecté : %s', $mainHost));
        $io->info(sprintf('FQDN extrait : %s', $fqdn));

        // 1. Gestion du cache local
        $io->section('Gestion du cache local');
        $filesystem = new Filesystem();
        $cachePath = sys_get_temp_dir() . '/esycms-cache';

        if ($filesystem->exists($cachePath)) {
            $filesystem->remove($cachePath);
            $io->note('Dossier esycms-cache local supprimé.');
        }

        // 2. Configuration Cloudflare via Rulesets
        $io->section('Configuration Cloudflare (Rulesets)');
        $cfToken = $_ENV['CLOUDFLARE_DEPLOY'] ?? null;

        if (!$cfToken) {
            $io->error('La clé API Cloudflare (CLOUDFLARE_DEPLOY) est manquante.');
            return Command::FAILURE;
        }

        try {
            // A. Récupération de la Zone
            $response = $this->httpClient->request('GET', 'https://api.cloudflare.com/client/v4/zones', [
                'headers' => ['Authorization' => 'Bearer ' . $cfToken],
                'query' => ['name' => $fqdn, 'status' => 'active'],
            ]);

            $data = $response->toArray();
            if (empty($data['result'])) {
                $io->error(sprintf('Zone introuvable pour : %s', $fqdn));
                return Command::FAILURE;
            }

            $zoneId = $data['result'][0]['id'];

            // B. Récupération ou Création du Ruleset ID pour la phase de cache
            $rulesetsResponse = $this->httpClient->request('GET', "https://api.cloudflare.com/client/v4/zones/$zoneId/rulesets", [
                'headers' => ['Authorization' => 'Bearer ' . $cfToken]
            ]);

            $rulesets = $rulesetsResponse->toArray()['result'] ?? [];
            $rulesetId = null;
            foreach ($rulesets as $rs) {
                if ($rs['phase'] === self::CACHE_PHASE) {
                    $rulesetId = $rs['id'];
                    break;
                }
            }

            if (!$rulesetId) {
                $io->note('Création du ruleset de cache...');
                $createResponse = $this->httpClient->request('POST', "https://api.cloudflare.com/client/v4/zones/$zoneId/rulesets", [
                    'headers' => [
                        'Authorization' => 'Bearer ' . $cfToken,
                        'Content-Type' => 'application/json',
                    ],
                    'json' => [
                        'name' => 'CRM Cache Ruleset',
                        'description' => 'Ruleset pour la gestion du cache CRM',
                        'kind' => 'zone',
                        'phase' => self::CACHE_PHASE
                    ]
                ]);
                $rulesetId = $createResponse->toArray()['result']['id'];
            }

            // C. Récupération des règles actuelles pour filtrage
            $rulesResponse = $this->httpClient->request('GET', "https://api.cloudflare.com/client/v4/zones/$zoneId/rulesets/$rulesetId", [
                'headers' => ['Authorization' => 'Bearer ' . $cfToken]
            ]);
            $currentRules = $rulesResponse->toArray()['result']['rules'] ?? [];

            // D. Reconstruction de la liste des règles (Sanitization pour éviter l'erreur 400)
            $sanitizedRules = [];
            foreach ($currentRules as $rule) {
                if (($rule['description'] ?? '') === self::LIBRARY_RULE_NAME) {
                    continue;
                }

                // On ne conserve que les champs mutables autorisés par l'API
                $sanitizedRules[] = [
                    'expression' => $rule['expression'],
                    'description' => $rule['description'] ?? '',
                    'action' => $rule['action'],
                    'action_parameters' => $rule['action_parameters'] ?? null,
                    'enabled' => $rule['enabled'] ?? true,
                ];
            }

            // E. Ajout de la règle pour /library/
            $sanitizedRules[] = [
                'expression' => sprintf('http.host in {"intranet.ludikevent.fr" "reservation.ludikevent.fr"} and (http.request.uri.path contains "/provider") or (http.request.uri.path contains "/images/image_options") or (http.request.uri.path contains "/images/image_product") or (http.request.uri.path contains "/media")'),
                'description' => self::LIBRARY_RULE_NAME,
                'action' => 'set_cache_settings',
                'action_parameters' => [
                    'cache' => true,
                    'edge_ttl' => [
                        'mode' => 'override_origin',
                        'default' => 31536000
                    ],
                    'browser_ttl' => [
                        'mode' => 'override_origin',
                        'default' => 31536000
                    ]
                ],
                'enabled' => true
            ];

            // F. Mise à jour globale du ruleset via PUT
            $this->httpClient->request('PUT', "https://api.cloudflare.com/client/v4/zones/$zoneId/rulesets/$rulesetId", [
                'headers' => [
                    'Authorization' => 'Bearer ' . $cfToken,
                    'Content-Type' => 'application/json',
                ],
                'json' => [
                    'rules' => $sanitizedRules
                ]
            ]);

            $io->success(sprintf('Ruleset Cloudflare mis à jour pour %s (Cache 1 an sur /storage/).', $fqdn));

        } catch (\Exception $e) {
            $io->error('Erreur Cloudflare Ruleset : ' . $e->getMessage());
            return Command::FAILURE;
        }

        return Command::SUCCESS;
    }
}
