<?php

namespace App\Controller\Dashboard;

use App\Entity\Options;
use App\Entity\Product;
use App\Entity\ProductBlocked;
use App\Entity\ProductDoc;
use App\Entity\ProductPhotos;
use App\Entity\ProductPointControll;
use App\Entity\ProductReserve;
use App\Entity\ProductVideo;
use App\Form\OptionsType;
use App\Form\ProductBlockedType;
use App\Form\ProductDocType;
use App\Form\ProductPhotosType;
use App\Form\ProductType;
use App\Form\ProductVideoType;
use App\Logger\AppLogger;
use App\Repository\OptionsRepository;
use App\Repository\ProductRepository;
use App\Service\Stripe\Client;
use Doctrine\ORM\EntityManagerInterface;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Routing\Attribute\Route;
use Presta\SitemapBundle\Messenger\DumpSitemapMessage;
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;

class ProductController extends AbstractController
{
    // --- JSON ENDPOINTS ---

    #[Route(path: '/crm/products/json', name: 'app_crm_product_json', methods: ['GET'])]
    public function productsJson(ProductRepository $productRepository, UploaderHelper $uploaderHelper): Response
    {
        $products = array_map(fn($p) => [
            'id' => $p->getId(),
            'name' => $p->getName(),
            'image' => $uploaderHelper->asset($p, 'imageFile') ?: "/provider/images/favicon.png",
            'price1day' => $p->getPriceDay(),
            'priceSup' => $p->getPriceSup(),
            'caution' => $p->getCaution(),
        ], $productRepository->findAll());

        return $this->json($products);
    }

    #[Route(path: '/crm/options/json', name: 'app_crm_options_json', methods: ['GET'])]
    public function optionsJson(OptionsRepository $optionsRepository, UploaderHelper $uploaderHelper): Response
    {
        $options = array_map(fn($o) => [
            'id' => $o->getId(),
            'name' => $o->getName(),
            'image' => $uploaderHelper->asset($o, 'imageFile') ?: "/provider/images/favicon.png",
            'price' => $o->getPriceHt(),
        ], $optionsRepository->findAll());

        return $this->json($options);
    }

    // --- LISTING ---

    #[Route(path: '/crm/products', name: 'app_crm_product', methods: ['GET'])]
    public function products(OptionsRepository $optionsRepo, ProductRepository $productRepo, AppLogger $logger, PaginatorInterface $paginator, Request $request): Response
    {
        $logger->record('VIEW', 'Consultation du catalogue (Produits & Options)');

        return $this->render('dashboard/products.twig', [
            'products' => $paginator->paginate($productRepo->findBy([], ['ref' => 'asc']), $request->query->getInt('product_page', 1), 10, ['pageParameterName' => 'product_page']),
            'options' => $paginator->paginate($optionsRepo->findBy([], ['id' => 'asc']), $request->query->getInt('option_page', 1), 10, ['pageParameterName' => 'option_page']),
        ]);
    }

