<?php
declare(strict_types=1);

namespace App\Commands;

use App\Entity\Galaxy;
use App\Services\GalaxyFactory;
use App\Services\GeometryService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(
    name: 'astra:debug:map',
    description: 'Affiche la carte hexagonale d\'une galaxie'
)]
class DebugMapCommand extends Command
{
    public function __construct(
        private EntityManagerInterface $entityManager,
        private GalaxyFactory $galaxyFactory,
        private GeometryService $geometryService
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->addArgument(
                'galaxy-id',
                InputArgument::OPTIONAL,
                'ID de la galaxie à afficher (optionnel)'
            )
            ->addOption(
                'create',
                'c',
                InputOption::VALUE_NONE,
                'Créer une nouvelle galaxie temporaire pour la démonstration'
            )
            ->addOption(
                'sectors',
                's',
                InputOption::VALUE_OPTIONAL,
                'Nombre de secteurs pour la galaxie temporaire',
                '200'
            )
            ->addOption(
                'name',
                null,
                InputOption::VALUE_OPTIONAL,
                'Nom de la galaxie temporaire',
                'Debug Galaxy'
            )
            ->setHelp(
                <<<EOT
Cette commande affiche la représentation graphique d'une galaxie sous forme de grille hexagonale.

Exemples d'utilisation :
  <info>php bin/console astra:debug:map</info>                    # Affiche la première galaxie trouvée
  <info>php bin/console astra:debug:map 1</info>                  # Affiche la galaxie avec l'ID 1
  <info>php bin/console astra:debug:map --create</info>           # Crée une galaxie temporaire
  <info>php bin/console astra:debug:map --create --sectors=500</info> # Crée une galaxie avec 500 secteurs

Légende :
  <comment>X</comment> = Secteur occupé
  <comment>O</comment> = Position disponible mais vide
  <comment>-</comment> = Espace vide (pourtour et centre de la galaxie)
EOT
            );
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $galaxyId = $input->getArgument('galaxy-id');
        $createNew = $input->getOption('create');

        if ($createNew) {
            // Créer une galaxie temporaire
            $sectors = (int) $input->getOption('sectors');
            $name = $input->getOption('name');

            $io->title("Création d'une galaxie temporaire");
            $io->text("Génération de {$sectors} secteurs...");

            $galaxy = $this->galaxyFactory->createGalaxy($sectors, $name);

            $io->success("Galaxie '{$name}' créée avec {$sectors} secteurs");
        } else {
            // Récupérer une galaxie existante
            $galaxyRepository = $this->entityManager->getRepository(Galaxy::class);

            if ($galaxyId) {
                $galaxy = $galaxyRepository->find($galaxyId);
                if (!$galaxy) {
                    $io->error("Aucune galaxie trouvée avec l'ID {$galaxyId}");
                    return Command::FAILURE;
                }
            } else {
                $galaxy = $galaxyRepository->findOneBy([]);
                if (!$galaxy) {
                    $io->error('Aucune galaxie trouvée en base de données. Utilisez --create pour créer une galaxie temporaire.');
                    return Command::FAILURE;
                }
            }
        }

        $this->displayGalaxyInfo($io, $galaxy);
        $this->displayMap($io, $galaxy);
        $this->displayStatistics($io, $galaxy);

        return Command::SUCCESS;
    }

    private function displayGalaxyInfo(SymfonyStyle $io, Galaxy $galaxy): void
    {
        $io->title("Informations de la galaxie");

        $sectorsCount = $galaxy->getSectors()->count();
        $positionedSectors = 0;

        foreach ($galaxy->getSectors() as $sector) {
            if ($sector->getX() !== null && $sector->getY() !== null) {
                $positionedSectors++;
            }
        }

        $io->definitionList(
            ['Nom' => $galaxy->getName()],
            ['ID' => $galaxy->getId() ?? 'N/A (galaxie temporaire)'],
            ['Total secteurs' => $sectorsCount],
            ['Secteurs positionnés' => $positionedSectors],
            ['Secteurs non positionnés' => $sectorsCount - $positionedSectors]
        );
    }

