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

namespace WriteTextAI\WriteTextAI\Helper;

use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use WriteTextAI\WriteTextAI\Model\GeneratedText;
use WriteTextAI\WriteTextAI\Helper\Settings;
use WriteTextAI\WriteTextAI\Model\Api\Session as ApiSession;
use Magento\User\Model\UserFactory;
use Magento\Catalog\Helper\Data;
use Magento\Framework\Filter\Template;
use Magento\Store\Model\StoreManagerInterface;
use WriteTextAI\WriteTextAI\Model\ApiManager;
use WriteTextAI\WriteTextAI\Model\SettingManager;
use WriteTextAI\WriteTextAI\Helper\Store as StoreHelper;
use WriteTextAI\WriteTextAI\Model\Categories\GeneratedText as CategoryGeneratedText;
use WriteTextAI\WriteTextAI\Helper\Categories\Fields as CategorySettings;

class Preview extends AbstractHelper
{
    /**
     * @var GeneratedText
     */
    protected $generatedText;

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

    /**
     * @var ApiSession
     */
    protected $apiSession;

    /**
     * @var UserFactory
     */
    protected $userFactory;

    /**
     * @var Data
     */
    protected $catalogData;

    /**
     * @var Template
     */
    protected $templateProcessor;

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

    /**
     * @var ApiManager
     */
    protected $apiManager;

    /**
     * @var SettingManager
     */
    protected $settingManager;

    /**
     * @var StoreHelper
     */
    protected $storeHelper;

    /**
     * @var CategoryGeneratedText
     */
    protected $categoryGeneratedText;

    /**
     * @var CategorySettings
     */
    protected $categorySettings;

    /**
     * @var array
     */
    protected $generated = [];

    /**
     * @var array
     */
    protected $categoryGenerated = [];

    /**
     * Constructor
     *
     * @param Context $context
     * @param GeneratedText $generatedText
     * @param Settings $settings
     * @param UserFactory $userFactory
     * @param ApiSession $apiSession
     * @param Data $catalogData
     * @param StoreManagerInterface $storeManager
     * @param ApiManager $apiManager
     * @param SettingManager $settingManager
     * @param StoreHelper $storeHelper
     * @param CategoryGeneratedText $categoryGeneratedText
     * @param CategorySettings $categorySettings
     */
    public function __construct(
        Context $context,
        GeneratedText $generatedText,
        Settings $settings,
        UserFactory $userFactory,
        ApiSession $apiSession,
        Data $catalogData,
        StoreManagerInterface $storeManager,
        ApiManager $apiManager,
        SettingManager $settingManager,
        StoreHelper $storeHelper,
        CategoryGeneratedText $categoryGeneratedText,
        CategorySettings $categorySettings
    ) {
        $this->generatedText = $generatedText;
        $this->settings = $settings;
        $this->apiSession = $apiSession;
        $this->userFactory = $userFactory;
        $this->catalogData = $catalogData;
        $this->storeManager = $storeManager;
        $this->apiManager = $apiManager;
        $this->settingManager = $settingManager;
        $this->storeHelper = $storeHelper;
        $this->categoryGeneratedText = $categoryGeneratedText;
        $this->categorySettings = $categorySettings;
        parent::__construct($context);
    }

    /**
     * Return template processor
     *
     * @return Template
     */
    protected function getTemplateProcessor()
    {
        if (null === $this->templateProcessor) {
            $this->templateProcessor = $this->catalogData->getPageTemplateProcessor();
        }

        return $this->templateProcessor;
    }

    /**
     * Get generated text from api
     *
     * @param int $productId
     * @param int $userId
     * @param int|null $storeId
     * @return array
     */
    public function getGeneratedTextFromApi($productId, $userId, $storeId = null)
    {
        $item = [];
        $user = $this->getUser($userId);
        
        if ($user) {
            $this->apiSession->setCurrentUser($user);
            $item = $this->generatedText->getTextFields($productId, $storeId);
        }

        return $item;
    }

