<?php
declare(strict_types=1);

namespace WriteTextAI\WriteTextAI\Model;

use WriteTextAI\WriteTextAI\Api\ImageApiInterface;
use Magento\Framework\Webapi\Rest\Response as RestResponse;
use WriteTextAI\WriteTextAI\Helper\Product as ProductHelper;
use Magento\Catalog\Helper\Image as ImageHelper;
use WriteTextAI\WriteTextAI\Helper\Image as WtaImageHelper;
use WriteTextAI\WriteTextAI\Model\Magento\Category as MagentoCategory;

use Magento\Framework\Exception\NoSuchEntityException;

/**
 * Class ImageApi
 * Implementation for retrieving product images with alt text
 */
class ImageApi implements ImageApiInterface
{
    /**
     * @var RestResponse
     */
    private $response;

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

    /**
     * @var MagentoCategory
     */
    private $magentoCategory;

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

    /**
     * @var array
     */
    private $featuredImageData = [];

    /**
     * @var array
     */
    private $galleryImageData = [];

    /**
     * @param RestResponse $response
     * @param ProductHelper $productHelper
     * @param ImageHelper $imageHelper
     * @param MagentoCategory $magentoCategory
     * @param WtaImageHelper $wtaImageHelper
     */
    public function __construct(
        RestResponse $response,
        ProductHelper $productHelper,
        ImageHelper $imageHelper,
        MagentoCategory $magentoCategory,
        WtaImageHelper $wtaImageHelper
    ) {
        $this->response = $response;
        $this->productHelper = $productHelper;
        $this->imageHelper = $imageHelper;
        $this->magentoCategory = $magentoCategory;
        $this->wtaImageHelper = $wtaImageHelper;
    }

    /**
     * Get product images with alt text
     *
     * @param int $recordId
     * @param string $type
     * @param int $storeId
     * @param string $language
     * @param bool $withAltText
     * @param bool $withTemplate
     * @return \Magento\Framework\DataObject
     */
    public function getImages(
        $recordId,
        $type,
        $storeId = null,
        $language = null,
        $withAltText = false,
        $withTemplate = false
    ) {
        $this->featuredImageData = [];
        $this->galleryImageData = [];

        try {
            $entity = $this->getEntity($recordId, $type, $storeId);
        } catch (NoSuchEntityException $e) {
            $this->response->setStatusCode(404);
            return $this->response->setBody(json_encode(['error' => $e->getMessage()]))->sendResponse();
        }
        try {
            if ($type === 'Category') {
                $responseData = $this->getCategoryImageResponse($entity, $withTemplate);
            } else {
                $images = $this->productHelper->getImages($entity, $storeId, $language);
                $altTexts = $this->getAltTextParams($entity, $images);
                $responseData = [];

                if (!empty($this->featuredImageData)) {
                    $responseData['images'] = [$this->featuredImageData];

                    if ($withTemplate) {
                        $responseData['featuredImage'] = $this->featuredImageData;
                    }
                }

                if (!empty($altTexts) && $withAltText) {
                    $responseData['imageAltTexts'] = $altTexts;
                }

                if (!empty($this->galleryImageData) && $withTemplate) {
                    $responseData['galleryImages'] = $this->galleryImageData;
                }
            }

            if (empty($responseData['images'])) {
                $responseData['images'] = [];
            }

            return $this->response->setBody(json_encode($responseData))->sendResponse();
        } catch (\Exception $e) {
            $this->response->setStatusCode(500);
            return $this->response->setBody(json_encode(
                [
                    'error' => 500,
                    'message' => $e->getMessage()
                ]
            ))->sendResponse();
        }
    }

    /**
     * Resolve the requested entity from the API type.
     *
     * @param int $recordId
     * @param string $type
     * @param int|null $storeId
     * @return mixed
     * @throws NoSuchEntityException
     */
    private function getEntity($recordId, $type, $storeId)
    {
        if ($type === 'Category') {
            $category = $this->magentoCategory->getCategory($recordId, $storeId);
            if (!$category || !$category->getId()) {
                throw new NoSuchEntityException(__('The category that was requested doesn\'t exist.'));
            }

            return $category;
        }

        return $this->productHelper->getProduct($recordId, $storeId);
    }

    /**
     * Build the category image response payload.
     *
     * @param \Magento\Catalog\Model\Category $category
     * @param bool $withTemplate
     * @return array
     */
    private function getCategoryImageResponse($category, $withTemplate)
    {
        if (!$category->getImage()) {
            return ['images' => []];
        }

        $imageData = [
            'imageId' => $category->getImage(),
            'url' => $this->wtaImageHelper->getCategoryImageUrl($category)
        ];

        $responseData = [
            'images' => [$imageData]
        ];

        if ($withTemplate) {
            $responseData['featuredImage'] = $imageData;
        }

        return $responseData;
    }

    /**
     * Get alt text params
     *
     * @param \Magento\Catalog\Model\Product $product
     * @param array $galleryImages
     * @param array $failedImages
     * @return array
     */
    protected function getAltTextParams($product, $galleryImages, $failedImages = [])
    {
        $altTexts = [];

        $images = $product->getMediaGalleryImages()->setOrder('position', 'ASC');
        $imageLimit = 10;
        $imageCount = 0;

        $featuredImageData = [];
        $featuredImageId = null;
        $isFeaturedImageIncluded = false;
        foreach ($galleryImages as $image) {
            if (isset($image['is_featured']) && $image['is_featured']) {
                $featuredImageId = $image['id'];
                $this->featuredImageData = [
                    'imageId' => $image['id'],
                    'url' => $image['noncached_url']
                ];
            }
        }

        foreach ($images as $image) {
            if ($image->getDisabled()) {
                continue;
            }
            
            if (in_array($image->getId(), $failedImages)) {
                $imageCount++;
                continue;
            }

            if ($imageCount >= $imageLimit) {
                break;
            }

            $imageFile = $image->getFile();
            $imageFilePreview = $this->imageHelper->init(
                $product,
                'product_listing_thumbnail_preview'
            )->setImageFile($imageFile);
            $url = $imageFilePreview->getUrl();
            if ($url == $imageFilePreview->getDefaultPlaceholderUrl()) {
                continue;
            }

            if ($image->getId() === $featuredImageId) {
                $isFeaturedImageIncluded = true;
                continue;
            }

            $this->galleryImageData[] = [
                'imageId' => $image->getId(),
                'url' => $image->getUrl()
            ];
            $altTexts = $this->galleryImageData;
                
            $imageCount++;
        }
        
        /** Add featured image to the beginning of the array */
        if ($isFeaturedImageIncluded) {
            array_unshift($altTexts, $this->featuredImageData);
        }

        return $altTexts;
    }
}
