<?php
/**
 * @category Mageants SimpleConfigurable
 * @package Mageants_SimpleConfigurable
 * @copyright Copyright (c) 2017 Mageants
 * @author Mageants Team <info@mageants.com>
 */

namespace Mageants\SimpleConfigurable\Block\Product\Renderer;

use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Helper\Product as CatalogProduct;
use Magento\Catalog\Model\Product;
use Magento\ConfigurableProduct\Helper\Data;
use Magento\ConfigurableProduct\Model\ConfigurableAttributeData;
use Magento\Customer\Helper\Session\CurrentCustomer;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Json\EncoderInterface;
use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Framework\Stdlib\ArrayUtils;
use Magento\Store\Model\ScopeInterface;
use Magento\Swatches\Helper\Data as SwatchData;
use Magento\Swatches\Helper\Media;
use Magento\Swatches\Model\Swatch;
use Magento\Swatches\Model\SwatchAttributesProvider;
use Magento\Catalog\Model\Product\Image\UrlBuilder;
use Magento\Catalog\Model\ProductRepository;
use Magento\Eav\Model\Config as EavConfig;
use Magento\Catalog\Model\ProductFactory;

/**
 * Swatch renderer block
 *
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Configurable extends \Magento\Swatches\Block\Product\Renderer\Configurable
{
    /**
     * Path to template file with Swatch renderer.
     */
    public const SWATCH_RENDERER_TEMPLATE = 'Mageants_SimpleConfigurable::product/view/renderer.phtml';

    /**
     * Path to default template file with standard Configurable renderer.
     */
    
    public const CONFIGURABLE_TEMPLATE = 'Mageants_SimpleConfigurable::product/view/type/options/configurable.phtml';

    /**
     * Action name for ajax request
     */
    public const MEDIA_CALLBACK_ACTION = 'swatches/ajax/media';

    /**
     * @var Product
     */
    public $product;

    /**
     * @var SwatchData
     */
    public $swatchHelper;

    /**
     * @var Media
     */
    public $swatchMediaHelper;

    /**
     * Indicate if product has one or more Swatch attributes
     *
     * @deprecated unused
     * @see SwatchAttributesProvider isProductHasSwatchAttribute().
     *
     * @var boolean
     */
    public $isProductHasSwatchAttribute;

    /**
     * @var SwatchAttributesProvider
     */
    private $swatchAttributesProvider;

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

    /**
     * @var \Magento\Framework\View\LayoutFactory
     */
    private $layoutFactory;

    /**
     * @var \Magento\Catalog\Helper\Output
     */
    private $output;

    /**
     * @var \Magento\Catalog\Model\Product
     */
    private $productObj;
    /**
     * @var UrlBuilder
     */
    private $imageUrlBuilder;

    /**
     * @var ProductRepository
     */
    public $productRepository;

    /**
     * @var EavConfig
     */
    protected $eavConfig;

    /**
     * @param Context $context
     * @param ArrayUtils $arrayUtils
     * @param EncoderInterface $jsonEncoder
     * @param Data $helper
     * @param CatalogProduct $catalogProduct
     * @param CurrentCustomer $currentCustomer
     * @param PriceCurrencyInterface $priceCurrency
     * @param ConfigurableAttributeData $configurableAttributeData
     * @param SwatchData $swatchHelper
     * @param Media $swatchMediaHelper
     * @param \Mageants\SimpleConfigurable\Helper\Data $simpleConfigurableHelper
     * @param SwatchAttributesProvider|null $swatchAttributesProvider
     * @param \Magento\Framework\View\LayoutFactory $layoutFactory
     * @param \Magento\Catalog\Helper\Output $output
     * @param \Magento\Catalog\Model\Product $productObj
     * @param ProductRepository $productRepository
     * @param UrlBuilder|null $imageUrlBuilder
     * @param array $data
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        Context $context,
        ArrayUtils $arrayUtils,
        EncoderInterface $jsonEncoder,
        Data $helper,
        CatalogProduct $catalogProduct,
        CurrentCustomer $currentCustomer,
        PriceCurrencyInterface $priceCurrency,
        ConfigurableAttributeData $configurableAttributeData,
        SwatchData $swatchHelper,
        Media $swatchMediaHelper,
        \Mageants\SimpleConfigurable\Helper\Data $simpleConfigurableHelper,
        \Magento\Framework\View\LayoutFactory $layoutFactory,
        \Magento\Catalog\Helper\Output $output,
        \Magento\Catalog\Model\Product $productObj,
        ProductRepository $productRepository,
        EavConfig $eavConfig,
        ProductFactory $productFactory,
        ?SwatchAttributesProvider $swatchAttributesProvider = null,
        ?UrlBuilder $imageUrlBuilder = null,
        array $data = []
    ) {
        $this->swatchHelper = $swatchHelper;
        $this->swatchMediaHelper = $swatchMediaHelper;
        $this->simpleConfigurableHelper = $simpleConfigurableHelper;
        $this->swatchAttributesProvider = $swatchAttributesProvider
        ?: ObjectManager::getInstance()->get(SwatchAttributesProvider::class);
        $this->layoutFactory = $layoutFactory;
        $this->output = $output;
        $this->scopeConfig = $context->getScopeConfig();
        $this->productObj = $productObj;
        $this->productRepository = $productRepository;
        $this->eavConfig = $eavConfig;
        $this->productFactory = $productFactory;
        $this->imageUrlBuilder = $imageUrlBuilder ?? ObjectManager::getInstance()->get(UrlBuilder::class);
        parent::__construct(
            $context,
            $arrayUtils,
            $jsonEncoder,
            $helper,
            $catalogProduct,
            $currentCustomer,
            $priceCurrency,
            $configurableAttributeData,
            $swatchHelper,
            $swatchMediaHelper,
            $data,
            $swatchAttributesProvider
        );
    }

    /**
     * Get Key for caching block content
     *
     * @return string
     */
    public function getCacheKey()
    {
        return parent::getCacheKey() . '-' . $this->getProduct()->getId();
    }

    /**
     * Get block cache life time
     *
     * @return int
     */
    public function getCacheLifetime()
    {
        return parent::hasCacheLifetime() ? parent::getCacheLifetime() : 3600;
    }

    /**
     * Get Swatch config data
     *
     * @return string
     */
    public function getJsonSwatchConfig()
    {
        $attributesData = $this->getSwatchAttributesData();
        $allOptionIds = $this->getConfigurableOptionsIds($attributesData);
        $swatchesData = $this->swatchHelper->getSwatchesByOptionsId($allOptionIds);

        $config = [];
        foreach ($attributesData as $attributeId => $attributeDataArray) {
            if (isset($attributeDataArray['options'])) {
                $config[$attributeId] = $this->addSwatchDataForAttribute(
                    $attributeDataArray['options'],
                    $swatchesData,
                    $attributeDataArray
                );
            }
            if (isset($attributeDataArray['additional_data'])) {
                $config[$attributeId]['additional_data'] = $attributeDataArray['additional_data'];
            }

        }

        return $this->jsonEncoder->encode($config);
    }

    /**
     * Get number of swatches from config to show on product listing.
     *
     * Other swatches can be shown after click button 'Show more'
     *
     * @return string
     */
    public function getNumberSwatchesPerProduct()
    {
        return $this->simpleConfigurableHelper->getNumberSwatchesPerProduct();
    }

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

    /**
     * Override parent function
     *
     * @return Product
     */
    public function getProduct()
    {
        if (!$this->product) {
            $this->product = parent::getProduct();
        }

        return $this->product;
    }

    /**
     * Get swatch attributes data
     *
     * @return array
     */
    public function getSwatchAttributesData()
    {
        return $this->swatchHelper->getSwatchAttributesAsArray($this->getProduct());
    }

    /**
     * Init is product has swatch attribute
     *
     * @deprecated unused
     * @see isProductHasSwatchAttribute().
     *
     * @codeCoverageIgnore
     * @return void
     */
    public function initIsProductHasSwatchAttribute()
    {
        $this->isProductHasSwatchAttribute = $this->swatchHelper->isProductHasSwatch($this->getProduct());
    }

    /**
     * Check is product has swatch attribute
     *
     * @codeCoverageIgnore
     *
     * @return bool
     */
    public function isProductHasSwatchAttribute()
    {
        $swatchAttributes = $this->swatchAttributesProvider->provide($this->getProduct());
        return count($swatchAttributes) > 0;
    }

    /**
     * Add Swatch Data for attribute
     *
     * @param array $options
     * @param array $swatchesCollectionArray
     * @param array $attributeDataArray
     * @return array
     */
    public function addSwatchDataForAttribute(
        array $options,
        array $swatchesCollectionArray,
        array $attributeDataArray
    ) {
        $result = [];
        foreach ($options as $optionId => $label) {
            if (isset($swatchesCollectionArray[$optionId])) {
                $result[$optionId] = $this->extractNecessarySwatchData($swatchesCollectionArray[$optionId]);
                $result[$optionId] = $this->addAdditionalMediaData($result[$optionId], $optionId, $attributeDataArray);
                $result[$optionId]['label'] = $label;
            }
        }

        return $result;
    }

    /**
     * Add media from variation
     *
     * @param array $swatch
     * @param integer $optionId
     * @param array $attributeDataArray
     * @return array
     */
    public function addAdditionalMediaData(array $swatch, $optionId, array $attributeDataArray)
    {
        if (isset($attributeDataArray['use_product_image_for_swatch'])
            && $attributeDataArray['use_product_image_for_swatch']
        ) {
            $variationMedia = $this->getVariationMedia($attributeDataArray['attribute_code'], $optionId);
            if (!empty($variationMedia)) {
                $swatch['type'] = Swatch::SWATCH_TYPE_VISUAL_IMAGE;
                $swatch = array_merge($swatch, $variationMedia);
            }
        }

        return $swatch;
    }

    /**
     * Retrieve Swatch data for config
     *
     * @param array $swatchDataArray
     * @return array
     */
    public function extractNecessarySwatchData(array $swatchDataArray)
    {
        $result['type'] = $swatchDataArray['type'];

        if ($result['type'] == Swatch::SWATCH_TYPE_VISUAL_IMAGE && !empty($swatchDataArray['value'])) {
            $result['value'] = $this->swatchMediaHelper->getSwatchAttributeImage(
                Swatch::SWATCH_IMAGE_NAME,
                $swatchDataArray['value']
            );
            $result['thumb'] = $this->swatchMediaHelper->getSwatchAttributeImage(
                Swatch::SWATCH_THUMBNAIL_NAME,
                $swatchDataArray['value']
            );
        } else {
            $result['value'] = $swatchDataArray['value'];
        }

        return $result;
    }

    /**
     * Generate Product Media array
     *
     * @param string $attributeCode
     * @param integer $optionId
     * @return array
     */
    public function getVariationMedia($attributeCode, $optionId)
    {
        $variationProduct = $this->swatchHelper->loadFirstVariationWithSwatchImage(
            $this->getProduct(),
            [$attributeCode => $optionId]
        );

        if (!$variationProduct) {
            $variationProduct = $this->swatchHelper->loadFirstVariationWithImage(
                $this->getProduct(),
                [$attributeCode => $optionId]
            );
        }

        $variationMediaArray = [];
        if ($variationProduct) {
            $variationMediaArray = [
                'value' => $this->getSwatchProductImage($variationProduct, Swatch::SWATCH_IMAGE_NAME),
                'thumb' => $this->getSwatchProductImage($variationProduct, Swatch::SWATCH_THUMBNAIL_NAME),
            ];
        }

        return $variationMediaArray;
    }

    /**
     * Get swatch product image
     *
     * @param Product $childProduct
     * @param string $imageType
     * @return string
     */
    public function getSwatchProductImage(Product $childProduct, $imageType)
    {
        if ($this->isProductHasImage($childProduct, Swatch::SWATCH_IMAGE_NAME)) {
            $swatchImageId = $imageType;
            $imageAttributes = ['type' => Swatch::SWATCH_IMAGE_NAME];
        } elseif ($this->isProductHasImage($childProduct, 'image')) {
            $swatchImageId = $imageType == Swatch::SWATCH_IMAGE_NAME ? 'swatch_image_base' : 'swatch_thumb_base';
            $imageAttributes = ['type' => 'image'];
        }

        if (!empty($swatchImageId) && !empty($imageAttributes['type'])) {
            return $this->imageUrlBuilder->getUrl($childProduct->getData($imageAttributes['type']), $swatchImageId);
        }
    }

    /**
     * Check is product has image
     *
     * @param Product $product
     * @param string $imageType
     * @return bool
     */
    public function isProductHasImage(Product $product, $imageType)
    {
        return $product->getData($imageType) !== null && $product->getData($imageType) != SwatchData::EMPTY_IMAGE_VALUE;
    }

    /**
     * Get configurable options ids
     *
     * @param array $attributeData
     * @return array
     */
    public function getConfigurableOptionsIds(array $attributeData)
    {
        $ids = [];
        foreach ($this->getAllowProducts() as $product) {
            /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute $attribute */
            foreach ($this->helper->getAllowAttributes($this->getProduct()) as $attribute) {
                $productAttribute = $attribute->getProductAttribute();
                $productAttributeId = $productAttribute->getId();
                if (isset($attributeData[$productAttributeId])) {
                    $ids[$product->getData($productAttribute->getAttributeCode())] = 1;
                }
            }
        }
        return array_keys($ids);
    }

    /**
     * Produce and return block's html output.
     *
     * @return string
     */
    public function _toHtml()
    {
        $this->setTemplate(
            $this->getRendererTemplate()
        );
        return parent::_toHtml();
    }

    /**
     * Get Renderer Template
     *
     * @codeCoverageIgnore
     *
     * @return string
     */
    public function getRendererTemplate()
    {
        return $this->isProductHasSwatchAttribute() ?
        self::SWATCH_RENDERER_TEMPLATE : self::CONFIGURABLE_TEMPLATE;
    }

    /**
     * Get media callback
     *
     * @return string
     */
    public function getMediaCallback()
    {
        return $this->getUrl(self::MEDIA_CALLBACK_ACTION, ['_secure' => $this->getRequest()->isSecure()]);
    }

    /**
     * Return unique ID(s) for each object in system
     *
     * @return string[]
     */
    public function getIdentities()
    {
        if ($this->product instanceof \Magento\Framework\DataObject\IdentityInterface) {
            return $this->product->getIdentities();
        } else {
            return [];
        }
    }

    /**
     * Get is enable
     *
     * @return string
     */
    public function isEnable()
    {
        return $this->simpleConfigurableHelper->isEnable();
    }

    /**
     * Get output helper
     *
     * @param object $product
     * @param string $attributeHtml
     * @param string $attributeName
     * @return array
     */
    public function outputHelper($product, $attributeHtml, $attributeName)
    {
        return $this->output->productAttribute($product, $attributeHtml, $attributeName);
    }

    /**
     * Get custom Attributes
     *
     * @return string
     */
    public function getcustomAttributes()
    {
        $reloadAttributes = $this->simpleConfigurableHelper->getReloadContent();
        $reloadAttributes = explode(',', $reloadAttributes);
        $children = $this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct());
        $getChildData = [];
        foreach ($children as $child) {
            $getChildData[$child->getId()] = $this->_getProductInfo($child, $reloadAttributes);
        }

        return $this->jsonEncoder->encode($getChildData);
    }

    /**
     * Get product info
     *
     * @param object $product
     * @param array $reloadValues
     * @return array
     */
    public function _getProductInfo($product, $reloadValues)
    {
        $reloadMeta = $this->simpleConfigurableHelper->updateMetaDta();
        if ($reloadMeta) {
            array_push($reloadValues, "meta_title", "meta_keyword", "meta_description");
            $metaSelector = [
                'meta_title' => "meta[name='title']",
                'meta_keyword' => "meta[name='keywords']",
                'meta_description' => "meta[name='description']",
            ];
        }
        $productInfo = [];
        $layout = $this->layoutFactory->create();
        foreach ($reloadValues as $reloadValue) {
            $selector = $this->scopeConfig->getValue(
                'simpleconfigurable_config/simpleconfigurable_reload/' . $reloadValue,
                \Magento\Store\Model\ScopeInterface::SCOPE_STORE
            );
            if (!$selector) {
                if (strpos($reloadValue, 'meta_') !== false) {
                    $selector = $metaSelector[$reloadValue];
                } else {
                    continue;
                }
            }
            if ($reloadValue == 'attributes') {
                $block = $layout->createBlock(
                    \Magento\Catalog\Block\Product\View\Attributes::class,
                    'product.attributes',
                    ['data' => []]
                )->setTemplate('product/view/attributes.phtml');
                $currentProduct = $this->_coreRegistry->registry('product');
                $this->_coreRegistry->unregister('product');
                $this->_coreRegistry->register('product', $product);
                $value = $block->setProduct($product)->toHtml();
                $this->_coreRegistry->unregister('product');
                $this->_coreRegistry->register('product', $currentProduct);
            } else {
                $product = $this->productFactory->create()->load($product->getId());
                $value = $this->output->productAttribute($product, $product->getData($reloadValue), $reloadValue);
            }
            // if ($value) {
                $productInfo[$reloadValue] = [
                    'class' => $selector,
                    'value' => $value,
                ];
            // }
        }
        return $productInfo;
    }

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

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

                $selectedOpt = [];
                $product = $this->productFactory->create()->load($this->getProduct()->getIsDefaultSelected());
                foreach ($optionCode as $k => $optCode) {
                    $selectedOpt[$optCode] = $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->productFactory->create()->load($child);
                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 = [];
                $product = $this->productFactory->create()->load($maxPriceProductId);

                foreach ($optionCode as $k => $optCode) {
                    $selectedOpt[$optCode] = $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 = "";
            $lowPriceProductId = 0;
            $productPriceArray = [];

            foreach ($children as $child) {
                $assoProduct = $this->productFactory->create()->load($child);
                if ($lowPrice == "") {
                    $lowPrice = $assoProduct->getPrice();
                    $lowPriceProductId = $assoProduct->getId();
                } else {
                    if ($lowPrice > $assoProduct->getPrice()) {
                        $lowPrice = $assoProduct->getPrice();
                        $lowPriceProductId = $assoProduct->getId();
                    }
                }

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

            if (!empty($productPriceArray) && count(array_unique($productPriceArray)) === 1) {
                return $this->jsonEncoder->encode($preoptionCode);
            } else {
                $selectedOpt = [];
                $product = $this->productFactory->create()->load($lowPriceProductId);

                foreach ($optionCode as $k => $optCode) {
                    $selectedOpt[$optCode] = $product->getData($optCode);
                }

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

    /**
     * Find matching child product of a configurable product based on attribute values.
     *
     * @param int $parentId
     * @param array/string $attributeValues (e.g. ['br_fa' => 6142, 'br_groesse' => 155, 'br_glas' => 6126])
     * @return \Magento\Catalog\Model\Product|null
     */
    public function getMatchingChildProduct($parentProduct, $attributeValues, $onlyUrlWithId = false)
    {
        if (is_string($attributeValues)) {
            $attributeValues = json_decode($attributeValues);
        }

        $children = $parentProduct->getTypeInstance()->getUsedProducts($parentProduct);

        foreach ($children as $child) {
            $isMatch = true;
            foreach ($attributeValues as $code => $value) {
                if ((int)$child->getData($code) !== (int)$value) {
                    $isMatch = false;
                    break;
                }
            }
            if ($isMatch && $child->getId()) {
                if ($onlyUrlWithId) {
                    $url = $this->getProductFullUrlByProduct($child);
                    return $this->jsonEncoder->encode([$child->getId() => $url]);
                }
                return $child;
            }
        }

        return null;
    }

    /**
     * Get full product URL by appending URL suffix if set
     *
     * @param object $product
     * @return string
     */
    public function getProductFullUrlByProduct($product)
    {
        $suffixValue = $this->scopeConfig->getValue(
            \Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX,
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
        );

        $urlKey = $product->getUrlKey();

        if (!empty($suffixValue)) {
            return $this->getBaseUrl() . $urlKey . $suffixValue;
        }

        return $this->getBaseUrl() . $urlKey;
    }

    /**
     * get Product Id By Url
     *
     * @return void
     */
    public function getCleanUrl()
    {
        $fullUrl = $this->getRequest()->getUri();
        $cleanUrl = strtok($fullUrl, '?');
        return rtrim($cleanUrl, '/');
    }

    public function getScpChildProduct()
    {
        return $this->_coreRegistry->registry('mageants_scp_child_product');
    }

    public function getChildOptionId($childProduct)
    {
        $optionDataSet = $this->getProduct()->getTypeInstance()->getConfigurableOptions($this->getProduct());
    
        $swatchAttributeData = [];
        $attributeData = [];
    
        if (!empty($optionDataSet)) {
            foreach ($optionDataSet as $attId => $attributeOptions) {
                foreach ($attributeOptions as $option) {
                    $attributeCode = $option['attribute_code'];
    
                    // Get value from child product
                    $value = $childProduct->getData($attributeCode);
    
                    if ($value !== null) {
                        $attributeData[$attributeCode] = $value;

                        // Check if attribute has swatch
                        $attribute = $this->eavConfig->getAttribute(Product::ENTITY, $attributeCode);
                        if ($this->swatchHelper->isVisualSwatch($attribute) ||
                            $this->swatchHelper->isTextSwatch($attribute)) {
                            $swatchAttributeData[$attributeCode] = $value;
                        }
                    }
    
                    // Only need the first option to get the attribute code
                    break;
                }
            }
        }
    
        return $this->jsonEncoder->encode(!empty($swatchAttributeData) ? $swatchAttributeData : $attributeData);
    }

    /**
     * Get Product URLs
     *
     * @return string
     */
    public function getProductUrls()
    {
        $productUrls = [];
        $configChild = $this->getProduct()->getTypeInstance()->getUsedProductIds($this->getProduct());
        $suffixValue = $this->scopeConfig->getValue(
            \Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX,
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
        );
        foreach ($configChild as $child) {
            if (!empty($suffixValue)) {
                $productUrls[$child] = $this->getBaseUrl();
                $productUrls[$child] .= $this->productFactory->create()->load($child)->getUrlKey();
                $productUrls[$child] .= $suffixValue;
            } else {
                $productUrls[$child] = $this->getBaseUrl();
                $productUrls[$child] .= $this->productFactory->create()->load($child)->getUrlKey();
            }
        }

        return $this->jsonEncoder->encode($productUrls);
    }

    /**
     * Replace URL
     *
     * @return string
     */
    public function replaceUrl()
    {
        return $this->simpleConfigurableHelper->replaceUrl();
    }

    /**
     * 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->productFactory->create()->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->productFactory->create()->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->productFactory->create()->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->productFactory->create()->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->productFactory->create()->load($lowPriceProductId);
                    foreach ($optionCode as $k => $optCode) {
                        $selectedOpt[$k] = $product->getData($optCode);
                    }
                }

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

    /**
     * Replace URL
     *
     * @return string
     */
    public function replaceBreadCrumbsData()
    {
        return $this->simpleConfigurableHelper->replaceBreadCrumbsData();
    }

    /**
     * Get Product URLs
     *
     * @return string
     */
    public function getBreadCrumbsData()
    {
        $breadCrumbsData = [];
        $configChild = $this->getProduct()->getTypeInstance()->getUsedProductIds($this->getProduct());
        foreach ($configChild as $child) {
            $breadCrumbsData[$child] = $this->productFactory->create()->load($child)->getName();
        }

        return !empty($breadCrumbsData) ? $this->jsonEncoder->encode($breadCrumbsData) : false;
    }

    public function convertAttributeCodeToId($data)
    {
        $newData = [];
        $data = is_string($data) ? json_decode($data) : $data;
        $data = $data ? $data : [];
        foreach ($data as $key => $value) {
            $attribute = $this->eavConfig->getAttribute(Product::ENTITY, $key);
            $newData['id_'.$attribute->getAttributeId()] = $value;
        }
        return $this->jsonEncoder->encode($newData);
    }
}
