<?php

namespace FiloBlu\Flow\Model\Actions\From;

use Exception;
use FiloBlu\Flow\Helper\CategoryHelper;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\Product;

/**
 * Class Removetocategory
 * @package FiloBlu\Flow\Model\Actions\From
 */
class Appendtocategory
{
    /**
     * @var array
     */
    protected $categoryLookup = [];

    /**
     * @var array
     */
    protected $excludedCategories = [];

    /**
     * @var ProductRepositoryInterface
     */
    protected $productRepository;

    /**
     * @var \FiloBlu\Flow\Helper\Product
     */
    protected $productHelper;

    /**
     * @var CategoryHelper
     */
    protected $categoryHelper;

    /**
     * TestAddToCategory constructor.
     * @param ProductRepositoryInterface $productRepository
     * @param CategoryHelper $categoryHelper
     * @param \FiloBlu\Flow\Helper\Product $productHelper
     */
    public function __construct(
        ProductRepositoryInterface $productRepository,
        CategoryHelper $categoryHelper,
        \FiloBlu\Flow\Helper\Product $productHelper
    ) {
        $this->productRepository = $productRepository;
        $this->productHelper = $productHelper;
        $this->categoryHelper = $categoryHelper;
    }

    /**
     * @param string $categoriesString single number (58) single string (parka) path of strings (woman/jacket/parka) path of number (2/5/9) separated by |
     * @param Product $product
     * @param $storeId
     * @throws Exception
     */
    public function process($product, $categoriesString, $storeId)
    {
        $this->categoryLookup = $this->categoryHelper->getCategoryLookup();
        $categoriesString = trim($categoriesString, '|');
        $categories = explode('|', $categoriesString);
        $categoryIds = [];

        foreach ($categories as $categoryGroup) {
            $pieces = explode('/', $categoryGroup);
            foreach ($pieces as $category) {
                if ($category === null) {
                    continue;
                }

                $category = trim($category);

                if (ctype_space($category)) {
                    continue;
                }

                $categoryIds = array_merge($this->lookupCategory($category), $categoryIds);
            }
        }

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

        $existingCategories = $product->getCategoryIds();
        $uniqueCategories = array_unique(array_merge($categoryIds, $existingCategories));
        $categoriesToSet = array_diff($uniqueCategories, $this->excludedCategories);

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

        $categoriesToSet[] = $categoryIds;

        $product->setCategoryIds($categoriesToSet);

        // Save through repository it is weired and produces
        // $this->productRepository->save($product);
        // so we use old save instead

        $product->save();
    }

    /**
     * @param $category
     * @return mixed
     */
    public function lookupCategory($category)
    {
        if (is_numeric($category)) {
            if (isset($this->categoryLookup[$category])) {
                if ($this->productHelper->assignFullTree()) {
                    return $this->categoryLookup[$category];
                }
                return [$category];
            }

            return [];
        }
    }
}
