<?php declare(strict_types=1);

namespace Shop\Application\Catalog\UpdateProductPositions;

use Shop\Application\Catalog\UpdateProduct\PositionDto;
use Propel\Runtime\Collection\Collection;
use Shop\Domain\Product\Contracts\ProductRepositoryInterface;
use Shop\Infrastructure\Models\Position\Position;
use Shop\Infrastructure\Models\ShopPositionSize\ShopPositionSize;
use Shop\Infrastructure\Models\ShopPositionSizeType\ShopPositionSizeType;
use Shop\Infrastructure\Models\ShopPositionSizeType\ShopPositionSizeTypeQuery;
use Shop\Presentation\Config\Main;

class UpdateProductPositionsHandler
{

    private array $cacheSizeNames = [];

    public function __construct(
        private ProductRepositoryInterface $repository, protected Main $mainConfig)
    {
    }

    public function handle(UpdateProductPositionsCommand $command): void
    {

        $product = $command->getProduct();
        $price = null;
        $collection = new Collection();
        /** @var PositionDto $positionDto */
        foreach ($command->getPositionCollection() as $positionDto) {
            $price = $positionDto->getPrice();
            $position = new Position();
            $position->setDesc($positionDto->getDescription());
            $position->setPrice($price);
            $position->setRemain($positionDto->getRemain());
            $position->setPricelistSheetId(1);//@todo сделать настраиваемым
            $this->findSizes($position, $positionDto->getSizes());

            $collection->push($position);
        }
        $product->setPrice($price);
        $product->setPositions($collection);

        $this->repository->save($product);
    }

    private function findSizes(Position $positionModel,array $sizes)
    {

        if(empty($sizes)){
            return;
        }

        //вставляем типы размеров


        foreach ($sizes as $name => $size) {

            $sizeTypeModel = $this->findSizeByName($name);

            if (!$sizeTypeModel) {
                $sizeTypeModel = new ShopPositionSizeType;
                $sizeTypeModel->setname($name);
                $sizeTypeModel->save();
            }

            $isSize = str_contains(mb_strtolower($name),'размер');

            //временно отключено, чтобы грузились размеры как есть
            if(false && $isSize){

                //размеры чистим
                if($isSize && preg_match('~([X|S|L|M]+)\s\(~isUu',$size, $match)){
                    $value = $match[1];
                }
                elseif($isSize && in_array($size,[
                        'XXS','XS','S','M','L','XL','XXL',
                    ])){
                    $value = $size;
                }
                else{
                    $value = mb_strtolower( preg_replace('~[^\/\,\.\d\-]~isu','$1',$size) );
                }

            }
            else{
                $value = $size;
            }

            if(empty($value)){
                continue;
            }

            $sizeModel = new ShopPositionSize();
            $sizeModel
                ->setPosition($positionModel)
                ->setSizeTypeId($sizeTypeModel->getId())
                ->setValue($value);
        }
    }

    private function findSizeByName(string $name):?ShopPositionSizeType
    {

        if (empty($name)) {
            return null;
        }

        if (!empty($this->cacheSizeNames[$name])) {
            return $this->cacheSizeNames[$name];
        }

        $this->cacheSizeNames[$name] = ShopPositionSizeTypeQuery::create()->findOneByname($name);

        return $this->cacheSizeNames[$name];
    }
}