    #[Route(path: '/crm/catalogue/upload', name: 'app_crm_catalogue_upload', methods: ['POST'])]
    public function uploadCatalogue(Request $request, AppLogger $logger): Response
    {
        /** @var UploadedFile $file */
        $file = $request->files->get('catalogue_pdf');

        if ($file) {
            // Vérification de sécurité (extension)
            if ($file->guessExtension() !== 'pdf') {
                $this->addFlash('error', 'Le fichier doit être un PDF valide.');
                return $this->redirectToRoute('app_crm_product');
            }

            try {
                // Chemin vers le dossier public/images
                $destination = $this->getParameter('kernel.project_dir') . '/public/images';

                // On force le nom "Catalogue.pdf" pour écraser l'existant
                $file->move($destination, 'Catalogue.pdf');

                $logger->record('UPDATE', 'Mise à jour du fichier Catalogue.pdf');
                $this->addFlash('success', 'Le catalogue PDF a été mis à jour avec succès.');
            } catch (FileException $e) {
                $this->addFlash('error', 'Une erreur est survenue lors de la sauvegarde du fichier.');
            }
        }

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

    // --- PRODUITS (ADD/EDIT/DELETE) ---

    #[Route(path: '/crm/products/add', name: 'app_crm_product_add', methods: ['GET', 'POST'])]
    public function productAdd(EntityManagerInterface $em, AppLogger $logger, Client $stripe, Request $request, MessageBusInterface $bus): Response
    {
        $product = new Product();
        $form = $this->createForm(ProductType::class, $product);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $em->persist($product);
            $em->flush();

            $stripe->createProduct($product);
            $em->flush();
            $logger->record('CREATE', "Nouveau produit : [{$product->getRef()}] {$product->getName()}");
            $bus->dispatch(new DumpSitemapMessage());

            $this->addFlash('success', "Le produit {$product->getName()} a été créé.");
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        return $this->render('dashboard/products/add.twig', ['form' => $form->createView(), 'product' => $product, 'is_edit' => false]);
    }

    #[Route(path: '/crm/products/edit/{id}', name: 'app_crm_product_edit', methods: ['GET', 'POST'])]
    public function productEdit(Product $product, EntityManagerInterface $em, AppLogger $logger, Request $request, Client $stripe, \App\Repository\ProductBlockedRepository $blockedRepo, \App\Repository\ProductReserveRepository $reserveRepo, OptionsRepository $optionsRepo, \App\Repository\TemplatePointControleRepository $templateRepo): Response
    {
        // 0. Toggle Publish
        if ($request->query->get('act') === 'togglePublish') {
            $status = $request->query->get('status') === 'true';
            $product->setIsPublish($status);
            $em->flush();

            $logger->record('UPDATE', "Statut de publication modifié pour {$product->getName()} : " . ($status ? 'En ligne' : 'Hors ligne'));
            $this->addFlash('success', 'Le statut du produit a été mis à jour.');
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 0.1 Ajout d'option
        if ($request->query->get('act') === 'addOption' && $idOption = $request->query->get('idOption')) {
            $option = $optionsRepo->find($idOption);
            if ($option) {
                $product->addOption($option);
                $em->flush();
                $logger->record('UPDATE', "Option ajoutée sur {$product->getName()} : {$option->getName()}");
                $this->addFlash('success', 'Option ajoutée.');
            }
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 0.2 Suppression d'option
        if ($request->query->get('act') === 'deleteOption' && $idOption = $request->query->get('idOption')) {
            $option = $optionsRepo->find($idOption);
            if ($option) {
                $product->removeOption($option);
                $em->flush();
                $logger->record('UPDATE', "Option supprimée sur {$product->getName()} : {$option->getName()}");
                $this->addFlash('success', 'Option supprimée.');
            }
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 0.3 Ajout Point de Contrôle
        if ($request->query->get('act') === 'addPoint' && $request->isMethod('POST')) {
            $name = $request->request->get('name');
            if ($name) {
                $point = new ProductPointControll();
                $point->setName($name);
                $point->setProduct($product);
                $em->persist($point);
                $em->flush();
                $logger->record('UPDATE', "Point de contrôle ajouté sur {$product->getName()} : {$name}");
                $this->addFlash('success', 'Point de contrôle ajouté.');
            }
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 0.4 Suppression Point de Contrôle
        if ($request->query->get('act') === 'deletePoint' && $idPoint = $request->query->get('idPoint')) {
            if ($this->isCsrfTokenValid('delete' . $idPoint, $request->request->get('_token'))) {
                $point = $em->getRepository(ProductPointControll::class)->find($idPoint);
                if ($point && $point->getProduct() === $product) {
                    $em->remove($point);
                    $em->flush();
                    $logger->record('DELETE', "Point de contrôle supprimé sur {$product->getName()}");
                    $this->addFlash('success', 'Point de contrôle supprimé.');
                }
            }
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 1. Suppression de Document
        if ($idDoc = $request->query->get('idDoc')) {
            $doc = $em->getRepository(ProductDoc::class)->find($idDoc);
            if ($doc && $doc->getProduct() === $product) {
                $docName = $doc->getName();
                $em->remove($doc);
                $em->flush();
                $logger->record('DELETE', "Document supprimé sur {$product->getName()} : $docName");
                $this->addFlash('success', 'Document supprimé.');
            }
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 2. Suppression de Vidéo
        if ($idVideo = $request->query->get('idVideo')) {
            $video = $em->getRepository(ProductVideo::class)->find($idVideo);
            if ($video && $video->getProduct() === $product) {
                $em->remove($video);
                $em->flush();
                $logger->record('DELETE', "Vidéo supprimée sur {$product->getName()}");
                $this->addFlash('success', 'Vidéo supprimée.');
            }
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 3. Suppression de Photo
        if ($idPhoto = $request->query->get('idPhoto')) {
            $photo = $em->getRepository(ProductPhotos::class)->find($idPhoto);
            if ($photo && $photo->getProduct() === $product) {
                $em->remove($photo);
                $em->flush();
                $logger->record('DELETE', "Photo supprimée sur {$product->getName()}");
                $this->addFlash('success', 'Photo supprimée.');
            }
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 4. Suppression de Blocage
        if ($request->query->get('act') === 'deleteBlocked' && $idBlocked = $request->query->get('idBlocked')) {
            if ($this->isCsrfTokenValid('delete' . $idBlocked, $request->request->get('_token'))) {
                $blocked = $em->getRepository(ProductBlocked::class)->find($idBlocked);
                if ($blocked && $blocked->getProduct() === $product) {
                    $em->remove($blocked);
                    $em->flush();
                    $logger->record('DELETE', "Période bloquée supprimée sur {$product->getName()}");
                    $this->addFlash('success', 'Période bloquée supprimée.');
                }
            } else {
                $this->addFlash('error', 'Action non autorisée (Token invalide).');
            }
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 5. Formulaire Ajout Photo
        $photo = new ProductPhotos();
        $photo->setProduct($product);
        $formPhotos = $this->createForm(ProductPhotosType::class, $photo);
        $formPhotos->handleRequest($request);

        if ($formPhotos->isSubmitted() && $formPhotos->isValid()) {
            $em->persist($photo);
            $em->flush();
            $logger->record('UPDATE', "Ajout photo sur : {$product->getName()}");
            $this->addFlash('success', 'Photo ajoutée.');
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 5. Formulaire Ajout Vidéo
        $video = new ProductVideo();
        $video->setProduct($product);
        $formVideo = $this->createForm(ProductVideoType::class, $video);
        $formVideo->handleRequest($request);

        if ($formVideo->isSubmitted() && $formVideo->isValid()) {
            $em->persist($video);
            $em->flush();
            $logger->record('UPDATE', "Ajout vidéo sur : {$product->getName()}");
            $this->addFlash('success', 'Vidéo ajoutée.');
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 6. Formulaire Ajout Document
        $doc = new ProductDoc();
        $doc->setProduct($product);
        $formDoc = $this->createForm(ProductDocType::class, $doc);
        $formDoc->handleRequest($request);

        if ($formDoc->isSubmitted() && $formDoc->isValid()) {
            $doc->setUpdatedAt(new \DateTimeImmutable());
            $em->persist($doc);
            $em->flush();
            $logger->record('CREATE', "Document ajouté sur {$product->getName()} : {$doc->getName()}");
            $this->addFlash('success', 'Document ajouté avec succès.');
            return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
        }

        // 7. Formulaire Ajout Blocage
        $blocked = new ProductBlocked();
        $blocked->setProduct($product);
        $formBlocked = $this->createForm(ProductBlockedType::class, $blocked);
        $formBlocked->handleRequest($request);

        if ($formBlocked->isSubmitted() && $formBlocked->isValid()) {
            // Check for overlaps with other BLOCKS
            $overlaps = $blockedRepo->findOverlappingForProduct($product, $blocked->getDateStart(), $blocked->getDateEnd());

            // Check for overlaps with RESERVATIONS
            $dummyReserve = new ProductReserve();
            $dummyReserve->setProduct($product);
            $dummyReserve->setStartAt($blocked->getDateStart());
            $dummyReserve->setEndAt($blocked->getDateEnd());
            $isAvailable = $reserveRepo->checkAvailability($dummyReserve);

            if (count($overlaps) > 0) {
                $this->addFlash('error', 'Impossible de bloquer cette période : elle chevauche une période DÉJÀ BLOQUÉE.');
            } elseif (!$isAvailable) {
                $this->addFlash('error', 'Impossible de bloquer cette période : elle chevauche une RÉSERVATION existante.');
            } else {
                $em->persist($blocked);
                $em->flush();
                $logger->record('CREATE', "Période bloquée ajoutée sur {$product->getName()}");
                $this->addFlash('success', 'Période bloquée ajoutée.');
                return $this->redirectToRoute('app_crm_product_edit', ['id' => $product->getId()]);
            }
        }

        // 8. Formulaire Principal Produit
        $form = $this->createForm(ProductType::class, $product);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            if ($product->getProductId()) {
                $stripe->updateProduct($product);
            }
            $em->flush();
            $logger->record('UPDATE', "Modification produit : {$product->getName()}");
            $this->addFlash('success', 'Produit mis à jour.');
            return $this->redirectToRoute('app_crm_product');
        }

        return $this->render('dashboard/products/add.twig', [
            'form' => $form->createView(),
            'formDoc' => $formDoc->createView(),
            'formPhoto' => $formPhotos->createView(),
            'formVideo' => $formVideo->createView(),
            'formBlocked' => $formBlocked->createView(),
            'product' => $product,
            'is_edit' => true,
            'optionsList' => $optionsRepo->findBy([], ['name' => 'ASC']),
            'templates' => $templateRepo->findAll()
        ]);
    }
    #[Route(path: '/crm/products/delete/{id}', name: 'app_crm_product_delete', methods: ['GET'])]
    public function productDelete(Product $product, EntityManagerInterface $em, Request $request, AppLogger $logger, Client $stripe): Response
    {
        if ($this->isCsrfTokenValid('delete'.$product->getId(), $request->query->get('_token'))) {
            $name = $product->getName();
            $stripe->deleteProduct($product);
            $em->remove($product);
            $em->flush();

            $logger->record('DELETE', "Suppression définitive produit : $name");
            $this->addFlash('success', "Le produit $name a été supprimé.");
        }
        return $this->redirectToRoute('app_crm_product');
    }

    // --- OPTIONS (ADD/EDIT/DELETE) ---

    #[Route(path: '/crm/products/options/add', name: 'app_crm_product_options_add', methods: ['GET', 'POST'])]
    public function optionsAdd(EntityManagerInterface $em, AppLogger $logger, Client $stripe, Request $request): Response {
        $option = new Options();
        $form = $this->createForm(OptionsType::class, $option);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $option->setStripeId("")->setUpdatedAt(new \DateTimeImmutable());
            $em->persist($option);
            $em->flush();

            $stripe->createOptions($option);
            $em->flush();
            $logger->record('CREATE', "Nouvelle option : {$option->getName()}");
            $this->addFlash('success', "L'option {$option->getName()} a été ajoutée.");

            return $this->redirectToRoute('app_crm_product');
        }
        return $this->render('dashboard/options/add.twig', ['form' => $form->createView(), 'options' => $option]);
    }

    #[Route(path: '/crm/products/options/edit/{id}', name: 'app_crm_product_options_edit', methods: ['GET', 'POST'])]
    public function optionsEdit(Options $option, EntityManagerInterface $em, AppLogger $logger, Request $request, Client $stripe): Response {
        $form = $this->createForm(OptionsType::class, $option);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            if ($option->getStripeId()) {
                $stripe->updateOptions($option);
            }
            $em->flush();
            $logger->record('UPDATE', "Modification option : {$option->getName()}");
            $this->addFlash('success', 'Option mise à jour.');
            return $this->redirectToRoute('app_crm_product');
        }
        return $this->render('dashboard/options/add.twig', ['form' => $form->createView(), 'options' => $option, 'is_edit' => true]);
    }

    #[Route(path: '/crm/products/options/delete/{id}', name: 'app_crm_product_option_delete', methods: ['POST'])]
    public function optionDelete(Options $option, EntityManagerInterface $em, Request $request, AppLogger $logger, Client $stripe): Response {
        if ($this->isCsrfTokenValid('delete'.$option->getId(), $request->request->get('_token'))) {
            $name = $option->getName();
            $stripe->deleteOptions($option);
            $em->remove($option);
            $em->flush();

            $logger->record('DELETE', "Suppression option : $name");
            $this->addFlash('success', "L'option $name a été supprimée.");
        }
        return $this->redirectToRoute('app_crm_product');
    }
}
