<?php

namespace App\Controller\Admin;

use App\Entity\AttestationCustom;
use App\Service\DocuSealService;
use App\Service\Pdf\AttestationCustomPdf;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\UploadedFile;
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;

#[Route('/admin/attestations', name: 'app_admin_attestation_custom_')]
#[IsGranted('ROLE_ROOT')]
class AttestationCustomController extends AbstractController
{
    public function __construct(
        private EntityManagerInterface $em,
    ) {
    }

    #[Route('', name: 'index')]
    public function index(): Response
    {
        $attestations = $this->em->getRepository(AttestationCustom::class)->findBy([], ['createdAt' => 'DESC']);

        return $this->render('admin/attestation_custom/index.html.twig', [
            'attestations' => $attestations,
        ]);
    }

    #[Route('/create', name: 'create', methods: ['POST'])]
    public function create(Request $request, KernelInterface $kernel, UrlGeneratorInterface $urlGenerator): Response
    {
        $title = trim($request->request->getString('title'));
        $itemsRaw = $request->request->all('items');

        // Filtrer les items vides
        $items = array_values(array_filter(array_map('trim', $itemsRaw), fn (string $v) => '' !== $v));

        if ('' === $title || [] === $items) {
            $this->addFlash('error', 'Le titre et au moins un element sont requis.');

            return $this->redirectToRoute('app_admin_attestation_custom_index');
        }

        $attestation = new AttestationCustom($title, $items);
        $this->em->persist($attestation);
        $this->em->flush();

        // Generer le PDF
        $this->generatePdfForAttestation($attestation, $kernel, $urlGenerator);

        $this->addFlash('success', 'Attestation '.$attestation->getReference().' creee.');

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

    #[Route('/{id}', name: 'show', requirements: ['id' => '\d+'])]
    public function show(int $id): Response
    {
        $attestation = $this->em->getRepository(AttestationCustom::class)->find($id);
        if (null === $attestation) {
            throw $this->createNotFoundException('Attestation introuvable');
        }

        return $this->render('admin/attestation_custom/show.html.twig', [
            'attestation' => $attestation,
        ]);
    }

    #[Route('/{id}/regenerate-pdf', name: 'regenerate_pdf', requirements: ['id' => '\d+'], methods: ['POST'])]
    public function regeneratePdf(int $id, KernelInterface $kernel, UrlGeneratorInterface $urlGenerator): Response
    {
        $attestation = $this->em->getRepository(AttestationCustom::class)->find($id);
        if (null === $attestation) {
            throw $this->createNotFoundException('Attestation introuvable');
        }

        $this->generatePdfForAttestation($attestation, $kernel, $urlGenerator);
        $this->addFlash('success', 'PDF regenere.');

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

    /**
     * Envoie le PDF a DocuSeal pour signature manuelle et redirige vers DocuSeal.
     */
    #[Route('/{id}/sign', name: 'sign', requirements: ['id' => '\d+'], methods: ['POST'])]
    public function sign(
        int $id,
        DocuSealService $docuSeal,
        #[\Symfony\Component\DependencyInjection\Attribute\Autowire('%kernel.project_dir%')] string $projectDir,
        #[\Symfony\Component\DependencyInjection\Attribute\Autowire(env: 'DOCUSEAL_URL')] string $docuSealUrl,
        \Symfony\Component\Routing\Generator\UrlGeneratorInterface $urlGenerator,
    ): Response {
        $attestation = $this->em->getRepository(AttestationCustom::class)->find($id);
        if (null === $attestation) {
            throw $this->createNotFoundException('Attestation introuvable');
        }

        if (null === $attestation->getPdfUnsigned()) {
            $this->addFlash('error', 'Le PDF doit etre genere avant la signature.');

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

        $pdfPath = $projectDir.'/public/uploads/attestations/'.$attestation->getPdfUnsigned();
        if (!file_exists($pdfPath)) {
            $this->addFlash('error', 'Fichier PDF introuvable.');

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

        /** @var \App\Entity\User $user */
        $user = $this->getUser();

        $redirectUrl = $urlGenerator->generate('app_admin_attestation_custom_show', [
            'id' => $attestation->getId(),
        ], \Symfony\Component\Routing\Generator\UrlGeneratorInterface::ABSOLUTE_URL);

        // @codeCoverageIgnoreStart
        try {
            $pdfBase64 = base64_encode(file_get_contents($pdfPath));

            $result = $docuSeal->getApi()->createSubmissionFromPdf([
                'name' => 'Attestation '.$attestation->getReference().' - '.$attestation->getTitle(),
                'send_email' => false,
                'flatten' => true,
                'documents' => [[
                    'name' => 'attestation-'.$attestation->getReference().'.pdf',
                    'file' => 'data:application/pdf;base64,'.$pdfBase64,
                ]],
                'submitters' => [[
                    'email' => 'client@e-cosplay.fr',
                    'name' => 'Association E-Cosplay',
                    'role' => 'First Party',
                    'send_email' => false,
                    'completed_redirect_url' => $redirectUrl,
                    'metadata' => [
                        'doc_type' => 'attestation_custom',
                        'attestation_custom_id' => $attestation->getId(),
                    ],
                ]],
            ]);

            // DocuSeal retourne soit {submitters: [{id}]} soit [{id}]
            $submitterId = $result['submitters'][0]['id']
                ?? ($result[0]['id'] ?? ($result['id'] ?? null));

            if (null !== $submitterId) {
                $slug = $docuSeal->getSubmitterSlug((int) $submitterId);
                if (null !== $slug) {
                    return $this->redirect(rtrim($docuSealUrl, '/').'/s/'.$slug);
                }
            }

            $this->addFlash('error', 'Erreur DocuSeal : impossible de recuperer le lien de signature. Reponse: '.json_encode($result));
        } catch (\Throwable $e) {
            $this->addFlash('error', 'Erreur DocuSeal : '.$e->getMessage());
        }
        // @codeCoverageIgnoreEnd

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

    #[Route('/{id}/delete', name: 'delete', requirements: ['id' => '\d+'], methods: ['POST'])]
    public function delete(int $id): Response
    {
        $attestation = $this->em->getRepository(AttestationCustom::class)->find($id);
        if (null === $attestation) {
            throw $this->createNotFoundException('Attestation introuvable');
        }

        $this->em->remove($attestation);
        $this->em->flush();

        $this->addFlash('success', 'Attestation supprimee.');

        return $this->redirectToRoute('app_admin_attestation_custom_index');
    }

    private function generatePdfForAttestation(AttestationCustom $attestation, KernelInterface $kernel, UrlGeneratorInterface $urlGenerator): void
    {
        $pdf = new AttestationCustomPdf($kernel, $attestation, $urlGenerator);
        $pdf->generate();

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

        $attestation->setPdfUnsignedFile(new UploadedFile(
            $tmpPath,
            'attestation-'.$attestation->getReference().'.pdf',
            'application/pdf',
            null,
            true,
        ));
        $attestation->setUpdatedAt(new \DateTimeImmutable());
        $this->em->flush();

        @unlink($tmpPath);
    }
}
