<?php declare(strict_types=1);

namespace Shop\Application\Catalog\UpdateProduct;

use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use Shop\Application\Catalog\UpdateProductPositions\UpdateProductPositionsCommand;
use Propel\Runtime\Collection\Collection;
use Shop\Domain\Product\Contracts\ProductRepositoryInterface;
use Shop\Infrastructure\Models\Product\Product;
use Shop\Infrastructure\Models\ShopProductGroupsRel\ShopProductGroupsRel;
use Shop\Presentation\Config\MainConfig;
use spaceonfire\CommandBus\CommandBus;

class UpdateProductHandler
{


    public function __construct(
        private ProductRepositoryInterface $repository,
        protected CommandBus               $commandBus,
        protected MainConfig               $mainConfig)
    {
    }

    private static function createFileName(string $image): string
    {
        $fileCache = md5($image);
        $dirs = str_split($fileCache, 2);

        $filePath = $dirs[0] . '/' . $dirs[1] . '/' . $dirs[2];

        $fileInfo = new \SplFileInfo($image);

        $fileName = $fileCache . '.' . $fileInfo->getExtension();

        return $filePath . '/' . $fileName;
    }


    public function handle(UpdateProductCommand $command): void
    {

        //если товар новый и у него нет наличия, пропускаем создание
        $logger = $command->getLogger();

        $cacheDirRoot = BASEPATH . '/public_html/upload/' . trim($this->mainConfig->getProductImagePath(), '/') .'/';

        $product = $command->getProduct();

        $currentImages = $command->getProduct()->getImages();
        $newImages = [];

        foreach ($command->getImages() as $image) {
            if (empty($image)) {
                continue;
            }
            //если это ссылка то формируем путь и готовимся для скачивания
            if(str_contains($imageUrl,'http')){
                $fileNamePath = self::createFileName($image);
            }
            //В противном используем путь к изображению, возможно это путь локальный
            else{
                $fileNamePath = ltrim($image, '/');
            }

            $newImages[$fileNamePath] = $image;
        }

        $deleteImages = array_diff($currentImages, array_keys($newImages));


        $newImages = array_slice($newImages, 0, count(Product::$images));


        //скачка изображений и создание
        $imgMethods = Product::$images;

        foreach ($newImages as $fileNamePath => $imageUrl) {

            
            foreach ($currentImages as $currentImage) {
                if ($currentImage === $fileNamePath) {
                    continue(2);
                }
            }

            $fullFileCache = $cacheDirRoot . $fileNamePath;

            $dir = dirname($fullFileCache);

            if (!is_dir($dir) && !@mkdir($dir, 0777, true) && !is_dir($dir)) {
                throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir));
            }

            //dump($fullFileCache,$imageUrl, strlen(file_get_contents($fullFileCache)));

            if(str_contains($imageUrl,'http')){

                try {

                    $client = new Client([
                        'timeout' => 10.0,
                        'cookie' => false
                    ]);

                    $source = $client->get($imageUrl);
                    $res =  $source->getBody()->getContents();

                    //CurlService::execInFile($imageUrl, $fullFileCache);

                } catch (\Error | RequestException | ConnectException $ex) {
                    $logger->error('upload error: ' . $ex->getMessage());
                    continue;
                }

                file_put_contents($fullFileCache, $res);
            }

            $method = array_shift($imgMethods);
            if (method_exists($product, 'set' . $method)) {
                $product->{'set' . $method}($fileNamePath);
            }


        }


        //delete images
        foreach ($deleteImages as $deleteImage) {
            foreach (Product::$images as $method) {
                if (method_exists($product, 'set' . $method)) {

                    if ($product->{'get' . $method}() === $deleteImage) {
                        $product->{'set' . $method}(null);
                    }
                }
            }
        }

        //сохранение товара
        $positionsCollection = $command->getPositionCollection();

        $emptyRemain  = false;

        if(!count($positionsCollection) || (count($positionsCollection)===1 && $positionsCollection[0]->getRemain()===0)){
            $emptyRemain = true;
        }

        //если нет наличия и одна позиция или вообще нет позиций
        if ($emptyRemain) {
            $positionsCollection = [];
        }

        $product->setdateUpdate(new \DateTime());
        $product->setTitle($command->getName());
        $product->setPrice($command->getPrice());
        $product->setDesc($command->getDescription());
        $product->setArticle($command->getSku());
        $product->setBrandId($command->getBrandId());
        $product->setCategoryId($command->getCategoryId());


        $groupsRelCollection = new Collection();

        foreach ($command->getGroupIds() as $groupId) {
            $groupsRel = new ShopProductGroupsRel();
            $groupsRel->setGroupId($groupId);
            $groupsRelCollection->push($groupsRel);
        }
        $product->getShopProductGroupsRels()->delete();
        $product->setShopProductGroupsRels($groupsRelCollection);

        $this->commandBus->handle(new UpdateProductPositionsCommand($product, $positionsCollection));

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

}