<?php
/**
 * @category Mageants HyvaSimpleConfigurable
 * @package Mageants_HyvaSimpleConfigurable
 * @copyright Copyright (c) 2023 Mageants
 * @author Mageants Team <info@mageants.com>
 */

declare(strict_types=1);

namespace Mageants\HyvaSimpleConfigurable\Plugin\Block\Product\View\Type;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\Json\Encoder;
use Magento\Framework\Json\Decoder;
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
use Magento\ConfigurableProduct\Block\Product\View\Type\Configurable as ConfigurableProductType;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Catalog\Helper\Image;

class Configurable
{
    /**
     * @var string
     */
    protected const IS_ENABLE = 'simpleconfigurable_config/simpleconfigurable_settings/enable';

    /**
     * @var string
     */
    protected const GET_PRESELECT_SOURCE = 'simpleconfigurable_config/simpleconfigurable_settings/preselect';

    /**
     * @var string
     */
    protected const CHANGE_URL = 'simpleconfigurable_config/simpleconfigurable_settings/updatepageurl';

    /**
     * @var string
     */
    protected const SHOW_QTY = 'simpleconfigurable_config/simpleconfigurable_settings/showqty';

    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $scopeConfig;

    /**
     * @var object
     */
    protected $product;

     /**
      * @var \Magento\Catalog\Api\ProductRepositoryInterface
      */
    protected $productRepository;

    /**
     * @var \Magento\Framework\Json\Encoder
     */
    protected $jsonEncoder;

    /**
     * @var \Magento\Framework\Json\Decoder
     */
    protected $jsonDecoder;

    /**
     * @var string
     */
    protected $childProductImages;

    /**
     * @var \Magento\Catalog\Helper\Image
     */
    protected $imageHelper;

    /**
     * @var Magento\Store\Model\StoreManagerInterface
     */
    public $storeManager;

    /**
     * @var Magento\Catalog\Api\ProductAttributeRepositoryInterface
     */
    public $productAttributeRepository;


    /**
     * Constructor Dependencies
     *
     * @param ScopeConfigInterface                $scopeConfig
     * @param ProductRepositoryInterface          $productRepository
     * @param Encoder                             $jsonEncoder
     * @param Decoder                             $jsonDecoder
     * @param ProductAttributeRepositoryInterface $productAttributeRepository
     * @param StoreManagerInterface               $storeManager
     * @param Image                               $imageHelper
     */
    public function __construct(
        ScopeConfigInterface $scopeConfig,
        ProductRepositoryInterface $productRepository,
        Encoder $jsonEncoder,
        Decoder $jsonDecoder,
        ProductAttributeRepositoryInterface $productAttributeRepository,
        StoreManagerInterface $storeManager,
        Image $imageHelper
    ) {
        $this->scopeConfig = $scopeConfig;
        $this->jsonEncoder = $jsonEncoder;
        $this->jsonDecoder = $jsonDecoder;
        $this->productAttributeRepository = $productAttributeRepository;
        $this->storeManager = $storeManager;
        $this->productRepository = $productRepository;
        $this->imageHelper = $imageHelper;
    }

    /**
     * After Get Json Config
     *
     * @param  ConfigurableProductType $subject
     * @param  string                  $result
     * @return string
     */
    public function afterGetJsonConfig(
        ConfigurableProductType $subject,
        $result
    ) {

        if ($this->isExtensionEnable()) {
            $this->setProduct($subject->getProduct());

            $preselectDataEncode = $this->getPreselectOptionId();

            if (is_string($preselectDataEncode)) {
                $preselectDataDecode = json_decode($preselectDataEncode, true);

                if (count($preselectDataDecode) > 0) {
                    $preselectData = [];
                    foreach ($preselectDataDecode as $key => $value) {

                        $attribute = $this->productAttributeRepository->get($key);
                        $attributeId = $attribute->getAttributeId();
                        $preselectData[$attributeId] = $value;
                    }
                }
                $result = $this->jsonDecoder->decode($result);
                $result['defaultValues'] = $preselectData;
                $result['productUrls'] = $subject->getProductUrls() !== null ?
                 $this->jsonDecoder->decode($subject->getProductUrls()) : '';
                $result['replaceUrl'] = $this->isChangeUrl();
                $result['showQty'] = $this->showQty();
                $result['childOptions'] = $this->getTrueChildProductOptions($subject->getProduct());
                return $this->jsonEncoder->encode($result);

            } else {
                $result = $this->jsonDecoder->decode($result);
                $result['productUrls'] = $subject->getProductUrls() !== null ?
                 $this->jsonDecoder->decode($subject->getProductUrls()) : '';
                $result['replaceUrl'] = $this->isChangeUrl();
                $result['showQty'] = $this->showQty();
                $result['childOptions'] = $this->getTrueChildProductOptions($subject->getProduct());
                return $this->jsonEncoder->encode($result);
            }
        
        } else {

            return $result;
        }
    }
    
    public function getTrueChildProductOptions($product)
    {
        $data = $this->getProduct()->getTypeInstance()->getConfigurableOptions($product);
        $options = [];

        foreach ($data as $key => $attr) {

            foreach ($attr as $val) {

                $chaildId = $this->productRepository->get($val['sku'])->getId();
                $options[$chaildId][$key] = $val['value_index'];
            }
        }

        return $options;
    }

    /**
     * Get Preselect Option Id
     *
     * @return string
     */
    public function getPreselectOptionId()
    {
        $_children = $this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct());
        $optionDatas = $this->getProduct()->getTypeInstance()->getConfigurableOptions($this->getProduct());

