<?php

namespace FiloBlu\Flow\Model\Actions\From;

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

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

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

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

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

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

    /**
     * @var CategoryLinkManagementInterface
     */
    private $categoryLinkManagement;

    /**
     * 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,
        CategoryLinkManagementInterface $categoryLinkManagement
    ) {
        $this->productRepository = $productRepository;
        $this->productHelper = $productHelper;
        $this->categoryHelper = $categoryHelper;
        $this->categoryLinkManagement = $categoryLinkManagement;
    }

    /**
     * @param string|null|int $categoriesString single number (58) single string (parka) path of strings (woman/jacket/parka) path of number (2/5/9) separated by |
     * @param Product|\Magento\Catalog\Api\Data\ProductInterface $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);
            }
            // Try to get the category also by string path
            $cat_id = $this->categoryHelper->getCategoryIdByStringPath($categoryGroup);
            $categoryIds = array_merge($this->lookupCategory($cat_id), $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;
        }

        $this->categoryLinkManagement->assignProductToCategories($product->getSku(), $categoriesToSet);
    }

    /**
     * @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 [];
    }
}
