<?php

namespace App\Controller\Admin;

use App\Entity\Facture;
use App\Service\MailerService;
use App\Service\MeilisearchService;
use App\Service\Pdf\FacturePdf;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
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\Routing\Attribute\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Twig\Environment;

#[Route('/admin/facture', name: 'app_admin_facture_')]
#[IsGranted('ROLE_EMPLOYE')]
class FactureController extends AbstractController
{
    public function __construct(
        private EntityManagerInterface $em,
        private MeilisearchService $meilisearch,
    ) {
    }

    #[Route('/search/{customerId}', name: 'search', requirements: ['customerId' => '\d+'], methods: ['GET'])]
    public function search(int $customerId, Request $request): JsonResponse
    {
        $query = trim($request->query->getString('q'));
        if ('' === $query) {
            return $this->json([]);
        }

        return $this->json($this->meilisearch->searchFactures($query, 20, $customerId));
    }

    #[Route('/{id}/generate-pdf', name: 'generate_pdf', requirements: ['id' => '\d+'], methods: ['POST'])]
    public function generatePdf(int $id, KernelInterface $kernel, UrlGeneratorInterface $urlGenerator, Environment $twig): Response
    {
        $facture = $this->em->getRepository(Facture::class)->find($id);
        if (null === $facture) {
            throw $this->createNotFoundException('Facture introuvable');
        }

        $pdf = new FacturePdf($kernel, $facture, $urlGenerator, $twig);
        $pdf->generate();

        $tmpPath = tempnam(sys_get_temp_dir(), 'facture_').'.pdf';
        $pdf->Output('F', $tmpPath);

        $hadOld = null !== $facture->getFacturePdf();
        $uploadDir = $kernel->getProjectDir().'/public/uploads/factures';

        if ($hadOld) {
            $oldPath = $uploadDir.'/'.$facture->getFacturePdf();
            if (file_exists($oldPath)) {
                @unlink($oldPath);
            }
            $facture->setFacturePdf(null);
        }

        $uploadedFile = new UploadedFile(
            $tmpPath,
            'facture-'.str_replace('/', '-', $facture->getInvoiceNumber()).'.pdf',
            'application/pdf',
            null,
            true
        );

        $facture->setFacturePdfFile($uploadedFile);
        $facture->setUpdatedAt(new \DateTimeImmutable());

        $this->em->flush();

        @unlink($tmpPath);

        $this->addFlash('success', 'PDF facture '.$facture->getInvoiceNumber().' '.($hadOld ? 'regenere' : 'genere').'.');

        return $this->redirectToRoute('app_admin_clients_show', [
            'id' => $facture->getCustomer()?->getId() ?? 0,
            'tab' => 'factures',
        ]);
    }

    #[Route('/{id}/send', name: 'send', requirements: ['id' => '\d+'], methods: ['POST'])]
    public function send(
        int $id,
        MailerService $mailer,
        Environment $twig,
        UrlGeneratorInterface $urlGenerator,
        KernelInterface $kernel,
        #[Autowire('%kernel.project_dir%')] string $projectDir,
    ): Response {
        $facture = $this->em->getRepository(Facture::class)->find($id);
        if (null === $facture) {
            throw $this->createNotFoundException('Facture introuvable');
        }

        // Auto-generer le PDF si il n'existe pas
        if (null === $facture->getFacturePdf()) {
            $pdf = new FacturePdf($kernel, $facture, $urlGenerator, $twig);
            $pdf->generate();

            $tmpPath = tempnam(sys_get_temp_dir(), 'facture_').'.pdf';
            $pdf->Output('F', $tmpPath);

            $facture->setFacturePdfFile(new UploadedFile(
                $tmpPath,
                'facture-'.str_replace('/', '-', $facture->getInvoiceNumber()).'.pdf',
                'application/pdf',
                null,
                true
            ));
            $facture->setUpdatedAt(new \DateTimeImmutable());
            $this->em->flush();

            @unlink($tmpPath);
        }

        $customer = $facture->getCustomer();
        if (null === $customer || null === $customer->getEmail()) {
            $this->addFlash('error', 'Client ou email introuvable.');

            return $this->redirectToRoute('app_admin_clients_show', [
                'id' => $customer?->getId() ?? 0,
                'tab' => 'factures',
            ]);
        }

        $invoiceNumber = $facture->getInvoiceNumber();

        $attachments = [];
        $pdfPath = $projectDir.'/public/uploads/factures/'.$facture->getFacturePdf();
        if (file_exists($pdfPath)) {
            $attachments[] = ['path' => $pdfPath, 'name' => 'facture-'.str_replace('/', '-', $invoiceNumber).'.pdf'];
        }

        $verifyUrl = $urlGenerator->generate('app_facture_verify', [
            'id' => $facture->getId(),
            'hmac' => $facture->getHmac(),
        ], UrlGeneratorInterface::ABSOLUTE_URL);

        $html = $twig->render('emails/facture_send.html.twig', [
            'customer' => $customer,
            'facture' => $facture,
            'verifyUrl' => $verifyUrl,
        ]);

        $mailer->sendEmail(
            $customer->getEmail(),
            'Facture '.$invoiceNumber,
            $html,
            null,
            null,
            false,
            $attachments,
        );

        $facture->setState(Facture::STATE_SEND);
        $this->em->flush();

        $this->addFlash('success', 'Facture '.$invoiceNumber.' envoyee a '.$customer->getEmail().'.');

        return $this->redirectToRoute('app_admin_clients_show', [
            'id' => $customer->getId(),
            'tab' => 'factures',
        ]);
    }
}