    private function displayMap(SymfonyStyle $io, Galaxy $galaxy): void
    {
        $io->section("Carte de la galaxie");

        // Collecter les positions des secteurs
        $sectorPositions = [];
        foreach ($galaxy->getSectors() as $sector) {
            if ($sector->getX() !== null && $sector->getY() !== null) {
                $sectorPositions[] = [
                    'x' => $sector->getX(),
                    'y' => $sector->getY()
                ];
            }
        }

        if (empty($sectorPositions)) {
            $io->warning('Aucun secteur positionné trouvé. La galaxie n\'a peut-être pas été générée avec les nouvelles coordonnées.');
            return;
        }

        // Régénérer la carte pour le GeometryService
        $this->geometryService->generateGalaxyPositions(count($sectorPositions));

        $map = $this->geometryService->printMap($sectorPositions);

        $io->text('Légende : <fg=green>X</> = Secteur | <fg=yellow>O</> = Disponible | <fg=red>-</> = Vide');
        $io->newLine();

        // Afficher la carte avec des couleurs
        $lines = explode("\n", $map);
        foreach ($lines as $line) {
            if (empty(trim($line))) continue;

            // Colorier la ligne
            $coloredLine = str_replace('X', '<fg=green>X</>', $line);
            $coloredLine = str_replace('O', '<fg=yellow>O</>', $coloredLine);
            $coloredLine = str_replace('-', '<fg=red>-</>', $coloredLine);

            $io->text($coloredLine);
        }
    }

    private function displayStatistics(SymfonyStyle $io, Galaxy $galaxy): void
    {
        $io->section("Statistiques");

        $minX = null;
        $maxX = null;
        $minY = null;
        $maxY = null;
        $totalSystems = 0;

        foreach ($galaxy->getSectors() as $sector) {
            if ($sector->getX() !== null && $sector->getY() !== null) {
                $minX = $minX === null ? $sector->getX() : min($minX, $sector->getX());
                $maxX = $maxX === null ? $sector->getX() : max($maxX, $sector->getX());
                $minY = $minY === null ? $sector->getY() : min($minY, $sector->getY());
                $maxY = $maxY === null ? $sector->getY() : max($maxY, $sector->getY());
            }

            $totalSystems += $sector->getSystems()->count();
        }

        if ($minX !== null) {
            $width = $maxX - $minX + 1;
            $height = $maxY - $minY + 1;
            $ratio = round($width / $height, 2);

            $io->definitionList(
                ['Dimensions' => "{$width} × {$height}"],
                ['Ratio (largeur/hauteur)' => $ratio],
                ['Coordonnées X' => "de {$minX} à {$maxX}"],
                ['Coordonnées Y' => "de {$minY} à {$maxY}"],
                ['Total systèmes' => $totalSystems],
                ['Moyenne systèmes/secteur' => round($totalSystems / $galaxy->getSectors()->count(), 1)]
            );
        }

        // Exemple de calcul de distance et voisins
        $sectors = $galaxy->getSectors()->toArray();
        if (count($sectors) >= 2 && $sectors[0]->getX() !== null) {
            $sector1 = $sectors[0];
            $sector2 = $sectors[1];

            if ($sector2->getX() !== null) {
                $distance = $this->geometryService->getManhattanDistance(
                    $sector1->getX(), $sector1->getY(),
                    $sector2->getX(), $sector2->getY()
                );

                $io->text("Distance Manhattan entre les secteurs {$sector1->getName()} et {$sector2->getName()} : {$distance}");
            }

            $neighbors = $this->geometryService->getHexNeighbors($sector1->getX(), $sector1->getY());
            $io->text("Le secteur {$sector1->getName()} a " . count($neighbors) . " voisins possibles.");
        }
    }
}