<?php

namespace App\Command;

use App\Entity\Contrats;
use App\Entity\Devis;
use App\Service\Mailer\Mailer;
use App\Service\Signature\Client;
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:mail',
    description: 'Envoi automatisé des emails de suivi et nettoyage des contrats expirés',
)]
class MailCommand extends Command
{
    public function __construct(
        private readonly KernelInterface $kernel,
        private readonly Client $client,
        private readonly Mailer $mailer,
        private readonly EntityManagerInterface $entityManager
    ) {
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $now = new \DateTime();

        // --- 1. DEVIS NON SIGNÉS ---
        $this->processUnsignedDevis($io, $now);

        // --- 2. CONTRATS NON SIGNÉS (RELANCE & SUPPRESSION) ---
        $this->processUnsignedContrats($io, $now);

        // --- 3. CONTRAT EN ATTENTE D'ACOMPTE ---
        $io->title('Traitement des contrats en attente d\'acompte');
        $contratsNoAccompte = $this->entityManager->getRepository(Contrats::class)->findBy(['isSigned' => true]);
        foreach ($contratsNoAccompte as $contrat) {
            // Skip reminder if payment method is Chorus
            if ($contrat->getDevis() && str_contains((string)$contrat->getDevis()->getPaymentMethod(), 'Chorus')) {
                continue;
            }

            if(!$contrat->isAccompte()) {
                $customer = $contrat->getCustomer();
                if ($customer) {
                    $this->mailer->send(
                        $customer->getEmail(),
                        $customer->getName() . " " . $customer->getSurname(),
                        "[Ludikevent] Rappel : Acompte à régler pour votre réservation N°" . $contrat->getNumReservation(),
                        "mails/task/contrat-noaccompte.twig",
                        ['contrat' => $contrat, 'customer' => $customer]
                    );
                    $io->text("Rappel acompte envoyé pour le contrat : " . $contrat->getNumReservation());
                }
            }
        }

        // --- 5 & 6. RAPPELS LOGISTIQUES (J-3 et J-1) ---
        $this->sendEventReminders($io, 3, "Préparation de votre événement J-3");
        $this->sendEventReminders($io, 1, "À demain ! Dernières infos pour votre événement");

        // --- 7. SATISFACTION (Fin d'événement + 3j) ---
        $io->title('Emails de satisfaction (Fin + 3j)');
        $targetFeedback = (new \DateTime())->modify('-3 days')->setTime(0, 0);
        $finishedContrats = $this->entityManager->getRepository(Contrats::class)->createQueryBuilder('c')
            ->where('c.dateEnd >= :start AND c.dateEnd <= :end')
            ->setParameter('start', $targetFeedback)
            ->setParameter('end', (clone $targetFeedback)->modify('+23 hours 59 mins'))
            ->getQuery()->getResult();

        foreach ($finishedContrats as $contrat) {
            if($contrat->isSolde() && $contrat->isAccompte()){
                $customer = $contrat->getCustomer();
                $this->mailer->send(
                    $customer->getEmail(),
                    $customer->getName(),
                    "[Ludikevent] Votre avis nous intéresse !",
                    "mails/task/feedback.twig",
                    ['contrat' => $contrat, 'customer' => $customer]
                );
                $io->text("Email de satisfaction envoyé à " . $customer->getEmail());
            }
        }

        $this->entityManager->flush();
        $io->success('Toutes les tâches d\'envoi d\'emails et de nettoyage ont été traitées.');

        return Command::SUCCESS;
    }

