<?php

namespace FiloBlu\Flow\Model\Actions\From;

use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\ProductFactory;
use Magento\Store\Model\StoreRepository;
use Magento\Store\Model\WebsiteRepository;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable as ProductTypeConfigurable;

/**
 * Class AbstractWebsite
 * @package FiloBlu\Flow\Model\Actions\From
 */
abstract class AbstractWebsite
{

    /**
     * @var string
     */
    CONST ENTITY_TYPE_CODE = 'catalog_product';

    /**
     * @var Product
     */
    protected $productFactory;

    /**
     * @var array|StoreRepository
     */
    protected $websites = [];

    /**
     * @var WebsiteRepository
     */
    protected $websiteRepository;

    /**
     * @var ProductTypeConfigurable
     */
    protected $productTypeConfigurable;

    /**
     * @var bool
     */
    public $useParent = false;

    /**
     * AbstractWebsite constructor.
     * @param ProductFactory $productFactory
     * @param WebsiteRepository $websiteRepository
     * @param ProductTypeConfigurable $productTypeConfigurable
     */
    public function __construct(
        ProductFactory $productFactory,
        WebsiteRepository $websiteRepository,
        ProductTypeConfigurable $productTypeConfigurable
    )
    {
        $this->productFactory = $productFactory;
        $this->websiteRepository = $websiteRepository;
        $this->productTypeConfigurable = $productTypeConfigurable;
        $this->websites = $this->getWebsites();
    }

    /**
     * @return array
     */
    public function getWebsites()
    {
        $websites = $this->websiteRepository->getList();
        $websiteIdArray = [];
        $websiteCodeArray = [];
        foreach ($websites as $website) {
            $websiteIdArray[$website['website_id']] = $website['website_id'];
            $websiteCodeArray[$website['code']] = $website['website_id'];
        }

        return ['id' => $websiteIdArray, 'code' => $websiteCodeArray];
    }


    /**
     * @param $prod
     * @param $value
     * @param $storeId
     * @return bool
     */
    public function process($prod, $value, $storeId)
    {
        if(!$value) {
            return false;
        }

        $websites = explode(',', str_replace('|', ',', $value));

        if (count($websites) === 0) {
            return false;
        }

        $websiteToProcess = $this->getNormalizedWebsiteArray($websites);

        if (count($websiteToProcess)) {
            $product_id = $this->productFactory->create()->getIdBySku($prod->getSku());
            $product = $this->productFactory->create()->setStoreId(0)->load($product_id);
            $finalWebsiteArray = $this->getFinalWebsiteArray($websiteToProcess, $product->getWebsiteIds());

            // Switch to the parent?
            if ($this->useParent){
                $parentIds = $this->productTypeConfigurable->getParentIdsByChild($product_id);
                if (isset($parentIds[0]) && $parentIds[0] > 0){
                    $product = $this->productFactory->create()->setStoreId(0)->load($parentIds[0]);
                    $finalWebsiteArray = $this->getFinalWebsiteArray($websiteToProcess, $product->getWebsiteIds());
                }
            }

            // Save only if necessary
            if ($product->getWebsiteIds() != $finalWebsiteArray){
                $product->setWebsiteIds($finalWebsiteArray);
                $product->save();
            }
        }
    }

    /**
     * @param $websites
     * @return array
     */
    protected function getNormalizedWebsiteArray($websites)
    {

        $websiteToProcess = [];
        foreach ($websites as $website) {
            if (is_numeric($website)) {
                if (key_exists($website, $this->websites['id'])) {
                    $websiteToProcess[] = $this->websites['id'][$website];
                }
            } else {
                if (key_exists($website, $this->websites['code'])) {
                    $websiteToProcess[] = $this->websites['code'][$website];
                }
            }
        }

        return array_unique($websiteToProcess);
    }

    public function setUseParent($bool = true){
        $this->useParent = $bool;
    }

    /**
     * @param $websites
     * @param $existingWebsites
     * @return mixed
     */
    abstract protected function getFinalWebsiteArray($websites, $existingWebsites);

}
