<?php
declare(strict_types=1);

namespace WriteTextAI\WriteTextAI\Model;

use WriteTextAI\WriteTextAI\Api\RecordDetailsApiInterface;
use Magento\Framework\Webapi\Rest\Response as RestResponse;
use WriteTextAI\WriteTextAI\Model\Config\Source\ProductAttributes;
use WriteTextAI\WriteTextAI\Model\Config\Source\ProductAttributes\Excluded;
use Magento\Customer\Api\GroupRepositoryInterface;
use Magento\Customer\Api\Data\GroupInterface;
use Magento\Catalog\Helper\Image as ImageHelper;
use WriteTextAI\WriteTextAI\Helper\Image as WTAImageHelper;
use Magento\Catalog\Helper\Output as OutputHelper;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\CollectionFactory as AttributeCollectionFactory;
use Magento\Framework\Exception\FileSystemException;
use Magento\Framework\Filter\FilterManager;
use WriteTextAI\WriteTextAI\Helper\Product as ProductHelper;
use WriteTextAI\WriteTextAI\Helper\Fields as FieldHelper;
use WriteTextAI\WriteTextAI\ViewModel\Settings;

/**
 * Class RecordDetailsApi
 * Implementation for record details API endpoint
 */
class RecordDetailsApi implements RecordDetailsApiInterface
{
    /**
     * @var RestResponse
     */
    private $response;

    /**
     * @var WTAImageHelper
     */
    private $wtaImageHelper;

    /**
     * @var ProductHelper
     */
    private $productHelper;

    /**
     * @var FilterManager
     */
    private $filterManager;

    /**
     * @var ImageHelper
     */
    private $imageHelper;

    /**
     * @var OutputHelper
     */
    private $outputHelper;

    /**
     * @var AttributeCollectionFactory
     */
    private $attributeCollectionFactory;

    /**
     * @var GroupRepositoryInterface
     */
    private $groupRepository;

    /**
     * @var ProductAttributes
     */
    private $productAttributes;

    /**
     * @var FieldHelper
     */
    private $fieldHelper;

    /**
     * @var Settings
     */
    private $settings;

    /**
     * @param RestResponse $response
     * @param WTAImageHelper $wtaImageHelper
     * @param ProductHelper $productHelper
     * @param FilterManager $filterManager
     * @param ImageHelper $imageHelper
     * @param OutputHelper $outputHelper
     * @param AttributeCollectionFactory $attributeCollectionFactory
     * @param GroupRepositoryInterface $groupRepository
     * @param ProductAttributes $productAttributes
     * @param FieldHelper $fieldHelper
     * @param Settings $settings
     */
    public function __construct(
        RestResponse $response,
        WTAImageHelper $wtaImageHelper,
        ProductHelper $productHelper,
        FilterManager $filterManager,
        ImageHelper $imageHelper,
        OutputHelper $outputHelper,
        AttributeCollectionFactory $attributeCollectionFactory,
        GroupRepositoryInterface $groupRepository,
        ProductAttributes $productAttributes,
        FieldHelper $fieldHelper,
        Settings $settings
    ) {
        $this->response = $response;
        $this->wtaImageHelper = $wtaImageHelper;
        $this->productHelper = $productHelper;
        $this->filterManager = $filterManager;
        $this->imageHelper = $imageHelper;
        $this->outputHelper = $outputHelper;
        $this->attributeCollectionFactory = $attributeCollectionFactory;
        $this->groupRepository = $groupRepository;
        $this->productAttributes = $productAttributes;
        $this->fieldHelper = $fieldHelper;
        $this->settings = $settings;
    }

    /**
     * Get record details
     *
     * @param string $storeId
     * @param string $type
     * @param string $recordId
     * @param mixed $parameters
     * @return void
     */
    public function getRecordDetails($storeId, $type, $recordId, $parameters)
    {
        $attributesData = [];
        $rules = $this->settings->getSettings('rules');

        try {
            if ($type === 'Product') {
                $attributesData = $this->getProductDetails($storeId, $type, $recordId, $parameters, $rules);
            }
        } catch (\Exception $e) {
            $attributesData = [];
        }

        $responseData = [
            'attributes' => $attributesData
        ];

        $this->response->setBody(json_encode($responseData))->sendResponse();
    }

    /**
     * Product get details
     *
     * @param string $storeId
     * @param string $type
     * @param string $recordId
     * @param mixed $parameters
     * @param array $rules
     * @return array
     */
    public function getProductDetails($storeId, $type, $recordId, $parameters, $rules)
    {
        $maxAttributes = $rules['maxAttributes'] ?? '';
        $maxAttributeValueLength = $rules['maxAttributeValueLength'] ?? '';
        $product = $this->productHelper->getProduct($recordId, $storeId);
        if (empty($parameters['attributes'])) {
            return [];
        }
        
        $productAttributes = $this->getProductAttributes($product, $parameters['attributes']);
        $attributesData = [];
        foreach ($productAttributes as $attribute) {
            try {
                if (strtolower($attribute['attribute'])
                    === ProductAttributes::PRODUCT_RESEARCH_DATA_ATTRIBUTE_CODE
                ) {
                    continue;
                }

                /*if ($maxAttributes <= count($attributesData)) {
                    break;
                }*/
                
                if (strtolower($attribute['attribute']) !== 'thumbnail') {
                    $stringAttribute = (string)$attribute['details'];
                    if (!empty(trim($stringAttribute))) {
                        $attributeValue = str_replace("<br />", "\n", $stringAttribute);
                        $attributeValue = $this->filterManager->stripTags($attributeValue);
                        //@codingStandardsIgnoreStart
                        $attributeValue = htmlspecialchars(
                            $attributeValue,
                            ENT_QUOTES | ENT_SUBSTITUTE,
                            'UTF-8'
                        );
                        //@codingStandardsIgnoreEnd
                        $attributesData[] = [
                            "name" => $attribute['attribute'],
                            "value" => $attributeValue,
                            "isCustom" => "false"
                        ];
                    }
                }
            } catch (\Exception $e) {
                continue;
            }
        }

        return $attributesData;
    }

