<?php

namespace App\Controller;

use App\Entity\Account;
use App\Entity\Contrats;
use App\Entity\ContratsPayments;
use App\Entity\EtatLieux;
use App\Entity\EtatLieuxComment;
use App\Entity\EtatLieuxFile;
use App\Entity\EtatLieuxPointControl;
use App\Entity\EtatLieuxReturnComment;
use App\Entity\EtatLieuxReturnPointControl;
use App\Entity\EtatReturnLieuxFile;
use App\Entity\ProductPointControll;
use App\Entity\Prestaire;
use App\Form\PrestairePasswordType;
use App\Repository\ContratsRepository;
use App\Service\Mailer\Mailer;
use App\Service\Pdf\EtatLieuxPdfService;
use App\Service\Signature\Client as SignatureClient;
use App\Service\Stripe\Client as StripeClient;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\File as MimeFile;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
use Vich\UploaderBundle\Storage\StorageInterface;

class EtlController extends AbstractController
{
    #[Route('/etl', name: 'etl_home')]
    public function eltHome(EntityManagerInterface $entityManager,ContratsRepository $contratsRepository): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        $missions = [];
        $states = ['ready', 'pending', 'progress'];

        $qb = $contratsRepository->createQueryBuilder('c');
        $qb->select('count(c.id)');
        if ($user instanceof Prestaire) {
            $qb->andWhere('c.prestataire = :user')->setParameter('user', $user);
        }
        $totalMissions = $qb->getQuery()->getSingleScalarResult();

        $qb = $contratsRepository->createQueryBuilder('c');
        $qb->select('count(c.id)');
        $qb->andWhere('c.dateAt >= :now')->setParameter('now', new \DateTime());
        $qb->andWhere('c.reservationState IN (:states)')->setParameter('states', $states);
        if ($user instanceof Prestaire) {
            $qb->andWhere('c.prestataire = :user')->setParameter('user', $user);
        }
        $upcomingMissions = $qb->getQuery()->getSingleScalarResult();

        if ($user instanceof Account) {
            $missions = $contratsRepository->findBy(['reservationState' => $states], ['dateAt' => 'ASC'], 5);
        } elseif ($user instanceof Prestaire) {
            $missions = $contratsRepository->findBy(['reservationState' => $states, 'prestataire' => $user], ['dateAt' => 'ASC'], 5);
        }
        $list = [];
        foreach ($missions as $mission) {
            if($mission->isSigned()) {
                $pl = $entityManager->getRepository(ContratsPayments::class)->findOneBy(['type'=>'accompte','contrat'=>$mission]);
                if($pl instanceof ContratsPayments &&$pl->getState() == "complete") {
                    $etatleiux = $mission->getEtatLieux();
                    if(!is_null($etatleiux)) {
                        if($etatleiux->getStatus() != "edl_return_done" && $etatleiux->getStatus() != "edl_return_refused"){
                            $list[] = $mission;
                        }
                    } else {
                        $list[] = $mission;
                    }

                }
            }
        }

