<?php

namespace Autogedal\Extend\Controller\Compatibility;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Catalog\Model\CategoryRepository;
use Magento\Catalog\Model\Layer\Category as CategoryLayer;
use Magento\Catalog\Model\Product\Attribute\Repository as AttributeRepository;
use Magento\Framework\App\Action\HttpGetActionInterface;

class FilterOptions extends Action implements HttpGetActionInterface
{
    const CATEGORY_ID = 2161;

    /**
     * @var JsonFactory
     */
    protected $resultJsonFactory;

    /**
     * @var CategoryRepository
     */
    protected $categoryRepository;

    /**
     * @var CategoryLayer
     */
    protected $categoryLayer;

    /**
     * @var AttributeRepository
     */
    protected $attributeRepository;

    /**
     * @param Context $context
     * @param JsonFactory $resultJsonFactory
     * @param CategoryRepository $categoryRepository
     * @param CategoryLayer $categoryLayer
     * @param AttributeRepository $attributeRepository
     */
    public function __construct(
        Context $context,
        JsonFactory $resultJsonFactory,
        CategoryRepository $categoryRepository,
        CategoryLayer $categoryLayer,
        AttributeRepository $attributeRepository
    ) {
        $this->resultJsonFactory = $resultJsonFactory;
        $this->categoryRepository = $categoryRepository;
        $this->categoryLayer = $categoryLayer;
        $this->attributeRepository = $attributeRepository;
        parent::__construct($context);
    }

    /**
     * Execute action
     *
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function execute()
    {
        $result = $this->resultJsonFactory->create();

        try {
            $marca = $this->getRequest()->getParam('marca');
            $model = $this->getRequest()->getParam('model');
            $caroserie = $this->getRequest()->getParam('caroserie');
            $tpPlafon = $this->getRequest()->getParam('tp_plafon');
            $attributeCode = $this->getRequest()->getParam('attribute');

            if (!$attributeCode) {
                return $result->setData([
                    'success' => false,
                    'message' => __('Attribute parameter is required'),
                    'options' => []
                ]);
            }

            $category = $this->categoryRepository->get(self::CATEGORY_ID);
            $this->categoryLayer->setCurrentCategory($category);

            $productCollection = $this->categoryLayer->getProductCollection();

            if ($marca) {
                $productCollection->addFieldToFilter('auto_brand', $marca);
            }
            if ($model) {
                $productCollection->addFieldToFilter('auto_model', $model);
            }
            if ($caroserie) {
                $productCollection->addFieldToFilter('auto_body_bare', $caroserie);
            }
            if ($tpPlafon) {
                $productCollection->addFieldToFilter('auto_roof_type_bare', $tpPlafon);
            }

            $attribute = $this->attributeRepository->get($attributeCode);
            $optionsFacetedData = $productCollection->getFacetedData($attributeCode);

            $options = [];
            if ($optionsFacetedData && is_array($optionsFacetedData)) {
                foreach ($optionsFacetedData as $optionId => $data) {
                    if (isset($data['count']) && $data['count'] > 0) {
                        $label = $attribute->getSource()->getOptionText($optionId);
                        if (!$label) {
                            $label = $optionId;
                        }

                        $options[] = [
                            'value' => $optionId,
                            'label' => $label,
                            'count' => $data['count']
                        ];
                    }
                }
            }

            // Sort options based on attribute type
            $sortedOptions = $this->sortOptions($options, $attributeCode);

            return $result->setData([
                'success' => true,
                'options' => $sortedOptions
            ]);

        } catch (\Exception $e) {
            return $result->setData([
                'success' => false,
                'message' => $e->getMessage(),
                'options' => []
            ]);
        }
    }

    /**
     * Sort options based on attribute type
     *
     * @param array $options
     * @param string $attributeCode
     * @return array
     */
    private function sortOptions($options, $attributeCode)
    {
        switch ($attributeCode) {
            case 'auto_brand':
            case 'auto_model':
            case 'auto_body_bare':
            case 'auto_roof_type_bare':
                return $this->sortAlphabetically($options);
            case 'auto_from_to_bare':
                return $this->sortChronologically($options);
            default:
                return $options;
        }
    }

    /**
     * Sort options alphabetically by label
     *
     * @param array $options
     * @return array
     */
    private function sortAlphabetically($options)
    {
        usort($options, function ($a, $b) {
            return strcasecmp($a['label'], $b['label']);
        });

        return $options;
    }

    /**
     * Sort year options chronologically
     *
     * @param array $options
     * @return array
     */
    private function sortChronologically($options)
    {
        usort($options, function ($a, $b) {
            $labelA = $a['label'];
            $labelB = $b['label'];

            preg_match_all('/(\d{4})/', $labelA, $matchesA);
            preg_match_all('/(\d{4})/', $labelB, $matchesB);

            $yearsA = isset($matchesA[1]) ? $matchesA[1] : [];
            $yearsB = isset($matchesB[1]) ? $matchesB[1] : [];

            if (empty($yearsA) && empty($yearsB)) {
                return 0;
            }
            if (empty($yearsA)) {
                return 1;
            }
            if (empty($yearsB)) {
                return -1;
            }

            $firstYearA = (int)$yearsA[0];
            $firstYearB = (int)$yearsB[0];

            if ($firstYearA != $firstYearB) {
                return $firstYearA - $firstYearB;
            }

            if (count($yearsA) > 1 && count($yearsB) > 1) {
                $secondYearA = (int)$yearsA[1];
                $secondYearB = (int)$yearsB[1];
                return $secondYearA - $secondYearB;
            }

            if (count($yearsA) > 1 && count($yearsB) == 1) {
                return -1;
            }
            if (count($yearsA) == 1 && count($yearsB) > 1) {
                return 1;
            }

            return 0;
        });

        return $options;
    }
}
