<?php

namespace App\Controller;

use App\Entity\Contrats;
use App\Entity\ContratsLine;
use App\Entity\ContratsOption;
use App\Service\Pdf\ContratPdfService;
use App\Entity\Account;
use App\Entity\AccountResetPasswordRequest;
use App\Entity\Devis;
use App\Entity\ProductReserve;
use App\Form\RequestPasswordConfirmType;
use App\Form\RequestPasswordRequestType;
use App\Logger\AppLogger;
use App\Repository\ContratsRepository;
use App\Repository\DevisRepository;
use App\Repository\ProductRepository;
use App\Service\Mailer\Mailer;
use App\Service\ResetPassword\Event\ResetPasswordConfirmEvent;
use App\Service\ResetPassword\Event\ResetPasswordEvent;
use App\Service\Signature\Client;
use Doctrine\ORM\EntityManagerInterface;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Contracts\HttpClient\HttpClientInterface;


class SignatureController extends AbstractController
{

    #[Route('/signature/complete', name: 'app_sign_complete')]
    public function appSignComplete(
        Client $client,
        DevisRepository $devisRepository,
        ContratsRepository $contratsRepository,
        ProductRepository $productRepository,
        EntityManagerInterface $entityManager,
        Request $request,
        Mailer $mailer,
        KernelInterface $kernel
    ): Response {
        if ($request->query->get('type') === "contrat") {
            $contrats = $contratsRepository->find($request->query->get('id'));
            if (!$contrats) {
                throw $this->createNotFoundException("Contrat introuvable.");
            }

            // On évite de retraiter un devis déjà marqué comme signé
            if ($contrats->isSigned()) {
                return $this->render('sign/contrat_sign_success.twig', ['contrat' => $contrats]);
            }
            $submiter = $client->getSubmiter($contrats->getSignID());
            $submission = $client->getSubmition($submiter['submission_id']);
            if ($submission['status'] === "completed") {
                $contrats->setIsSigned(true);

                // Update Reservation State if Acompte is already paid
                if ($contrats->isAccompte()) {
                    $contrats->setReservationState('ready');
                }

                $auditUrl = $submission['audit_log_url'];
                $signedDocUrl = $submission['documents'][0]['url'];

                try {
                    // 1. Gestion du PDF SIGNÉ
                    $tmpSigned = sys_get_temp_dir() . '/sign_' . uniqid() . '.pdf';
                    $signedContent = file_get_contents($signedDocUrl);
                    file_put_contents($tmpSigned, $signedContent);

                    // On utilise UploadedFile pour simuler un upload propre pour VichUploader
                    $contrats->setDevisSignFile(new UploadedFile($tmpSigned, "sign-" . $contrats->getNumReservation() . ".pdf", "application/pdf", null, true));

                    // 2. Gestion de l'AUDIT LOG
                    $tmpAudit = sys_get_temp_dir() . '/audit_' . uniqid() . '.pdf';
                    $auditContent = file_get_contents($auditUrl);
                    file_put_contents($tmpAudit, $auditContent);

                    $contrats->setDevisAuditFile(new UploadedFile($tmpAudit, "audit-" . $contrats->getNumReservation() . ".pdf", "application/pdf", null, true));

                    // 3. Préparation des pièces jointes pour le mail (Le PDF signé est le plus important)
                    $attachments = [
                        new DataPart($signedContent, "Contrat -" . $contrats->getNumReservation() . "-Signe.pdf", "application/pdf"),
                        new DataPart($auditContent, "Certificat-Signature-" . $contrats->getNumReservation() . ".pdf", "application/pdf"),
                    ];

                    $entityManager->persist($contrats);

                    foreach ($contrats->getContratsLines() as $line) {
                        $p = $productRepository->findOneBy(['name' => $line->getName()]);
                        $pr = new ProductReserve();
                        $pr->setContrat($contrats);
                        $pr->setProduct($p);
                        $pr->setStartAt($contrats->getDateAt());
                        $pr->setEndAt($contrats->getEndAt());
                        $pr->setCustomer($contrats->getCustomer());
                        $pr->setDevis($contrats->getDevis());
                        $entityManager->persist($pr);
                    }
                    $entityManager->flush();

                    // 5. Envoi du mail de confirmation avec le récapitulatif
                    $mailer->send(
                        $contrats->getCustomer()->getEmail(),
                        $contrats->getCustomer()->getName() . " " . $contrats->getCustomer()->getSurname(),
                        "[Ludikevent] Confirmation de signature - Contrat " . $contrats->getNumReservation(),
                        "mails/sign/signed_contrat.twig",
                        [
                            'contrats' => $contrats // Correction ici : passage de l'objet, pas d'un string
                        ],
                        $attachments
                    );
                    $mailer->send(
                        "contact@ludikevent.fr",
                        "Ludikevent",
                        "[Intranet Ludikevent] Confirmation signature  d'un client pour - Contrat " . $contrats->getNumReservation(),
                        "mails/sign/signed_contrat_notification.twig",
                        [
                            'contrats' => $contrats // Correction ici : passage de l'objet, pas d'un string
                        ],
                        $attachments
                    );
                } catch (\Exception $e) {
                    return new Response("Erreur lors de la récupération ou de l'envoi des documents : " . $e->getMessage(), 500);
                }
            }
            return $this->render('sign/contrat_sign_success.twig', ['contrat' => $contrats]);
        }
        if ($request->query->get('type') === "devis") {
            $devis = $devisRepository->find($request->query->get('id'));

            if (!$devis) {
                throw $this->createNotFoundException("Devis introuvable.");
            }

            // On évite de retraiter un devis déjà marqué comme signé
            if ($devis->getState() === 'signed') {
                return $this->render('sign/sign_success.twig', ['devis' => $devis]);
            }

            $submiter = $client->getSubmiter($devis->getSignatureId());
            $submission = $client->getSubmition($submiter['submission_id']);

            if ($submission['status'] === "completed") {
                $devis->setState("signed");

                $auditUrl = $submission['audit_log_url'];
                $signedDocUrl = $submission['documents'][0]['url'];

                try {
                    // 1. Gestion du PDF SIGNÉ
                    $tmpSigned = sys_get_temp_dir() . '/sign_' . uniqid() . '.pdf';
                    $signedContent = file_get_contents($signedDocUrl);
                    file_put_contents($tmpSigned, $signedContent);

                    // On utilise UploadedFile pour simuler un upload propre pour VichUploader
                    $devis->setDevisSignFile(new UploadedFile($tmpSigned, "sign-" . $devis->getNum() . ".pdf", "application/pdf", null, true));

                    // 2. Gestion de l'AUDIT LOG
                    $tmpAudit = sys_get_temp_dir() . '/audit_' . uniqid() . '.pdf';
                    $auditContent = file_get_contents($auditUrl);
                    file_put_contents($tmpAudit, $auditContent);

                    $devis->setDevisAuditFile(new UploadedFile($tmpAudit, "audit-" . $devis->getNum() . ".pdf", "application/pdf", null, true));

                    // 3. Préparation des pièces jointes pour le mail (Le PDF signé est le plus important)
                    $attachments = [
                        new DataPart($signedContent, "Devis-" . $devis->getNum() . "-Signe.pdf", "application/pdf"),
                        new DataPart($auditContent, "Certificat-Signature-" . $devis->getNum() . ".pdf", "application/pdf"),
                    ];


                    // 4. Sauvegarde en base de données
                    $devis->setUpdateAt(new \DateTimeImmutable());
                    $entityManager->persist($devis);
                    $entityManager->flush();

                    // 5. Envoi du mail de confirmation avec le récapitulatif
                    $mailer->send(
                        $devis->getCustomer()->getEmail(),
                        $devis->getCustomer()->getName() . " " . $devis->getCustomer()->getSurname(),
                        "[Ludikevent] Confirmation de signature - Devis " . $devis->getNum(),
                        "mails/sign/signed.twig",
                        [
                            'devis' => $devis // Correction ici : passage de l'objet, pas d'un string
                        ],
                        $attachments
                    );
                    $mailer->send(
                        "contact@ludikevent.fr",
                        "Ludikevent",
                        "[Intranet Ludikevent] Confirmation signature  d'un client pour - Devis " . $devis->getNum(),
                        "mails/sign/signed_notification.twig",
                        [
                            'devis' => $devis // Correction ici : passage de l'objet, pas d'un string
                        ],
                        $attachments
                    );

                    // --- AUTOMATION: Create Contrat from Devis if OrderSession exists ---
                    if ($devis->getOrderSession()) {
                        $contrat = new Contrats();
                        $contrat->setNumReservation('RESERV-' . date('Ymd') . '-' . substr(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 10));
                        $contrat->setCreateAt(new \DateTimeImmutable());

                        // Hydrate from Devis
                        $contrat->setDateAt($devis->getStartAt())
                            ->setEndAt($devis->getEndAt())
                            ->setCustomer($devis->getCustomer())
                            ->setDevis($devis);

                        if ($devis->getOrderSession()->getPrestataire()) {
                            $contrat->setPrestataire($devis->getOrderSession()->getPrestataire());
                        }

                        if ($address = $devis->getAddressShip()) {
                            $contrat->setAddressEvent($address->getAddress())
                                ->setZipCodeEvent($address->getZipcode())
                                ->setTownEvent($address->getCity());
                        }

                        // Copy Lines
                        foreach ($devis->getDevisLines() as $dLine) {
                            $cLine = (new ContratsLine())
                                ->setName($dLine->getProduct())
                                ->setPrice1DayHt($dLine->getPriceHt())
                                ->setPriceSupDayHt($dLine->getPriceHtSup())
                                ->setCaution(0);

                                $product = $productRepository->findOneBy(['name' => $dLine->getProduct()]);
                                if ($product) {
                                    $cLine->setCaution($product->getCaution());
                                }
                                $entityManager->persist($cLine);
                                $contrat->addContratsLine($cLine);
                        }

                        // Copy Options
                        foreach ($devis->getDevisOptions() as $dOpt) {
                            $cOpt = (new ContratsOption())
                                ->setName($dOpt->getOption())
                                ->setDetails($dOpt->getDetails())
                                ->setPrice($dOpt->getPriceHt());
                            $entityManager->persist($cOpt);
                            $contrat->addContratsOption($cOpt);
                        }

                        // Generate PDF
                        foreach ([true, false] as $isDocuseal) {
                            $service = new ContratPdfService($kernel, $contrat, $isDocuseal);
                            $tmp = sys_get_temp_dir() . '/' . uniqid() . '.pdf';
                            file_put_contents($tmp, $service->generate());

                            $file = new UploadedFile($tmp, 'doc.pdf', 'application/pdf', null, true);
                            $isDocuseal ? $contrat->setDevisDocuSealFile($file) : $contrat->setDevisFile($file);
                        }

                        $entityManager->persist($contrat);
                        $entityManager->flush();

                        // Create Signature Submission
                        $client->createSubmissionContrat($contrat);
                    }
                } catch (\Exception $e) {
                    return new Response("Erreur lors de la récupération ou de l'envoi des documents : " . $e->getMessage(), 500);
                }
            }
        }

        return $this->render('sign/sign_success.twig', [
            'devis' => $devis ?? null
        ]);
    }

}