        return $this->render('etl/home.twig', [
            'missions' => $list,
            'totalMissions' => $totalMissions,
            'upcomingMissions' => $upcomingMissions
        ]);
    }

    #[Route('/etl/contrats', name: 'etl_contrats')]
    public function eltContrats(ContratsRepository $contratsRepository): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        $missions = [];
        $states = ['ready', 'pending'];

        if ($user instanceof Account) {
            $missions = $contratsRepository->findBy(['reservationState' => $states], ['dateAt' => 'ASC']);
        } elseif ($user instanceof Prestaire) {
            $missions = $contratsRepository->findBy(['reservationState' => $states, 'prestataire' => $user], ['dateAt' => 'ASC']);
        }

        return $this->render('etl/contrats.twig', [
            'missions' => $missions
        ]);
    }

    #[Route('/etl/mission/{id}', name: 'etl_contrat_view', methods: ['GET'])]
    public function eltContratView(Contrats $contrat): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        // Security check for Prestaire
        if ($user instanceof Prestaire && $contrat->getPrestataire() !== $user) {
            throw $this->createAccessDeniedException('Vous n\'avez pas accès à cette mission.');
        }

        // Calculate Totals
        $totalHt = 0;
        $totalCaution = 0;
        $days = ($contrat->getDateAt() && $contrat->getEndAt()) ? ($contrat->getDateAt()->diff($contrat->getEndAt())->days + 1) : 1;

        foreach ($contrat->getContratsLines() as $line) {
            $totalHt += $line->getPrice1DayHt() + ($line->getPriceSupDayHt() * max(0, $days - 1));
            $totalCaution += $line->getCaution();
        }

        foreach ($contrat->getContratsOptions() as $option) {
            $totalHt += $option->getPrice();
        }

        $dejaPaye = 0;
        foreach ($contrat->getContratsPayments() as $p) {
            if ($p->getState() === 'complete' && $p->getType() !== 'caution') {
                $dejaPaye += $p->getAmount();
            }
        }
        $solde = $totalHt - $dejaPaye;

        // Check if Caution is already paid
        $cautionPaid = false;
        foreach ($contrat->getContratsPayments() as $p) {
            if ($p->getType() === 'caution' && $p->getState() === 'complete') {
                $cautionPaid = true;
                break;
            }
        }

        return $this->render('etl/view.twig', [
            'mission' => $contrat,
            'totalCaution' => $totalCaution,
            'solde' => $solde,
            'cautionPaid' => $cautionPaid
        ]);
    }

    #[Route('/etl/mission/{id}/start', name: 'etl_mission_start', methods: ['POST'])]
    public function eltMissionStart(Contrats $contrat, EntityManagerInterface $em, Mailer $mailer): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        if ($user instanceof Prestaire && $contrat->getPrestataire() !== $user) {
            throw $this->createAccessDeniedException('Vous n\'avez pas accès à cette mission.');
        }

        $etatLieux = $contrat->getEtatLieux();
        if (!$etatLieux) {
            $etatLieux = new EtatLieux();
            $etatLieux->setContrat($contrat);
            if ($user instanceof Prestaire) {
                $etatLieux->setPrestataire($user);
            } elseif ($user instanceof Account) {
                $etatLieux->setAccount($user);
            }
            $em->persist($etatLieux);
        }

        $etatLieux->setStatus('delivery_progress');
        $em->flush();

        // Notification client
        if ($contrat->getCustomer()) {
            $mailer->send(
                $contrat->getCustomer()->getEmail(),
                $contrat->getCustomer()->getName(),
                "Votre commande est en route ! - #" . $contrat->getNumReservation(),
                "mails/customer/delivery_start.twig",
                ['contrat' => $contrat]
            );
        }

        $this->addFlash('success', 'Livraison démarrée, le client a été notifié.');
        return $this->redirectToRoute('etl_contrat_view', ['id' => $contrat->getId()]);
    }

    #[Route('/etl/mission/{id}/finish', name: 'etl_mission_finish', methods: ['POST'])]
    public function eltMissionFinish(Contrats $contrat, EntityManagerInterface $em): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        if ($user instanceof Prestaire && $contrat->getPrestataire() !== $user) {
            throw $this->createAccessDeniedException('Vous n\'avez pas accès à cette mission.');
        }

        $etatLieux = $contrat->getEtatLieux();
        if ($etatLieux) {
            $etatLieux->setStatus('delivery_done');
            $em->flush();
            $this->addFlash('success', 'Livraison terminée et confirmée.');
        }

        return $this->redirectToRoute('etl_contrat_view', ['id' => $contrat->getId()]);
    }

    #[Route('/etl/mission/{id}/caution', name: 'etl_mission_caution', methods: ['POST'])]
    public function eltMissionCaution(Contrats $contrat, EntityManagerInterface $em): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        // Check already paid
        foreach ($contrat->getContratsPayments() as $p) {
            if ($p->getType() === 'caution' && $p->getState() === 'complete') {
                $this->addFlash('warning', 'Caution déjà validée.');
                return $this->redirectToRoute('etl_contrat_view', ['id' => $contrat->getId()]);
            }
        }

        // Calculate Caution Amount
        $totalCaution = 0;
        $days = ($contrat->getDateAt() && $contrat->getEndAt()) ? ($contrat->getDateAt()->diff($contrat->getEndAt())->days + 1) : 1;
        foreach ($contrat->getContratsLines() as $line) {
            $totalCaution += $line->getCaution();
        }

        $payment = new ContratsPayments();
        $payment->setContrat($contrat)
            ->setType('caution')
            ->setAmount($totalCaution)
            ->setState('complete')
            ->setPaymentAt(new \DateTimeImmutable())
            ->setValidateAt(new \DateTimeImmutable())
            ->setCard(['type' => 'manuel', 'method' => 'Prestataire'])
            ->setPaymentId("CAUTION-" . uniqid());

        $em->persist($payment);
        $em->flush();

        $this->addFlash('success', 'Caution validée.');
        return $this->redirectToRoute('etl_contrat_view', ['id' => $contrat->getId()]);
    }

    #[Route('/etl/mission/{id}/confirme', name: 'elt_mission_confirme', methods: ['POST'])]
    public function eltMissionConfirme(Contrats $contrat, StripeClient $stripeClient, EntityManagerInterface $em): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        // Calculate Solde
        $totalHt = 0;
        $days = ($contrat->getDateAt() && $contrat->getEndAt()) ? ($contrat->getDateAt()->diff($contrat->getEndAt())->days + 1) : 1;
        foreach ($contrat->getContratsLines() as $line) {
            $totalHt += $line->getPrice1DayHt() + ($line->getPriceSupDayHt() * max(0, $days - 1));
        }
        foreach ($contrat->getContratsOptions() as $option) {
            $totalHt += $option->getPrice();
        }
        $dejaPaye = 0;
        foreach ($contrat->getContratsPayments() as $p) {
            if ($p->getState() === 'complete' && $p->getType() !== 'caution') {
                $dejaPaye += $p->getAmount();
            }
        }
        $solde = $totalHt - $dejaPaye;

        if ($solde <= 0) {
            $this->addFlash('info', 'Le solde est déjà réglé.');
            return $this->redirectToRoute('etl_contrat_view', ['id' => $contrat->getId()]);
        }

        // Create Payment Intent/Session using StripeClient (Using createPaymentSolde logic but manual or new method)
        // Since createPaymentSolde redirects to specific success URL, I might need to adjust or create a generic one.
        // Assuming createPaymentSolde can be reused but we might want custom success URL?
        // Actually, createPaymentSolde sets success_url to /contrat/payment/success/... which is the customer success page.
        // That might be fine, or we want redirection back to ETL?
        // If we want redirection back to ETL, we need a new method in StripeClient or pass options.
        // For now, I will use getNativeClient to build session manually to control success_url.

        try {
            $stripe = $stripeClient->getNativeClient();
            $customer = $contrat->getCustomer();

            // Ensure Stripe Customer exists (Controller helper or reuse existing logic if possible)
            if (!$customer->getCustomerId()) {
                $stripeClient->createCustomer($customer);
                $em->flush();
            }

            $session = $stripe->checkout->sessions->create([
                'customer' => $customer->getCustomerId(),
                'line_items' => [[
                    'price_data' => [
                        'currency' => 'eur',
                        'product_data' => [
                            'name' => 'Solde Réservation #' . $contrat->getNumReservation(),
                            'description' => 'Règlement du solde via interface prestataire',
                        ],
                        'unit_amount' => (int)round($solde * 100),
                    ],
                    'quantity' => 1,
                ]],
                'mode' => 'payment',
                'success_url' => $this->generateUrl('etl_contrat_view', ['id' => $contrat->getId()], UrlGeneratorInterface::ABSOLUTE_URL), // Back to ETL view
                'cancel_url' => $this->generateUrl('etl_contrat_view', ['id' => $contrat->getId()], UrlGeneratorInterface::ABSOLUTE_URL),
                'metadata' => [
                    'contrat_id' => $contrat->getId(),
                    'type' => 'etl_payment' // Special type to trigger specific webhook logic
                ]
            ]);

            // Persist pending payment
            $payment = new ContratsPayments();
            $payment->setContrat($contrat)
                ->setType('etl_payment') // Or 'solde' if we want it standard
                ->setAmount($solde)
                ->setState('created')
                ->setPaymentAt(new \DateTimeImmutable())
                ->setPaymentId($session->id);

            $em->persist($payment);
            $em->flush();

            return new RedirectResponse($session->url);

        } catch (\Exception $e) {
            $this->addFlash('error', 'Erreur Stripe: ' . $e->getMessage());
            return $this->redirectToRoute('etl_contrat_view', ['id' => $contrat->getId()]);
        }
    }

    #[Route('/etl/mission/{id}/manual-pay', name: 'etl_mission_manual_pay', methods: ['POST'])]
    public function eltMissionManualPayment(Contrats $contrat, Request $request, EntityManagerInterface $em): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        $method = $request->request->get('method');
        $amount = (float)$request->request->get('amount'); // Optional, or calculate solde

        if ($amount <= 0) {
            // Calculate Solde if not provided
            $totalHt = 0;
            $days = ($contrat->getDateAt() && $contrat->getEndAt()) ? ($contrat->getDateAt()->diff($contrat->getEndAt())->days + 1) : 1;
            foreach ($contrat->getContratsLines() as $line) {
                $totalHt += $line->getPrice1DayHt() + ($line->getPriceSupDayHt() * max(0, $days - 1));
            }
            foreach ($contrat->getContratsOptions() as $option) {
                $totalHt += $option->getPrice();
            }
            $dejaPaye = 0;
            foreach ($contrat->getContratsPayments() as $p) {
                if ($p->getState() === 'complete' && $p->getType() !== 'caution') {
                    $dejaPaye += $p->getAmount();
                }
            }
            $amount = $totalHt - $dejaPaye;
        }

        if ($amount > 0) {
            $payment = new ContratsPayments();
            $payment->setContrat($contrat)
                ->setType('etl_payment')
                ->setAmount($amount)
                ->setState('complete')
                ->setPaymentAt(new \DateTimeImmutable())
                ->setValidateAt(new \DateTimeImmutable())
                ->setCard(['type' => 'manuel', 'method' => $method])
                ->setPaymentId("MANUAL-" . uniqid());

            $em->persist($payment);
            $em->flush();
            $this->addFlash('success', 'Paiement manuel enregistré.');
        }

        return $this->redirectToRoute('etl_contrat_view', ['id' => $contrat->getId()]);
    }

    #[Route('/etl/mission/{id}/edl/start', name: 'etl_mission_edl_start', methods: ['POST'])]
    public function eltMissionEdlStart(Contrats $contrat, EntityManagerInterface $em): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        $etatLieux = $contrat->getEtatLieux();
        if ($etatLieux) {
            $etatLieux->setStatus('edl_progress');
            $em->flush();
            $this->addFlash('success', 'État des lieux commencé.');
        }

        return $this->redirectToRoute('etl_mission_edl', ['id' => $contrat->getId()]);
    }

    #[Route('/etl/mission/{id}/edl', name: 'etl_mission_edl', methods: ['GET'])]
    public function eltEdl(Contrats $contrat): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        // Security check
        if ($user instanceof Prestaire && $contrat->getPrestataire() !== $user) {
            throw $this->createAccessDeniedException('Vous n\'avez pas accès à cette mission.');
        }

        return $this->render('etl/edl.twig', [
            'mission' => $contrat,
            'etatLieux' => $contrat->getEtatLieux()
        ]);
    }

    #[Route('/etl/mission/{id}/edl/return', name: 'etl_mission_edl_return', methods: ['GET'])]
    public function eltEdlReturn(Contrats $contrat): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        // Security check
        if ($user instanceof Prestaire && $contrat->getPrestataire() !== $user) {
            throw $this->createAccessDeniedException('Vous n\'avez pas accès à cette mission.');
        }

        return $this->render('etl/edl.twig', [
            'mission' => $contrat,
            'etatLieux' => $contrat->getEtatLieux(),
            'isReturnEdl' => true // Flag to indicate it\'s a return EDL
        ]);
    }

    #[Route('/etl/mission/{id}/edl/comment', name: 'etl_edl_add_comment', methods: ['POST'])]
    public function eltEdlAddComment(Contrats $contrat, Request $request, EntityManagerInterface $em): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        $content = $request->request->get('content');
        if ($content) {
            $etatLieux = $contrat->getEtatLieux();
            if($etatLieux->getStatus() == "return_edl_progress") {
                $comment = new EtatLieuxReturnComment();
            } else {
                $comment = new EtatLieuxComment();
            }

            $comment->setContent($content);
            $comment->setEtatLieux($etatLieux);
            $em->persist($comment);
            $em->flush();
            $this->addFlash('success', 'Commentaire ajouté.');
        }

        return $this->redirectToRoute('etl_mission_edl', ['id' => $contrat->getId()]);
    }

    #[Route('/etl/mission/{id}/edl/save-points', name: 'etl_edl_save_points', methods: ['POST'])]
    public function eltEdlSavePoints(Contrats $contrat, Request $request, EntityManagerInterface $em): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        $etatLieux = $contrat->getEtatLieux();
        if (!$etatLieux) {
            return $this->redirectToRoute('etl_mission_edl', ['id' => $contrat->getId()]);
        }

        $data = $request->request->all('points');

        if ($data) {
            foreach ($data as $productId => $points) {
                foreach ($points as $pointId => $values) {
                    $productPoint = $em->getRepository(ProductPointControll::class)->find($pointId);

                    if ($productPoint) {
                        $existing = null;
                        if($etatLieux->getStatus() == "return_edl_progress") {
                            foreach ($etatLieux->getPointControlsReturn() as $ep) {
                                if ($ep->getName() === $productPoint->getName()) {
                                    $existing = $ep;
                                    break;
                                }
                            }

                            if (!$existing) {
                                $existing = new EtatLieuxReturnPointControl();
                                $existing->setName($productPoint->getName());
                                $existing->setEtatLieux($etatLieux);
                                $em->persist($existing);
                            }

                            $existing->setStatus(isset($values['status']));
                            $existing->setDetails($values['details'] ?? null);
                        } else {
                            foreach ($etatLieux->getPointControls() as $ep) {
                                if ($ep->getName() === $productPoint->getName()) {
                                    $existing = $ep;
                                    break;
                                }
                            }

                            if (!$existing) {
                                $existing = new EtatLieuxPointControl();
                                $existing->setName($productPoint->getName());
                                $existing->setEtatLieux($etatLieux);
                                $em->persist($existing);
                            }

                            $existing->setStatus(isset($values['status']));
                            $existing->setDetails($values['details'] ?? null);
                        }

                    }
                }
            }
            $em->flush();
            $this->addFlash('success', 'Points de contrôle enregistrés.');
        }

        return $this->redirectToRoute('etl_mission_edl', ['id' => $contrat->getId()]);
    }

    #[Route('/etl/mission/{id}/edl/file', name: 'etl_edl_add_file', methods: ['POST'])]
    public function eltEdlAddFile(Contrats $contrat, Request $request, EntityManagerInterface $em): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        $photos = $request->files->get('photos');
        $videos = $request->files->get('videos');
        $etatLieux = $contrat->getEtatLieux();
        $hasFiles = false;


        if ($photos) {
            if (!is_array($photos)) $photos = [$photos];
            foreach ($photos as $uploadedFile) {
                if ($uploadedFile instanceof UploadedFile) {
                    $this->compressImage($uploadedFile);

                    if($etatLieux->getStatus() == "return_edl_progress") {
                        $file = new EtatReturnLieuxFile();
                        $file->setFile($uploadedFile);
                        $file->setType('photo');
                        $file->setEtatLieux($etatLieux);
                        $em->persist($file);
                        $hasFiles = true;
                    } else {
                        $file = new EtatLieuxFile();
                        $file->setFile($uploadedFile);
                        $file->setType('photo');
                        $file->setEtatLieux($etatLieux);
                        $em->persist($file);
                        $hasFiles = true;
                    }

                }
            }
        }
        if ($videos) {
            if (!is_array($videos)) $videos = [$videos];
            foreach ($videos as $uploadedFile) {
                if ($uploadedFile instanceof UploadedFile) {
                    $this->compressVideo($uploadedFile);
                    if($etatLieux->getStatus() == "return_edl_progress") {
                        $file = new EtatReturnLieuxFile();
                        $file->setFile($uploadedFile);
                        $file->setType('video');
                        $file->setEtatLieux($etatLieux);
                        $em->persist($file);
                        $hasFiles = true;
                    } else {
                        $file = new EtatLieuxFile();
                        $file->setFile($uploadedFile);
                        $file->setType('video');
                        $file->setEtatLieux($etatLieux);
                        $em->persist($file);
                        $hasFiles = true;
                    }

                }
            }
        }
        if ($hasFiles) {
            $em->flush();
            $this->addFlash('success', 'Fichiers ajoutés.');
        }

        return $this->redirectToRoute('etl_mission_edl', ['id' => $contrat->getId()]);

    }


    #[Route('/etl/mission/{id}/edl/file/{fileId}/delete', name: 'etl_edl_delete_file', methods: ['POST'])]
    public function eltEdlDeleteFile(Contrats $contrat, int $fileId, EntityManagerInterface $em): Response

    {

        $user = $this->getUser();

        if (!$user) {

            return $this->redirectToRoute('etl_login');

        }


        $etatLieux = $contrat->getEtatLieux();

        if($etatLieux->getStatus() == "return_edl_progress") {
            $file = $em->getRepository(EtatReturnLieuxFile::class)->find($fileId);
        } else {
        $file = $em->getRepository(EtatLieuxFile::class)->find($fileId);
}

        if ($file && $file->getEtatLieux() === $etatLieux) {

            $em->remove($file);

            $em->flush();

            $this->addFlash('success', 'Fichier supprimé.');

        }


        return $this->redirectToRoute('etl_mission_edl', ['id' => $contrat->getId()]);

    }


    #[Route('/etl/mission/{id}/edl/finish', name: 'etl_edl_finish', methods: ['POST'])]
    public function eltEdlFinish(Contrats $contrat, EntityManagerInterface $em, KernelInterface $kernel, SignatureClient $signatureClient): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        $etatLieux = $contrat->getEtatLieux();
        if($etatLieux->getStatus() == "return_edl_progress") {
            $etatLieux->setStatus('edl_return_done');
            $this->generateAndSendToDocuSealReturn($contrat, $em, $kernel, $signatureClient);
            $this->addFlash('success', 'État des lieux terminé et PDF généré.');
            return $this->redirectToRoute('etl_mission_signed_entry_state', ['id' => $contrat->getId()]);
        } else {
            if ($etatLieux) {
                $etatLieux->setStatus('edl_done');
                $this->generateAndSendToDocuSeal($contrat, $em, $kernel, $signatureClient);

                $this->addFlash('success', 'État des lieux terminé et PDF généré.');
                return $this->redirectToRoute('etl_mission_signed_entry_state', ['id' => $contrat->getId()]);
            }
        }

        return $this->redirectToRoute('etl_contrat_view', ['id' => $contrat->getId()]);
    }

    #[Route('/etl/mission/{id}/edl/return/start', name: 'etl_mission_edl_return_start', methods: ['POST'])]
    public function eltMissionEdlReturnStart(Contrats $contrat, EntityManagerInterface $em): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        if ($user instanceof Prestaire && $contrat->getPrestataire() !== $user) {
            throw $this->createAccessDeniedException("Vous n'avez pas accès à cette mission.");
        }

        $etatLieux = $contrat->getEtatLieux();
        if ($etatLieux) {
            $etatLieux->setStatus('return_edl_progress');
            $em->flush();
            $this->addFlash('success', 'État des lieux de retour commencé.');
        }

        return $this->redirectToRoute('etl_mission_edl_return', ['id' => $contrat->getId()]);
    }

    #[Route('/etl/mission/{id}/edl/regenerate-view', name: 'etl_edl_regenerate_view', methods: ['GET'])]
    public function eltEdlRegenerateAndView(Contrats $contrat, EntityManagerInterface $em, KernelInterface $kernel, SignatureClient $signatureClient, UploaderHelper $uploaderHelper): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        if($contrat->getEtatLieux()->getStatus() == "edl_return_done") {
            $this->generateAndSendToDocuSealReturn($contrat, $em, $kernel, $signatureClient);
            $etatLieux = $contrat->getEtatLieux();
            $path = $uploaderHelper->asset($etatLieux, 'etatLieuxUnsignReturnFile');
        } else {
            $this->generateAndSendToDocuSeal($contrat, $em, $kernel, $signatureClient);
            $etatLieux = $contrat->getEtatLieux();
            $path = $uploaderHelper->asset($etatLieux, 'etatLieuxUnsignFile');
        }


        return new RedirectResponse($path);
    }

    private function generateAndSendToDocuSeal(Contrats $contrat, EntityManagerInterface $em, KernelInterface $kernel, SignatureClient $signatureClient): void
    {
        $etatLieux = $contrat->getEtatLieux();

        // Generate PDF
        $pdfService = new EtatLieuxPdfService($kernel, $contrat);
        $pdfContent = $pdfService->generate();

        // Save PDF
        $tmpPath = sys_get_temp_dir() . '/edl_entrant_' . $contrat->getId() . '_' . uniqid() . '.pdf';
        file_put_contents($tmpPath, $pdfContent);

        // Update entity with file
        $file = new UploadedFile($tmpPath, 'edl_entrant.pdf', 'application/pdf', null, true);
        $etatLieux->setEtatLieuxUnsignFile($file);
        $etatLieux->setUpdatedAt(new \DateTimeImmutable());

        $em->persist($etatLieux);
        $em->flush(); // Save file

        // Send to DocuSeal
        try {
            $signatureClient->createSubmissionEtatLieux($etatLieux);
        } catch (\Exception $e) {
            // Fallback
        }
    }

    #[Route('/etl/mission/{id}/signed-entry-state', name: 'etl_mission_signed_entry_state', methods: ['GET'])]
    public function eltMissionSignedEntryState(Contrats $contrat, SignatureClient $signatureClient): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        $etatLieux = $contrat->getEtatLieux();

        $providerSigned = false;
        $customerSigned = false;
        if($contrat->getEtatLieux()->getStatus() == "edl_return_done") {
            if ($etatLieux->getSignIdReturn()) {
                try {
                    $sub = $signatureClient->getSubmiter($etatLieux->getSignIdReturn());
                    if ($sub && ($sub['status'] ?? '') === 'completed') $providerSigned = true;
                } catch (\Exception $e) {
                }
            }

            if ($etatLieux->getSignIdCustomerReturn()) {
                try {
                    $sub = $signatureClient->getSubmiter($etatLieux->getSignIdCustomerReturn());
                    if ($sub && ($sub['status'] ?? '') === 'completed') $customerSigned = true;
                } catch (\Exception $e) {
                }
            }
        } else {

            if ($etatLieux->getSignIdDelivery()) {
                try {
                    $sub = $signatureClient->getSubmiter($etatLieux->getSignIdDelivery());
                    if ($sub && ($sub['status'] ?? '') === 'completed') $providerSigned = true;
                } catch (\Exception $e) {
                }
            }

            if ($etatLieux->getSignIdCustomer()) {
                try {
                    $sub = $signatureClient->getSubmiter($etatLieux->getSignIdCustomer());
                    if ($sub && ($sub['status'] ?? '') === 'completed') $customerSigned = true;
                } catch (\Exception $e) {
                }
            }
        }
        return $this->render('etl/signed_entry_state.twig', [
            'mission' => $contrat,
            'etatLieux' => $etatLieux,
            'providerSigned' => $providerSigned,
            'customerSigned' => $customerSigned
        ]);
    }

    #[Route('/etl/sign/provider/{id}', name: 'etl_sign_provider', methods: ['GET'])]
    public function eltSignProvider(EtatLieux $etatLieux, SignatureClient $signatureClient): Response
    {
        // Redirect to DocuSeal URL for Provider
        $url = $signatureClient->getSigningUrl($etatLieux, 'Ludikevent'); // Role name from PDF
        if ($url) {
            return new RedirectResponse($url);
        }
        $this->addFlash('error', 'Lien de signature non disponible.');
        return $this->redirectToRoute('etl_mission_signed_entry_state', ['id' => $etatLieux->getContrat()->getId()]);
    }

    #[Route('/etl/sign/customer/{id}', name: 'etl_sign_customer', methods: ['GET'])]
    public function eltSignCustomer(EtatLieux $etatLieux, SignatureClient $signatureClient): Response
    {
        // Redirect to DocuSeal URL for Customer
        $url = $signatureClient->getSigningUrl($etatLieux, 'Client'); // Role name from PDF
        if ($url) {
            return new RedirectResponse($url);
        }
        $this->addFlash('error', 'Lien de signature non disponible.');
        return $this->redirectToRoute('etl_mission_signed_entry_state', ['id' => $etatLieux->getContrat()->getId()]);
    }

    #[Route('/etl/mission/{id}/edl/close', name: 'etl_edl_close', methods: ['POST'])]
    public function eltMissionCloseEdl(Contrats $contrat, SignatureClient $signatureClient, EntityManagerInterface $em, Mailer $mailer, StorageInterface $storage): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }


        $etatLieux = $contrat->getEtatLieux();
        if($etatLieux->getStatus() == "edl_return_done") {
            if (!$etatLieux || !$etatLieux->getSignIdReturn() || !$etatLieux->getSignIdCustomerReturn()) {
                $this->addFlash('error', 'Signatures manquantes.');
                return $this->redirectToRoute('etl_mission_signed_entry_state', ['id' => $contrat->getId()]);
            }
            // Get signed documents
            $sub = $signatureClient->getSubmiter($etatLieux->getSignIdReturn());
            $submissionId = $sub['submission_id'];
            $submission = $signatureClient->getSubmition($submissionId);

            $signedPdfUrl = $submission['documents'][0]['url'] ?? null;
            $auditUrl = $submission['audit_log_url'] ?? null;

            if ($signedPdfUrl) {
                $tmpPath = sys_get_temp_dir() . '/edl_retour_signed_' . $contrat->getId() . '.pdf';
                file_put_contents($tmpPath, file_get_contents($signedPdfUrl));
                $file = new UploadedFile($tmpPath, 'edl_retour_signed_.pdf', 'application/pdf', null, true);
                $etatLieux->setEtatLieuxSignReturnFile($file);
            }
            if ($auditUrl) {
                $tmpPathAudit = sys_get_temp_dir() . '/edl_retour_audit_signed_' . $contrat->getId() . '.pdf';
                file_put_contents($tmpPathAudit, file_get_contents($auditUrl));
                $file = new UploadedFile($tmpPathAudit, 'edl_retour_audit_signed_.pdf', 'application/pdf', null, true);
                $etatLieux->setEtatLieuxAuditReturnFile($file);
            }
            $etatLieux->setUpdatedAt(new \DateTimeImmutable());

            $etatLieux->setStatus('edl_return_finised');
            $contrat->setReservationState('finished');
            $em->flush();

            // Emails
            $recipients = [
                $contrat->getCustomer()->getEmail(),
                'contact@ludikevent.fr'
            ];
            if ($etatLieux->getPrestataire()) {
                $recipients[] = $etatLieux->getPrestataire()->getEmail();
            }

            $attachments = [];

            // Try resolve path from Vich
            $signPath = $storage->resolvePath($etatLieux, 'etatLieuxSignReturnFile');
            // If resolvePath returns null (e.g. no mapping or file not found yet?), check manual path
            // But flush() should have moved it. resolvePath usually returns absolute path.
            if ($signPath && file_exists($signPath)) {
                $attachments[] = DataPart::fromPath($signPath, 'Etat_des_retour_signe.pdf');
            } elseif (isset($tmpPath) && file_exists($tmpPath)) {
                $attachments[] = DataPart::fromPath($tmpPath, 'Etat_des_retour_signe.pdf');
            }

            $auditPath = $storage->resolvePath($etatLieux, 'etatLieuxAuditReturnFile');
            if ($auditPath && file_exists($auditPath)) {
                $attachments[] = DataPart::fromPath($auditPath, 'Audit_Etat_des_retour_signe.pdf');
            } elseif (isset($tmpPathAudit) && file_exists($tmpPathAudit)) {
                $attachments[] = DataPart::fromPath($tmpPathAudit, 'Audit_Etat_des_retour_signe.pdf');
            }

            foreach (array_unique($recipients) as $email) {
                $mailer->send(
                    $email,
                    'Destinataire',
                    "État des lieux validé - #" . $contrat->getNumReservation(),
                    "mails/etl/edl_retour_confirmation.twig",
                    [
                        'contrat' => $contrat,
                        'etatLieux' => $etatLieux
                    ],
                    $attachments
                );
            }

            $this->addFlash('success', 'État des lieux clôturé et envoyé.');
            return $this->redirectToRoute('etl_contrat_view', ['id' => $contrat->getId()]);
        } else {
            if (!$etatLieux || !$etatLieux->getSignIdDelivery() || !$etatLieux->getSignIdCustomer()) {
                $this->addFlash('error', 'Signatures manquantes.');
                return $this->redirectToRoute('etl_mission_signed_entry_state', ['id' => $contrat->getId()]);
            }
            // Get signed documents
            $sub = $signatureClient->getSubmiter($etatLieux->getSignIdDelivery());
            $submissionId = $sub['submission_id'];
            $submission = $signatureClient->getSubmition($submissionId);

            $signedPdfUrl = $submission['documents'][0]['url'] ?? null;
            $auditUrl = $submission['audit_log_url'] ?? null;

            if ($signedPdfUrl) {
                $tmpPath = sys_get_temp_dir() . '/edl_signed_' . $contrat->getId() . '.pdf';
                file_put_contents($tmpPath, file_get_contents($signedPdfUrl));
                $file = new UploadedFile($tmpPath, 'edl_entrant_signed.pdf', 'application/pdf', null, true);
                $etatLieux->setEtatLieuxSignFile($file);
            }
            if ($auditUrl) {
                $tmpPathAudit = sys_get_temp_dir() . '/edl_audit_signed_' . $contrat->getId() . '.pdf';
                file_put_contents($tmpPathAudit, file_get_contents($auditUrl));
                $file = new UploadedFile($tmpPathAudit, 'edl_audit_signed.pdf', 'application/pdf', null, true);
                $etatLieux->setEtatLieuxAuditFile($file);
            }
            $etatLieux->setUpdatedAt(new \DateTimeImmutable());

            $etatLieux->setStatus('edl_validated');
            $contrat->setReservationState('progress');
            $em->flush();

            // Emails
            $recipients = [
                $contrat->getCustomer()->getEmail(),
                'contact@ludikevent.fr'
            ];
            if ($etatLieux->getPrestataire()) {
                $recipients[] = $etatLieux->getPrestataire()->getEmail();
            }

            $attachments = [];

            // Try resolve path from Vich
            $signPath = $storage->resolvePath($etatLieux, 'etatLieuxSignFile');
            // If resolvePath returns null (e.g. no mapping or file not found yet?), check manual path
            // But flush() should have moved it. resolvePath usually returns absolute path.
            if ($signPath && file_exists($signPath)) {
                $attachments[] = DataPart::fromPath($signPath, 'Etat_des_lieux_signe.pdf');
            } elseif (isset($tmpPath) && file_exists($tmpPath)) {
                $attachments[] = DataPart::fromPath($tmpPath, 'Etat_des_lieux_signe.pdf');
            }

            $auditPath = $storage->resolvePath($etatLieux, 'etatLieuxAuditFile');
            if ($auditPath && file_exists($auditPath)) {
                $attachments[] = DataPart::fromPath($auditPath, 'Audit_Etat_des_lieux_signe.pdf');
            } elseif (isset($tmpPathAudit) && file_exists($tmpPathAudit)) {
                $attachments[] = DataPart::fromPath($tmpPathAudit, 'Audit_Etat_des_lieux_signe.pdf');
            }

            foreach (array_unique($recipients) as $email) {
                $mailer->send(
                    $email,
                    'Destinataire',
                    "État des lieux validé - #" . $contrat->getNumReservation(),
                    "mails/etl/edl_confirmation.twig",
                    [
                        'contrat' => $contrat,
                        'etatLieux' => $etatLieux
                    ],
                    $attachments
                );
            }

            $this->addFlash('success', 'État des lieux clôturé et envoyé.');
            return $this->redirectToRoute('etl_contrat_view', ['id' => $contrat->getId()]);
        }


    }

    #[Route('/etl/account', name: 'etl_account', methods: ['GET', 'POST'])]
    public function eltAccount(
        Request                     $request,
        UserPasswordHasherInterface $passwordHasher,
        EntityManagerInterface      $entityManager
    ): Response
    {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        if ($user instanceof Account) {
            $this->addFlash('warning', 'Les administrateurs ne peuvent pas modifier leur mot de passe ici.');
            return $this->redirectToRoute('etl_home');
        }

        $form = $this->createForm(PrestairePasswordType::class, $user);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $hashedPassword = $passwordHasher->hashPassword(
                $user,
                $form->get('password')->getData()
            );
            $user->setPassword($hashedPassword);

            $entityManager->flush();

            $this->addFlash('success', 'Votre mot de passe a été modifié avec succès.');
            return $this->redirectToRoute('etl_account');
        }

        return $this->render('etl/account.twig', [
            'form' => $form->createView(),
        ]);
    }

    #[Route('/etl/connexion', name: 'etl_login')]
    public function eltLogin(AuthenticationUtils $authenticationUtils): Response
    {
        if ($this->getUser()) {
            return $this->redirectToRoute('etl_home');
        }

        return $this->render('etl/login.twig', [
            'last_username' => $authenticationUtils->getLastUsername(),
            'error' => $authenticationUtils->getLastAuthenticationError()
        ]);
    }

    #[Route('/etl/logout', name: 'elt_logout')]
    public function eltLogout(): Response
    {
        // This method can be blank - it will be intercepted by the logout key on your firewall
        return $this->redirectToRoute('etl_login');
    }

    #[Route('/etl/connect/keycloak', name: 'connect_keycloak_etl_start')]
    public function connectKeycloakEtlStart(ClientRegistry $clientRegistry): RedirectResponse
    {
        return $clientRegistry
            ->getClient('keycloak_etl')
            ->redirect(['openid', 'profile', 'email']);
    }

    #[Route('/etl/oauth/sso', name: 'connect_keycloak_etl_check')]
    public function connectKeycloakEtlCheck(): Response
    {
        return new Response('Auth check', 200); // Intercepted by authenticator
    }

    private function compressImage(UploadedFile $file): UploadedFile
    {
        if (!extension_loaded('gd')) {
            return $file;
        }

        $mime = $file->getMimeType();
        $path = $file->getPathname();

        // Simple compression logic
        switch ($mime) {
            case 'image/jpeg':
                $image = @imagecreatefromjpeg($path);
                if ($image) {
                    imagejpeg($image, $path, 75); // Quality 75
                    imagedestroy($image);
                }
                break;
            case 'image/png':
                $image = @imagecreatefrompng($path);
                if ($image) {
                    // PNG compression 0-9
                    imagepng($image, $path, 6);
                    imagedestroy($image);
                }
                break;
        }

        return $file;
    }

    private function compressVideo(UploadedFile $file): UploadedFile
    {
        // Check if ffmpeg is available
        $ffmpegPath = shell_exec('which ffmpeg');
        if (empty($ffmpegPath)) {
            return $file;
        }

        $inputPath = $file->getPathname();
        $outputPath = $inputPath . '_compressed.mp4';

        // Compress video using ffmpeg (CRF 28 for reasonable quality/size trade-off)
        // -y to overwrite, -vcodec libx264, -crf 28, -preset fast
        $command = sprintf(
            'ffmpeg -y -i %s -vcodec libx264 -crf 28 -preset fast %s 2>&1',
            escapeshellarg($inputPath),
            escapeshellarg($outputPath)
        );

        exec($command, $output, $returnVar);

        if ($returnVar === 0 && file_exists($outputPath)) {
            // Replace original file with compressed one
            if (rename($outputPath, $inputPath)) {
                // Success
            } else {
                // Fallback cleanup
                @unlink($outputPath);
            }
        }

        return $file;
    }

    private function generateAndSendToDocuSealReturn(Contrats $contrat, EntityManagerInterface $em, KernelInterface $kernel, SignatureClient $signatureClient)
    {
        $etatLieux = $contrat->getEtatLieux();

        // Generate PDF
        $pdfService = new EtatLieuxPdfService($kernel, $contrat);
        $pdfContent = $pdfService->generate();


        // Save PDF
        $tmpPath = sys_get_temp_dir() . '/edl_sortant_' . $contrat->getId() . '_' . uniqid() . '.pdf';
        file_put_contents($tmpPath, $pdfContent);

        // Update entity with file
        $file = new UploadedFile($tmpPath, 'edl_sortant_.pdf', 'application/pdf', null, true);
        $etatLieux->setEtatLieuxUnsignReturnFile($file);
        $etatLieux->setUpdatedAt(new \DateTimeImmutable());

        $em->persist($etatLieux);
        $em->flush(); // Save file

        // Send to DocuSeal
        try {
            $signatureClient->createSubmissionEtatLieuxSortant($etatLieux);
        } catch (\Exception $e) {
            // Fallback
        }
    }

    #[Route('/etl/mission/{id}/edl/refused', name: 'etl_edl_customer_refused', methods: ['POST'])]
    public function eltEdlCustomerRefused(
        Contrats $contrat,
        StorageInterface $storage,
        Request $request,
        EntityManagerInterface $em,
        Mailer $mailer
    ): Response {
        $user = $this->getUser();
        if (!$user) {
            return $this->redirectToRoute('etl_login');
        }

        $etatLieux = $contrat->getEtatLieux();

        // On vérifie que l'on est bien en phase de retour
        if (!$etatLieux || $etatLieux->getStatus() !== 'edl_return_done') {
            $this->addFlash('error', 'Action impossible dans l\'état actuel.');
            return $this->redirectToRoute('etl_mission_signed_entry_state', ['id' => $contrat->getId()]);
        }

        // Récupération de la raison saisie
        $reason = $request->request->get('refusal_reason');

        // Mise à jour de l'entité
        // Note : Assurez-vous d'avoir le champ raisonRefus dans votre entité EtatLieux
        $etatLieux->setRaisonRefused($reason);
        $etatLieux->setStatus('edl_return_refused'); // Nouveau status pour différencier

        // On clôture tout de même la mission côté réservation
        $contrat->setReservationState('finished');

        $em->flush();


        // Notification par email (Optionnel mais recommandé)
        $mailer->send(
            'contact@ludikevent.fr',
            'Admin Ludikevent',
            "Signature refusée par le client - #" . $contrat->getNumReservation(),
            "mails/etl/edl_refused_alert.twig",
            [
                'contrat' => $contrat,
                'reason' => $reason,
                'prestataire' => $user
            ]
        );

        $this->addFlash('warning', 'Le refus a été enregistré. La mission est clôturée avec mention de litige.');

        return $this->redirectToRoute('etl_contrat_view', ['id' => $contrat->getId()]);
    }
}