    /**
     * Get product attributes
     *
     * @param \Magento\Catalog\Model\Product $product
     * @param array $selectedAttributes
     * @return array
     */
    protected function getProductAttributes($product, $selectedAttributes = [])
    {
        $attributes = $this->productAttributes->toOptionArray();

        $attributeSetId = $product->getAttributeSetId();
        $attributeSet = $this->attributeCollectionFactory->create()
            ->addFieldToSelect('attribute_id')
            ->setAttributeSetFilter($attributeSetId)
            ->load()
            ->getItems();
        $attributeIds = array_map(fn($attribute) => $attribute->getAttributeId(), $attributeSet);
        
        $data = [];
        foreach ($attributes as &$attribute) {
            if ($attribute['value'] === 'wtai_product_research_data'
                && in_array($attribute['value'], $selectedAttributes)
            ) {
                $selectedAttribute = [
                    'attribute' => $attribute['value'],
                    'value' => $attribute['value'],
                    'details' => ''
                ];
                $data[] = $selectedAttribute;
                continue;
            }
            
            if (!in_array($attribute['value'], $selectedAttributes) ||
                !in_array($attribute['id'], $attributeIds)
            ) {
                continue;
            }
            
            $selectedAttribute = [
                'attribute' => $attribute['label'],
                'value' => $attribute['value']
            ];

            if (in_array($attribute['value'], Excluded::ARRAY_ATTRIBUTES)) {
                try {
                    switch ($attribute['value']) {
                        case 'tier_price':
                            $selectedAttribute['details'] = '';
                            foreach ($product->getTierPrices() as $tierPrice) {
                                $qty = $tierPrice['qty'] ?? '';
                                $price = $tierPrice['value'] ?? '';
                                $groupName = $tierPrice['customer_group_id'] !== GroupInterface::CUST_GROUP_ALL ?
                                    $this->groupRepository->getById($tierPrice['customer_group_id']) :
                                    __('ALL GROUPS');
                                
                                // Check if it's an object and get the group name
                                if (is_object($groupName) && method_exists($groupName, 'getCode')) {
                                    $groupName = $groupName->getCode();
                                }

                                $selectedAttribute['details'] .= sprintf("%s: ", __('Customer Group'))
                                    . $groupName . "<br />"
                                    . sprintf("%s: ", __('Quantity')) . $qty . "<br />"
                                    . sprintf("%s: ", __('Price')) . $price . "<br /><br />";
                            }
                            
                            break;

                        case 'quantity_and_stock_status':
                            $quantityAndStockStatus = $product->getQuantityAndStockStatus();
                            $qty = $quantityAndStockStatus['qty'] ?? '';
                            $stockStatus = $quantityAndStockStatus['is_in_stock'] ?? '';
                            $stockStatusLabel = $stockStatus ? __('In Stock') : __('Out of Stock');
                            $selectedAttribute['details'] = '';

                            if ($qty || $stockStatus) {
                                $selectedAttribute['details'] = sprintf("%s: ", __('Quantity')) . $qty . "<br />"
                                    . sprintf("%s: ", __('Stock status')) . $stockStatusLabel;
                            }
                            
                            break;
                    }
                } catch (\Exception $e) {
                    continue;
                }

                $data[] = $selectedAttribute;
            } else {
                $selectedAttribute['details'] = '';

                if (strtolower($attribute['value']) === 'thumbnail') {
                    $imageHelper = $this->imageHelper->init($product, 'product_listing_thumbnail_preview');
                    try {
                        $thumbnail = $imageHelper->setImageFile($product->getData('thumbnail'));
                        $thumbnail->getUrl();
                        $thumbnail->getOriginalWidth();
                    } catch (\InvalidArgumentException | FileSystemException $e) {
                        continue;
                    }
                    
                    $selectedAttribute['details'] = $imageHelper->getUrl();
                    $imageHelper = $this->imageHelper->init($product, 'product_listing_thumbnail');
                    $selectedAttribute['thumbnail'] = $imageHelper->getUrl();
                    $value = $this->wtaImageHelper->getImageValue($product);
                    $selectedAttribute['value'] = $value;

                    if ($value) {
                        $data[] = $selectedAttribute;
                    }
                } else {
                    try {
                        $details = $product->getResource()
                            ->getAttribute($attribute['value'])
                            ->getFrontend()
                            ->getValue($product);

                        if ($details) {
                            $selectedAttribute['details'] = $this->outputHelper->productAttribute(
                                $product,
                                $details,
                                $attribute['value']
                            );
                        }

                        $data[] = $selectedAttribute;
                    } catch (\Exception $e) {
                        /** Skip attributes with error */
                        continue;
                    }
                }
            }
        }
        return $data;
    }
}