    /**
     * Get preview value by attribute code
     *
     * @param int $productId
     * @param int $userId
     * @param string $attributeCode
     * @return string
     */
    public function getAttributePreviewValue($productId, $userId, $attributeCode)
    {
        $attributes = $this->getAttributes();
        $preview = '';
        if ($attributeCode && in_array($attributeCode, $attributes)) {
            $generated = $this->getGeneratedText($productId, $userId);

            foreach ($generated as $key => $value) {
                if (isset($attributes[$key]) && $attributes[$key] == $attributeCode) {
                    $preview = $this->getTemplateProcessor()->filter($value);
                }
            }
        }

        return $preview;
    }

    /**
     * Get generated images
     *
     * @param array $imageIds
     * @return array
     */
    public function getGeneratedImages($imageIds)
    {
        $apiImages = [];
        $storeId = $this->storeManager->getStore()->getId();
        $language = $this->storeHelper->getFormattedLanguage($storeId);
        $rules = $this->settingManager->getSettings('rules');
        $chunks = array_chunk($imageIds, $rules['maxImageAltTextPerRequest'] ?? 10);

        foreach ($chunks as $chunk) {
            try {
                $apiParams = [
                    "language" => $language,
                    "images" => array_values($chunk),
                    "storeId" => $storeId
                ];
                $apiResponse = $this->apiManager->getImageList($apiParams);
            } catch (\WriteTextAI\WriteTextAI\Exception\ApiException $e) {
                if ($e->getCode() === 404) {
                    $apiResponse = [];
                }
            }
            
            $apiImages += $apiResponse['images'] ?? [];
        }

        return $apiImages;
    }

    /**
     * Cache generated text
     *
     * @param int $productId
     * @param int $userId
     * @return array
     */
    public function getGeneratedText($productId, $userId)
    {
        if (!isset($this->generated[$productId])) {
            $storeId = $this->storeManager->getStore()->getId();
            $this->generated[$productId] = $this->getGeneratedTextFromApi($productId, $userId, $storeId);
        }
       
        return $this->generated[$productId];
    }

    /**
     * Get attributes
     *
     * @return array
     */
    public function getAttributes()
    {
        return $this->settings->getMappingSettings();
    }

    /**
     * Get user by id
     *
     * @param int $userId
     * @return bool|\Magento\User\Model\User
     */
    private function getUser($userId)
    {
        $model = $this->userFactory->create();
        $model->load($userId);

        if ($model->getId()) {
            return $model;
        }

        return false;
    }

    /**
     * Get preview value by attribute code
     *
     * @param int $categoryId
     * @param int $userId
     * @param string $attributeCode
     * @return string
     */
    public function getCategoryAttributePreviewValue($categoryId, $userId, $attributeCode)
    {
        $attributes = $this->getCategoryAttributes();
        $preview = '';
        if ($attributeCode && in_array($attributeCode, $attributes)) {
            $generated = $this->getCategoryGeneratedText($categoryId, $userId);

            foreach ($generated as $key => $value) {
                if (isset($attributes[$key]) && $attributes[$key] == $attributeCode) {
                    $preview = $this->getTemplateProcessor()->filter($value);
                }
            }
        }

        return $preview;
    }

    /**
     * Get generated text from api
     *
     * @param int $categoryId
     * @param int $userId
     * @param int|null $storeId
     * @return array
     */
    public function getCategoryGeneratedTextFromApi($categoryId, $userId, $storeId = null)
    {
        $item = [];
        $user = $this->getUser($userId);
        
        if ($user) {
            $this->apiSession->setCurrentUser($user);
            $item = $this->categoryGeneratedText->getTextFields($categoryId, $storeId);
        }

        return $item;
    }

    /**
     * Cache generated text
     *
     * @param int $categoryId
     * @param int $userId
     * @return array
     */
    public function getCategoryGeneratedText($categoryId, $userId)
    {
        if (!isset($this->categoryGenerated[$categoryId])) {
            $storeId = $this->storeManager->getStore()->getId();
            $this->categoryGenerated[$categoryId] = $this->getCategoryGeneratedTextFromApi(
                $categoryId,
                $userId,
                $storeId
            );
        }
       
        return $this->categoryGenerated[$categoryId];
    }

    /**
     * Get attributes
     *
     * @return array
     */
    public function getCategoryAttributes()
    {
        return $this->categorySettings->getMappingSettings();
    }
}
