<?php
/**
 * @author 1902 Software
 * @copyright Copyright © 2023 1902 Software (https://1902software.com/magento/)
 * @package WriteTextAI_WriteTextAI
 */

namespace WriteTextAI\WriteTextAI\Helper\Categories;

use Magento\Catalog\Api\CategoryRepositoryInterface;
use Magento\Catalog\Helper\Image;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;
use Magento\Framework\HTTP\Client\Curl;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use WriteTextAI\WriteTextAI\Helper\Image as WtaImageHelper;

class RepresentativeProducts extends AbstractHelper
{
    /**
     * @var ProductCollectionFactory
     */
    protected $productCollectionFactory;

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

    /**
     * @var StoreManagerInterface
     */
    protected $storeManager;

    /**
     * @var Image
     */
    protected $imageHelper;

    /**
     * @var Curl
     */
    private $curl;

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

    /**
     * Constructor
     *
     * @param Context $context
     * @param ProductCollectionFactory $productCollectionFactory
     * @param CategoryRepositoryInterface $categoryRepository
     * @param StoreManagerInterface $storeManager
     * @param Image $imageHelper
     * @param Curl $curl
     * @param WtaImageHelper $wtaImageHelper
     */
    public function __construct(
        Context $context,
        ProductCollectionFactory $productCollectionFactory,
        CategoryRepositoryInterface $categoryRepository,
        StoreManagerInterface $storeManager,
        Image $imageHelper,
        Curl $curl,
        WtaImageHelper $wtaImageHelper
    ) {
        $this->productCollectionFactory = $productCollectionFactory;
        $this->categoryRepository = $categoryRepository;
        $this->storeManager = $storeManager;
        $this->imageHelper = $imageHelper;
        $this->curl = $curl;
        $this->wtaImageHelper = $wtaImageHelper;
        parent::__construct($context);
    }

    /**
     * Get product attributes selected
     *
     * @param \WriteTextAI\WriteTextAI\Model\AiCategory $aiCategory
     * @return array
     */
    public function getRepresentativeProductsSelected($aiCategory)
    {
        $result = [];

        if ($aiCategory->getRepresentativeProductsSelected()) {
            $result = json_decode($aiCategory->getRepresentativeProductsSelected());
        }

        return $result;
    }
    
    /**
     * Get representative products selected record
     *
     * @param \WriteTextAI\WriteTextAI\Model\AiCategory $aiCategory
     * @return array
     */
    public function getRepresentativeProductsSelectedRecord($aiCategory)
    {
        $response = [];

        $storeId = (int) ($aiCategory->getStoreId() ?: $this->storeManager->getStore()->getId());

        if (!empty($aiCategory->getRepresentativeProductsSelected())) {
            $result = json_decode($aiCategory->getRepresentativeProductsSelected());
            foreach ($result as $key => $value) {
                $record = [
                    'id' => $value->value ?? null,
                    'name' => $value->label ?? null,
                    'description' => $value->description ?? null,
                    'image' => $value->image ?? null,
                    'imageUrl' => null
                ];

                $record = $this->enrichRepresentativeProductRecord($record, $storeId);
                $response[] = $record;
            }
        } else {
            $response = $this->getRandomRepresentativeProducts($aiCategory);
        }

        return $response;
    }

    /**
     * Enrich representative product record with resolved image and dimensions
     *
     * @param array $record
     * @param int $storeId
     * @return array
     */
    private function enrichRepresentativeProductRecord(array $record, int $storeId): array
    {
        $record = $this->resolveRepresentativeProductImageData($record, $storeId);

        return $this->addImageDimensionsToRecord($record);
    }

    /**
     * Resolve record image ID and base image URL
     *
     * @param array $record
     * @param int $storeId
     * @return array
     */
    private function resolveRepresentativeProductImageData(array $record, int $storeId): array
    {
        $recordId = isset($record['id']) ? (int) $record['id'] : 0;
        if ($recordId <= 0) {
            $record['imageUrl'] = null;

            return $record;
        }

        try {
            $collection = $this->productCollectionFactory->create();
            $collection->setStoreId($storeId);
            $collection->addStoreFilter($storeId);
            $collection->addIdFilter([$recordId]);
            $collection->addAttributeToSelect(['image', 'thumbnail']);
            $collection->addMediaGalleryData();
            $collection->setPageSize(1);

            $product = $collection->getFirstItem();
            if ($product && $product->getId()) {
                $resolvedImageId = $this->wtaImageHelper->getImageValue($product);
                if ($resolvedImageId !== '') {
                    $record['image'] = $resolvedImageId;
                }

                $record['imageUrl'] = $this->getProductBaseImageUrlById($recordId, $storeId);
            }
        } catch (\Exception $e) {
            $record['imageUrl'] = null;
        }

        return $record;
    }

