<?php

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Controller\Site;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Context\GroupContext;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Filesystem\Filesystem;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Utils\Pdf;
use CpCreation\VitiCore\Cart\CartService;
use CpCreation\VitiCore\Cart\Model\Cart;
use CpCreation\VitiCore\Cart\Model\PaymentMethod;
use CpCreation\VitiCore\Cart\Repository\CartRepository;
use CpCreation\VitiCore\Contact\Repository\ContactRepository;
use CpCreation\VitiCore\Product\Model\ProductCategory;
use CpCreation\VitiCore\Product\Repository\ProductCategoryRepository;
use CpCreation\VitiCore\Product\Repository\ProductRepository;
use CpCreation\VitiCore\Shop\Repository\ShopConfigRepository;
use CpCreation\VitiCore\User\Model\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpKernel\Attribute\ValueResolver;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\Translation\TranslatorInterface;

class ShopController extends AbstractController
{
    public function __construct(
        private ProductCategoryRepository $productCategoryRepository,
        private readonly ProductRepository $productRepository,
        private readonly CartService $cartService,
        private readonly CartRepository $cartRepository,
        private readonly ShopConfigRepository $shopConfigRepository,
        private readonly ContactRepository $contactRepository,
        private readonly Filesystem $filesystem,
        private readonly Pdf $pdf,
        private readonly TranslatorInterface $translator,
    ) {
    }

    #[Route(path: [
        'fr' => '/boutique/{slug}',
        'en' => '/en/shop/{slug}',
    ], name: 'shop', defaults: ['slug' => null], methods: ['GET'])]
    public function index(
        #[ValueResolver('translation_resolver')]
        ?ProductCategory $category = null,
    ): Response {
        $categories = $this->productCategoryRepository->findOnlyShop(GroupContext::$groupId);
        if (null === $category && \count($categories) > 0) {
            $category = $categories[0];
        }
        $config = $this->shopConfigRepository->findOne();
        if (null === $config) {
            throw new \RuntimeException('Shop config not found');
        }
        $shopProducts = null !== $category
            ? $this->productRepository->findOnlyShop(GroupContext::$groupId, $category)
            : [];

        return $this->render('shop/index.html.twig', [
            'config' => $config,
            'categories' => $categories,
            'category' => $category,
            'shopProducts' => $shopProducts,
        ]);
    }

    #[Route(path: [
        'fr' => '/boutique/finaliser-ma-commande',
        'en' => '/en/shop/checkout',
    ], name: 'shop_checkout', priority: 100)]
    #[Route(path: [
        'fr' => '/boutique/finaliser-ma-commande/{cartId}',
        'en' => '/en/shop/checkout/{cartId}',
    ], name: 'shop_checkout_cart', requirements: ['cartId' => '[0-9a-fA-F-]{36}'], priority: 100)]
    public function checkout(?string $cartId = null): Response
    {
        $cart = null !== $cartId
            ? $this->cartRepository->findOneCartInProgressById($cartId, false)
            : $this->cartService->getCart();

        if (!$cart) {
            return $this->redirectToRoute('shop');
        }

        return $this->render('shop/checkout.html.twig', [
            'checkout_cart_id' => $cart->getId()->toString(),
        ]);
    }

    #[Route(path: [
        'fr' => '/boutique/commande-confirmee/{cartId}',
        'en' => '/en/shop/order-confirmed/{cartId}',
    ], name: 'shop_checkout_success', requirements: ['cartId' => '[0-9a-fA-F-]{36}'], priority: 100)]
    public function success(string $cartId): Response
    {
        $cart = $this->cartRepository->find($cartId);

        if (!$cart instanceof Cart || !$this->canDisplayOrderDetails($cart)) {
            return $this->redirectToRoute('shop');
        }

        $documentLabel = $cart->getDocumentLabelKey();

        return $this->render('shop/success.html.twig', [
            'cart' => $cart,
            'payment_method_label' => $this->resolvePaymentMethodLabel($cart->getPaymentMethod()),
            'document_label' => $documentLabel,
            'download_document_label' => $cart->getDownloadDocumentLabelKey(),
        ]);
    }

    #[Route(path: [
        'fr' => '/boutique/commande-confirmee/{cartId}/telecharger',
        'en' => '/en/shop/order-confirmed/{cartId}/download',
    ], name: 'shop_purchase_order_download', requirements: ['cartId' => '[0-9a-fA-F-]{36}'], priority: 100)]
    public function purchaseOrderDownload(string $cartId): Response
    {
        $cart = $this->cartRepository->find($cartId);

        if (!$cart instanceof Cart || !$this->canDisplayOrderDetails($cart)) {
            return $this->redirectToRoute('shop');
        }

        $contact = $this->contactRepository->findOne();
        if (null === $contact) {
            throw $this->createNotFoundException('Aucun contact boutique configuré.');
        }

        $locale = $cart->getLocale();
        $filename = $this->pdf->createPdfCartDocument($contact, $cart, $locale);
        $filePath = $this->filesystem->absolutePath('order', $filename);

        return $this->file($filePath, $filename, ResponseHeaderBag::DISPOSITION_ATTACHMENT);
    }

    private function resolvePaymentMethodLabel(?PaymentMethod $paymentMethod): ?string
    {
        if (null === $paymentMethod) {
            return null;
        }

        $configuration = method_exists($paymentMethod, 'getConfiguration')
            ? $paymentMethod->getConfiguration()
            : [];

        $configuredName = $configuration['name'] ?? null;
        if (\is_string($configuredName) && '' !== $configuredName) {
            return $configuredName;
        }

        $method = $paymentMethod->getMethod();

        return match ($method) {
            'check' => $this->translator->trans('checkout_design.payment_check'),
            'bankTransfert', 'banktransfert' => $this->translator->trans('checkout_design.payment_banktransfert'),
            default => $paymentMethod->isPaymentOnline()
                ? $this->translator->trans('checkout_design.payment_card')
                : $method,
        };
    }

    private function canDisplayOrderDetails(Cart $cart): bool
    {
        if ($cart->isCheckoutPayed()) {
            return true;
        }

        $checkout = $cart->getCartCheckout();
        $paymentMethod = $cart->getPaymentMethod();
        $user = $this->getUser();

        return $checkout?->getOrderedAt() instanceof \DateTimeImmutable
            && false === ($paymentMethod?->isPaymentOnline() ?? true)
            && $user instanceof User
            && $cart->getUser() instanceof User
            && $cart->getUser()->getId()->toString() === $user->getId()->toString();
    }

}