        $optionCode = [];
        $preoptionCode = [];
        $childProductImages = [];

        foreach ($_children as $child) {
            $url = $this->imageHelper->init($child, 'product_base_image')->getUrl();
            $childProductImages[$child->getId()] = $url;
        }

        $this->setChildProductImages($childProductImages);
        if ($this->getPreselectSource()==0) {
            if (count($optionDatas)>0):
                foreach ($optionDatas as $opt => $optionData):
                    foreach ($optionData as $optionVal):
                        $optionCode[$opt] = $optionVal['attribute_code'];
                        $preoptionCode[$optionVal['attribute_code']] = $optionVal['value_index'];
                        break;
                    endforeach;
                endforeach;
            endif;

            return $this->jsonEncoder->encode($preoptionCode);
        } elseif ($this->getPreselectSource()==1) {
            if (!$this->getProduct()->getIsDefaultSelected()) {
                return;
            } else {
                foreach ($optionDatas as $opt => $optionData):
                    foreach ($optionData as $optionVal):
                        $optionCode[$opt] = $optionVal['attribute_code'];
                        break;
                    endforeach;
                endforeach;

                $selectedOpt = [];
                   $product = $this->productRepository->getById($this->getProduct()->getIsDefaultSelected());
                foreach ($optionCode as $k => $optCode) {
                    $selectedOpt[$optCode] = $product->getData($optCode);
                }

                return $this->jsonEncoder->encode($selectedOpt);
            }
        } elseif ($this->getPreselectSource()==2) {
            if (count($optionDatas)>0):
                foreach ($optionDatas as $opt => $optionData):
                    foreach ($optionData as $optionVal):
                        $optionCode[$opt] = $optionVal['attribute_code'];
                        $preoptionCode[$optionVal['attribute_code']] = $optionVal['value_index'];
                        break;
                    endforeach;
                endforeach;
            endif;

            $maxprice = 0;
            $maxpriceproductid = 0;
            $productpricearray = [];
            $productImages = [];

            foreach ($_children as $child) {
                if ($maxprice < $child->getPrice()) {
                    $maxprice = $child->getPrice();
                    $maxpriceproductid = $child->getId();
                }
                $productpricearray[] = $child->getPrice();
            }

            if (!empty($productpricearray) && count(array_unique($productpricearray)) === 1) {

                return $this->jsonEncoder->encode($preoptionCode);
            } else {
                $selectedOpt = [];
                $product = $this->productRepository->getById($maxpriceproductid);
                foreach ($optionCode as $k => $optCode) {
                    $selectedOpt[$optCode] = $product->getData($optCode);
                }

                return $this->jsonEncoder->encode($selectedOpt);
            }
        } elseif ($this->getPreselectSource()==3) {
            if (count($optionDatas)>0):
                foreach ($optionDatas as $opt => $optionData):
                    foreach ($optionData as $optionVal):
                        $optionCode[$opt] = $optionVal['attribute_code'];
                        $preoptionCode[$optionVal['attribute_code']] = $optionVal['value_index'];
                        break;
                    endforeach;
                endforeach;
            endif;

            $lowprice = 0;
            $lowpriceproductid = 0;
            $productpricearray = [];

            foreach ($_children as $child) {
                if ($lowprice==0) {
                    $lowprice = $child->getPrice();
                    $lowpriceproductid = $child->getId();
                } else {
                    if ($lowprice > $child->getPrice()) {
                        $lowprice = $child->getPrice();
                        $lowpriceproductid = $child->getId();
                    }
                }
                $productpricearray[] = $child->getPrice();
            }

            if (!empty($productpricearray) && count(array_unique($productpricearray)) === 1) {
                
                return $this->jsonEncoder->encode($preoptionCode);
            } else {
                $selectedOpt = [];
                 $product = $this->productRepository->getById($lowpriceproductid);
                foreach ($optionCode as $k => $optCode) {
                    $selectedOpt[$optCode] = $product->getData($optCode);
                }

                return $this->jsonEncoder->encode($selectedOpt);
            }
        } else {
            return;
        }
    }

    /**
     * Set Child Product Images
     *
     * @param array $images
     */
    public function setChildProductImages($images)
    {
        $this->childProductImages = $images;
    }

    /**
     * Get Child Product Images
     *
     * @return array
     */
    public function getChildProductImages()
    {
        return $this->childProductImages;
    }

    /**
     * Get Preselect Source
     *
     * @return boolean
     */
    public function getPreselectSource()
    {
        return (int)$this->scopeConfig->getValue(
            self::GET_PRESELECT_SOURCE,
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
            $this->storeManager->getStore()->getId()
        );
    }

    /**
     * Is Enable
     *
     * @return boolean
     */
    public function isExtensionEnable()
    {
        return (int)$this->scopeConfig->getValue(
            self::IS_ENABLE,
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
            $this->storeManager->getStore()->getId()
        );
    }

    /**
     * Is Change Url
     *
     * @return boolean
     */
    public function isChangeUrl()
    {
        return (int)$this->scopeConfig->getValue(
            self::CHANGE_URL,
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
            $this->storeManager->getStore()->getId()
        );
    }

    /**
     * Show Qty
     *
     * @return boolean
     */
    public function showQty()
    {
        return (int)$this->scopeConfig->getValue(
            self::SHOW_QTY,
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
            $this->storeManager->getStore()->getId()
        );
    }

    /**
     * Get Product
     *
     * @return object
     */
    public function getProduct()
    {
        return $this->product;
    }

    /**
     * Set Product
     *
     * @param object $product
     */
    public function setProduct($product)
    {
        $this->product = $product;
    }
}