    /**
     * Add image dimensions to record
     *
     * @param array $record
     * @return array
     */
    private function addImageDimensionsToRecord(array $record): array
    {
        $imageUrl = isset($record['imageUrl']) ? (string) $record['imageUrl'] : '';
        if ($imageUrl === '') {
            $record['imageSize'] = null;
            $record['imageWidth'] = null;
            $record['imageHeight'] = null;

            return $record;
        }

        $imageInfo = $this->getImageInfoFromUrl($imageUrl);
        $record['imageSize'] = $imageInfo ? (string) ($imageInfo[0] * $imageInfo[1]) : null;
        $record['imageWidth'] = $imageInfo ? $imageInfo[0] : null;
        $record['imageHeight'] = $imageInfo ? $imageInfo[1] : null;

        return $record;
    }

    /**
     * Get image info from URL
     *
     * @param string $imageUrl
     * @return array|null
     */
    private function getImageInfoFromUrl($imageUrl)
    {
        if (!$imageUrl || !is_string($imageUrl)) {
            return null;
        }

        try {
            $this->curl->setOptions([
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_MAXREDIRS => 3,
                CURLOPT_TIMEOUT => 10
            ]);
            $this->curl->get($imageUrl);
            $imageBytes = $this->curl->getBody();
        } catch (\Exception $e) {
            return null;
        }

        if (!$imageBytes) {
            return null;
        }

        $imageInfo = getimagesizefromstring($imageBytes);
        if (!$imageInfo) {
            return null;
        }

        return $imageInfo;
    }

    /**
     * Get product base image URL by product ID
     *
     * @param int $productId
     * @param int $storeId
     * @return string|null
     */
    private function getProductBaseImageUrlById(int $productId, int $storeId): ?string
    {
        if ($productId <= 0) {
            return null;
        }

        try {
            $collection = $this->productCollectionFactory->create();
            $collection->setStoreId($storeId);
            $collection->addStoreFilter($storeId);
            $collection->addIdFilter([$productId]);
            $collection->addAttributeToSelect(['image']);
            $collection->setPageSize(1);

            $product = $collection->getFirstItem();
            if (!$product || !$product->getId()) {
                return null;
            }

            $imageFile = (string) $product->getImage();
            if ($imageFile === '' || $imageFile === 'no_selection') {
                return null;
            }

            return $this->imageHelper->init($product, 'product_base_image')
                ->setImageFile($imageFile)
                ->getUrl();
        } catch (\Exception $e) {
            return null;
        }
    }

    /**
     * Get random representative products
     *
     * @param \WriteTextAI\WriteTextAI\Model\AiCategory $aiCategory
     * @param int $limit
     * @return array
     */
    public function getRandomRepresentativeProducts($aiCategory, $limit = 5)
    {
        $response = [];
        $categoryId = $aiCategory->getCategoryId();
        $storeId = (int) ($aiCategory->getStoreId() ?: $this->storeManager->getStore()->getId());

        if (!$categoryId) {
            return $response;
        }

        try {
            $collection = $this->productCollectionFactory->create();
            $collection->setStoreId($storeId);
            $collection->addStoreFilter($storeId);
            $collection->addCategoryFilter($this->categoryRepository->get($categoryId, $storeId));
            $collection->addAttributeToSelect(['name', 'image', 'thumbnail', 'description']);
            $collection->addAttributeToFilter(
                'visibility',
                ['neq' => \Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE]
            );
            $collection->getSelect()->orderRand();
            $collection->setPageSize($limit);
            $collection->load();
            $collection->addMediaGalleryData();

            if (!$collection->getSize()) {
                $collection = $this->productCollectionFactory->create();
                $collection->setStoreId($storeId);
                $collection->addCategoryFilter($this->categoryRepository->get($categoryId, $storeId));
                $collection->addAttributeToSelect(['name', 'image', 'thumbnail', 'description']);
                $collection->getSelect()->orderRand();
                $collection->setPageSize($limit);
                $collection->load();
                $collection->addMediaGalleryData();
            }

            foreach ($collection as $product) {
                $record = [];
                $record['id'] = $product->getId();
                $record['name'] = $product->getName();
                $record['description'] = $product->getDescription();

                // Get product image URL
                $imageUrl = $this->imageHelper->init($product, 'product_base_image')
                    ->setImageFile($product->getImage())
                    ->getUrl();
                $record['image'] = $this->wtaImageHelper->getImageValue($product);
                $record['imageUrl'] = $imageUrl;

                if ($imageUrl) {
                    $imageInfo = $this->getImageInfoFromUrl($imageUrl);
                    $record['imageSize'] = $imageInfo ? (string) ($imageInfo[0] * $imageInfo[1]) : null;
                    $record['imageWidth'] = $imageInfo ? $imageInfo[0] : null;
                    $record['imageHeight'] = $imageInfo ? $imageInfo[1] : null;
                } else {
                    $record['imageSize'] = null;
                    $record['imageWidth'] = null;
                    $record['imageHeight'] = null;
                }

                $response[] = $record;
            }
        } catch (\Exception $e) {
            $response = [];
        }

        return $response;
    }
}
