<?php

declare(strict_types=1);

namespace App\Command;

use App\Entity\Backup;
use App\Service\Mailer\Mailer;
use App\Service\System\DatabaseDumper;
use App\Service\System\ZipArchiver;
use Doctrine\ORM\EntityManagerInterface;
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\HttpKernel\KernelInterface;

#[AsCommand(name: 'app:backup', description: 'Sauvegarde complète PostgreSQL + Images')]
class BackupCommand extends Command
{
    public function __construct(
        private readonly KernelInterface $kernel,
        private readonly EntityManagerInterface $entityManager,
        private readonly Mailer $mailer,
        private readonly DatabaseDumper $databaseDumper,
        private readonly ZipArchiver $zipArchiver,
        ?string $name = null
    ) {
        parent::__construct($name);
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $io->title('Démarrage de la sauvegarde PostgreSQL + Images');

        $backupEntry = new Backup();
        $this->entityManager->persist($backupEntry);
        $this->entityManager->flush();

        $projectDir = $this->kernel->getProjectDir();
        $backupDir = $projectDir . '/sauvegarde';
        $sqlDumpPath = $projectDir . '/var/temp_db.sql';
        $imagesDir = $projectDir . '/public/images';
        $pdfDir = $projectDir . '/public/pdf';
        $seoDif = $projectDir . '/public/seo';

        try {
            if (!is_dir($backupDir)) {
                mkdir($backupDir, 0777, true);
            }

            // 1. DUMP POSTGRESQL
            $dbUrl = $_ENV['DATABASE_URL'] ?? '';
            $io->text('Extraction SQL via pg_dump...');

            $this->databaseDumper->dump($dbUrl, $sqlDumpPath);

            // 2. CRÉATION DU ZIP
            $fileName = sprintf('db_backup_%s.zip', date('Y-m-d_H-i'));
            $zipPath = $backupDir . '/' . $fileName;

            $directoriesToZip = [
                'images' => $imagesDir,
                'pdf' => $pdfDir,
                'seo' => $seoDif,
            ];

            // On s'assure que les dossiers existent avant de les passer (bien que le service vérifie aussi)
            $io->text('Compression des dossiers...');
            $this->zipArchiver->createArchive($zipPath, $sqlDumpPath, $directoriesToZip);

            // 3. STATISTIQUES ET SUCCÈS
            $fileSizeMb = round(filesize($zipPath) / (1024 * 1024), 2);
            $backupEntry->setStatus('SUCCESS');
            $backupEntry->setSizeMb($fileSizeMb);

            $io->success("Sauvegarde réussie : $fileName ($fileSizeMb MB)");

        } catch (\Exception $e) {
            $backupEntry->setStatus('ERROR');
            $backupEntry->setErrorMessage($e->getMessage());
            $io->error("Échec : " . $e->getMessage());
        }

        $this->entityManager->flush();

        // NOTIFICATION
        $statusEmoji = ($backupEntry->getStatus() === 'SUCCESS') ? '✅' : '❌';
        $this->mailer->send(
            'notification@siteconseil.fr',
            'Intranet Ludievent',
            $statusEmoji . ' Sauvegarde - ' . date('d/m/Y'),
            'mails/backup_notification.twig',
            ['backup' => $backupEntry]
        );

        if (file_exists($sqlDumpPath)) unlink($sqlDumpPath);
        $this->cleanOldFiles($backupDir, $io);

        return Command::SUCCESS;
    }

    private function cleanOldFiles(string $backupDir, SymfonyStyle $io): void
    {
        $io->text('Nettoyage historique...');
        $limitDate = new \DateTimeImmutable('-7 days');
        $retentionTs = time() - (7 * 24 * 60 * 60);

        foreach (glob($backupDir . '/*.zip') as $file) {
            if (filemtime($file) <= $retentionTs) unlink($file);
        }

        $this->entityManager->createQuery(
            'DELETE FROM App\Entity\Backup b WHERE b.createdAt <= :limitDate'
        )->setParameter('limitDate', $limitDate)->execute();
    }
}
