<?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;

use CpCreation\VitiCore\Cart\Repository\CartRepository;
use CpCreation\VitiCore\Product\Model\ProductVariant;
use CpCreation\VitiCore\Product\Repository\ProductPriceCodeRepository;
use CpCreation\VitiCore\Product\Repository\ProductPriceGroupRepository;
use CpCreation\VitiCore\Shop\Model\ShippingCountry;
use CpCreation\VitiCore\Shop\Repository\ShippingCountryRepository;
use CpCreation\VitiCore\Shop\Repository\ShopConfigDisableCountryRepository;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Intl\Countries;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;

class AppExtension extends AbstractExtension
{
    public function __construct(
        private ProductPriceGroupRepository $productPriceGroupRepository,
        private ProductPriceCodeRepository $productPriceCodeRepository,
        private CartRepository $cartRepository,
        private ShippingCountryRepository $shippingCountryRepository,
        private ShopConfigDisableCountryRepository $shopConfigDisableCountryRepository,
        private RequestStack $requestStack,
    ) {
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('countriesShippingByGroup', [$this, 'countriesShippingByGroup']),
            new TwigFunction('countryDisableDescription', [$this, 'countryDisableDescription']),
            new TwigFunction('soldOutWithStock', [$this, 'soldOutWithStock']),
        ];
    }

    public function getFilters(): array
    {
        return [
            new TwigFilter('saleSinceStockAt', [$this, 'saleSinceStockAt']),
            new TwigFilter('price_format', [$this, 'priceFormat']),
        ];
    }

    public function countriesShippingByGroup(string $string, mixed $groupId): string
    {
        $group = $this->productPriceGroupRepository->find($groupId);

        if (null === $group) {
            return $string;
        }

        $countries = $this->shippingCountryRepository->findCountriesAssignedByGroup($group->getId()->toString());

        $countriesWithZone = [];

        foreach ($countries as $country) {
            if (!$country instanceof ShippingCountry) {
                continue;
            }

            $countriesWithZone[] = Countries::getName($country->getCode());
        }

        return str_replace('%countries%', implode(', ', $countriesWithZone), $string);
    }

    public function countryDisableDescription(string $country): ?string
    {
        $disableCountry = $this->shopConfigDisableCountryRepository->findOneBy(['country' => $country]);

        if (null === $disableCountry) {
            return null;
        }

        return $disableCountry->getDescription();
    }

    public function saleSinceStockAt(ProductVariant $variant): int
    {
        $result = $this->cartRepository->stockSaleSinceStockAt($variant);
        $quantitySale = $result[0]['quantitySale'] ?? 0;

        return (int) $quantitySale;
    }

    public function soldOutWithStock(ProductVariant $variant): bool
    {
        $stock = $variant->getStock();

        if (null === $stock || 0 === $stock) {
            return false;
        }

        return $this->saleSinceStockAt($variant) >= $stock;
    }

    public function priceFormat(?int $price, ?string $locale = null): ?string
    {
        if (null === $price) {
            return null;
        }

        $locale ??= $this->requestStack->getCurrentRequest()?->getLocale()
            ?? $this->requestStack->getMainRequest()?->getLocale()
            ?? 'fr';

        $formatter = new \NumberFormatter($locale, \NumberFormatter::DECIMAL);
        $formatter->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, 2);
        $formatter->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, 2);

        return $formatter->format($price / 100);
    }
}
