<?php

declare(strict_types=1);

/*
 * 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\Twig\Components\Shop;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Context\GroupContext;
use CpCreation\VitiCore\Product\Model\Product;
use CpCreation\VitiCore\Product\Model\ProductCategory;
use CpCreation\VitiCore\Product\Model\Translation\ProductCategoryTranslation;
use CpCreation\VitiCore\Product\Model\Translation\ProductTranslation;
use CpCreation\VitiCore\Product\Repository\ProductRepository;
use CpCreation\VitiCore\Shop\Model\ShopConfig;
use CpCreation\VitiCore\Shop\Repository\ShopConfigRepository;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

#[AsTwigComponent('shop:ProductNavigation', template: '@components/shop/ProductNavigation.html.twig')]
final class ProductNavigation
{
    public Product $product;

    /**
     * @var Product[]|null
     */
    private ?array $products = null;

    public function __construct(
        private readonly ProductRepository $productRepository,
        private readonly ShopConfigRepository $shopConfigRepository,
    ) {}

    public function isShowCategoryMenu(): bool
    {
        $config = $this->shopConfigRepository->findOne();

        return !$config instanceof ShopConfig || $config->isShowCategoryMenuFront();
    }

    /**
     * @return Product[]
     */
    public function getProducts(): array
    {
        if (null !== $this->products) {
            return $this->products;
        }

        return $this->products = array_values(array_filter(
            $this->productRepository->findOnlyShop(GroupContext::$groupId),
            static function (Product $product): bool {
                $category = $product->getCategory();
                $productTranslation = $product->translate();
                $categoryTranslation = $category?->translate();

                return $category instanceof ProductCategory
                    && $productTranslation instanceof ProductTranslation
                    && null !== $productTranslation->getSlug()
                    && $categoryTranslation instanceof ProductCategoryTranslation
                    && null !== $categoryTranslation->getSlug();
            },
        ));
    }

    public function getCurrentIndex(): int
    {
        return $this->findCurrentIndex() ?? 0;
    }

    public function getPreviousProduct(): ?Product
    {
        $index = $this->findCurrentIndex();

        return null !== $index && $index > 0 ? $this->getProducts()[$index - 1] : null;
    }

    public function getNextProduct(): ?Product
    {
        $index = $this->findCurrentIndex();
        $products = $this->getProducts();

        return null !== $index && $index + 1 < \count($products) ? $products[$index + 1] : null;
    }

    private function findCurrentIndex(): ?int
    {
        foreach ($this->getProducts() as $index => $product) {
            if ($product->getId()->equals($this->product->getId())) {
                return $index;
            }
        }

        return null;
    }
}
