<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Mageants\SimpleConfigurable\Block\Product\View\Type;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Helper\Product;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\ConfigurableProduct\Helper\Data;
use Magento\ConfigurableProduct\Model\ConfigurableAttributeData;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices;
use Magento\Customer\Helper\Session\CurrentCustomer;
use Magento\Customer\Model\Session;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Json\EncoderInterface;
use Magento\Framework\Locale\Format;
use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Framework\Stdlib\ArrayUtils;
use Magento\Store\Model\Store;
use Mageants\SimpleConfigurable\Helper\Data as SimpleConfigurableHelper;
use Magento\Catalog\Model\Product as ProductObj;

/**
 * Confugurable product view type
 *
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 * @api
 * @since 100.0.2
 */
class Configurable extends \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable
{
    /**
     * @var Product
     */
    protected $catalogProduct = null;

    /**
     * Current customer
     *
     * @deprecated 100.2.0 as unused property
     * @var CurrentCustomer
     */
    protected $currentCustomer;

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

    /**
     * @var EncoderInterface
     */
    protected $jsonEncoder;

    /**
     * @var Data $imageHelper
     */
    protected $helper;

    /**
     * @var PriceCurrencyInterface
     */
    protected $priceCurrency;

    /**
     * @var ConfigurableAttributeData
     */
    protected $configurableAttributeData;

    /**
     * @var Format
     */
    private $localeFormat;

    /**
     * @var Session
     */
    private $customerSession;

    /**
     * @var Prices
     */
    private $variationPrices;

    /**
     * @var SimpleConfigurableHelper
     */
    protected $simpleConfigurableHelper;

    /**
     * @var ProductObj
     */
    protected $productObj;

    /**
     * @param Context $context
     * @param ArrayUtils $arrayUtils
     * @param EncoderInterface $jsonEncoder
     * @param Data $helper
     * @param Product $catalogProduct
     * @param CurrentCustomer $currentCustomer
     * @param PriceCurrencyInterface $priceCurrency
     * @param ConfigurableAttributeData $configurableAttributeData
     * @param SimpleConfigurableHelper $simpleConfigurableHelper
     * @param ProductObj $productObj
     * @param array $data
     * @param Format|null $localeFormat
     * @param Session|null $customerSession
     * @param Prices|null $variationPrices
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        Context $context,
        ArrayUtils $arrayUtils,
        EncoderInterface $jsonEncoder,
        Data $helper,
        Product $catalogProduct,
        CurrentCustomer $currentCustomer,
        PriceCurrencyInterface $priceCurrency,
        ConfigurableAttributeData $configurableAttributeData,
        SimpleConfigurableHelper $simpleConfigurableHelper,
        ProductObj $productObj,
        array $data = [],
        ?Format $localeFormat = null,
        ?Session $customerSession = null,
        ?Prices $variationPrices = null
    ) {
        $this->priceCurrency = $priceCurrency;
        $this->helper = $helper;
        $this->jsonEncoder = $jsonEncoder;
        $this->catalogProduct = $catalogProduct;
        $this->currentCustomer = $currentCustomer;
        $this->configurableAttributeData = $configurableAttributeData;
        $this->simpleConfigurableHelper = $simpleConfigurableHelper;
        $this->productObj =  $productObj;
        $this->localeFormat = $localeFormat ?: ObjectManager::getInstance()->get(Format::class);
        $this->customerSession = $customerSession ?: ObjectManager::getInstance()->get(Session::class);
        $this->variationPrices = $variationPrices ?: ObjectManager::getInstance()->get(
            Prices::class
        );

        parent::__construct(
            $context,
            $arrayUtils,
            $jsonEncoder,
            $helper,
            $catalogProduct,
            $currentCustomer,
            $priceCurrency,
            $configurableAttributeData,
            $data,
            $localeFormat,
            $customerSession,
            $variationPrices
        );
    }

    /**
     * Get preselect source
     *
     * @return string
     */
    public function getPreselectSource()
    {
        $preselectVal = $this->simpleConfigurableHelper->getPreselectSource();
        if (!$preselectVal) {
            $preselectVal = 0;
        }
        return $preselectVal;
    }

    /**
     * Get configurable preselect option
     *
     * @return string
     */
    public function getConfigurablePreselectOption()
    {
        $children = $this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct());
        $optionDataSet = $this->getProduct()->getTypeInstance()->getConfigurableOptions($this->getProduct());

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

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

                return $this->jsonEncoder->encode($selectedOpt);
            }
        } elseif ($this->getPreselectSource() == 2) {
            if (!empty($optionDataSet)):
                foreach ($optionDataSet 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 = [];

            foreach ($children as $child) {
                $assoProduct = $this->productObj->load($child->getId());
                // Skip disabled products
                if ($assoProduct->getStatus() != 1) {
                    continue;
                }
                if ($maxPrice < $assoProduct->getPrice()) {
                    $maxPrice = $assoProduct->getPrice();
                    $maxPriceProductId = $assoProduct->getId();
                }

                $productPriceArray[] = $assoProduct->getPrice();
            }

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

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

            $lowPrice = null; // Changed from "" to null for clarity
            $lowPriceProductId = 0;
            $productPriceArray = [];

            foreach ($children as $child) {
                $assoProduct = $this->productObj->load($child->getId());
                // Skip disabled products
                if ($assoProduct->getStatus() != 1) {
                    continue;
                }
                $currentPrice = $assoProduct->getPrice();
                if ($lowPrice === null || $lowPrice > $currentPrice) {
                    $lowPrice = $currentPrice;
                    $lowPriceProductId = $assoProduct->getId();
                }

                $productPriceArray[] = $currentPrice;
            }

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

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