    private function processUnsignedDevis(SymfonyStyle $io, \DateTime $now): void
    {
        $io->title('Analyse des devis non signés');
        $devisWaiting = $this->entityManager->getRepository(Devis::class)->findBy(['state' => 'wait-sign']);
        foreach ($devisWaiting as $devis) {
            if (!$devis->getCreateA()) continue;

            $diff = $devis->getCreateA()->diff($now)->days;

            // Suppression si plus de 3 jours
            if ($diff >= 3) {
                foreach ($devis->getDevisLines() as $line) {
                    $this->entityManager->persist($line);
                }
                foreach ($devis->getDevisOptions() as $line) {
                    $this->entityManager->persist($line);
                }
                $io->warning("Suppression du devis N°" . $devis->getNum() . " (Non signé après 3 jours)");
                $this->entityManager->remove($devis);
            }
            // Relance si 1 jour révolu (email initial déjà envoyé à 0j)
            elseif ($diff >= 1) {
                $customer = $devis->getCustomer();
                if ($customer) {
                    $this->mailer->send(
                        $customer->getEmail(),
                        $customer->getName(),
                        "[Ludikevent] Devis N°" . $devis->getNum() . " en attente de signature",
                        "mails/task/task-nosigned.twig",
                        ['devis' => $devis, 'customer' => $customer, 'sign' => $this->client->getLinkSign($devis->getSignatureId())]
                    );
                    $io->text("Relance envoyée pour le devis : " . $devis->getNum());
                }
            }
        }
    }

    private function processUnsignedContrats(SymfonyStyle $io, \DateTime $now): void
    {
        $io->title('Analyse des contrats non signés (Relance & Nettoyage)');
        $contratWaiting = $this->entityManager->getRepository(Contrats::class)->findBy(['isSigned' => false]);

        foreach ($contratWaiting as $contrat) {
            if (!$contrat->getCreateAt()) continue;

            $diff = $contrat->getCreateAt()->diff($now)->days;

            // Suppression si plus de 3 jours
            if ($diff >= 3) {
                foreach ($contrat->getContratsLines() as $contratLine) {
                    $this->entityManager->remove($contratLine);
                }
                foreach ($contrat->getContratsOptions() as $contratOption) {
                    $this->entityManager->remove($contratOption);
                }
                $io->warning("Suppression du contrat N°" . $contrat->getNumReservation() . " (Non signé après 3 jours)");
                $this->entityManager->remove($contrat);
            }
            // Relance si 1 jour révolu (mais moins de 3)
            elseif ($diff >= 1) {
                $customer = $contrat->getCustomer();
                if ($customer) {
                    $this->mailer->send(
                        $customer->getEmail(),
                        $customer->getName(),
                        "[Ludikevent] Signature urgente : Contrat N°" . $contrat->getNumReservation(),
                        "mails/task/contrat-nosigned.twig",
                        ['contrat' => $contrat, 'customer' => $customer, 'sign' => $this->client->getLinkSign($contrat->getSignID())]
                    );
                    $io->text("Relance envoyée pour le contrat : " . $contrat->getNumReservation());
                }
            }
        }
    }

    private function sendEventReminders(SymfonyStyle $io, int $daysBefore, string $subject): void
    {
        $io->title("Envoi des rappels J-$daysBefore");
        $targetDate = (new \DateTime())->modify("+$daysBefore days")->setTime(0, 0);

        $contrats = $this->entityManager->getRepository(Contrats::class)->createQueryBuilder('c')
            ->where('c.dateStart >= :start AND c.dateStart <= :end')
            ->andWhere('c.isSigned = true')
            ->setParameter('start', $targetDate)
            ->setParameter('end', (clone $targetDate)->modify('+23 hours 59 mins'))
            ->getQuery()->getResult();

        foreach ($contrats as $contrat) {
            if($contrat->isAccompte() && $contrat->isSigned() && $contrat->isCaution()) {
                $customer = $contrat->getCustomer();
                $this->mailer->send(
                    $customer->getEmail(),
                    $customer->getName(),
                    "[Ludikevent] $subject",
                    "mails/task/event-reminder-j$daysBefore.twig",
                    ['contrat' => $contrat, 'customer' => $customer,'isSolde'=>$contrat->isSolde()]
                );
                $io->text("Rappel J-$daysBefore envoyé pour " . $contrat->getNumReservation());
            }
        }
    }
}
