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

namespace WriteTextAI\WriteTextAI\Controller\Adminhtml\CategoriesGrid;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Data\Form\FormKey;
use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\Store;
use WriteTextAI\WriteTextAI\Model\BulkGenerateRequestsManager;
use WriteTextAI\WriteTextAI\Helper\Data;
use WriteTextAI\WriteTextAI\Helper\Store as StoreHelper;
use WriteTextAI\WriteTextAI\Model\ApiManager;
use WriteTextAI\WriteTextAI\Model\OptionSource\Filter\Fields;
use WriteTextAI\WriteTextAI\Ui\Component\MassAction\JsonFilter;
use WriteTextAI\WriteTextAI\Model\Api\Keywords;
use WriteTextAI\WriteTextAI\Model\Config\Source\AutomaticTextOptimization;

class MassGenerate extends Action implements HttpPostActionInterface
{
    public const ADMIN_RESOURCE = 'WriteTextAI_WriteTextAI::generate';

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

    /**
     * @var RemoteAddress
     */
    protected $remoteAddress;

    /**
     * @var ScopeConfigInterface
     */
    protected $scopeConfig;

    /**
     * @var JsonFilter
     */
    protected $filter;

    /**
     * @var CategoryCollectionFactory
     */
    protected $collectionFactory;

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

    /**
     * @var FormKey
     */
    protected $formKey;

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

    /**
     * @var BulkGenerateRequestsManager
     */
    protected $bulkGenerateRequestsManager;

    /**
     * @var Keywords
     */
    protected $keywords;

    /**
     * Constructor
     *
     * @param Context $context
     * @param ApiManager $apiManager
     * @param RemoteAddress $remoteAddress
     * @param ScopeConfigInterface $scopeConfig
     * @param JsonFilter $filter
     * @param CategoryCollectionFactory $collectionFactory
     * @param Data $helper
     * @param FormKey $formKey
     * @param StoreHelper $storeHelper
     * @param BulkGenerateRequestsManager $bulkGenerateRequestsManager
     * @param Keywords $keywords
     */
    public function __construct(
        Context $context,
        ApiManager $apiManager,
        RemoteAddress $remoteAddress,
        ScopeConfigInterface $scopeConfig,
        JsonFilter $filter,
        CategoryCollectionFactory $collectionFactory,
        Data $helper,
        FormKey $formKey,
        StoreHelper $storeHelper,
        BulkGenerateRequestsManager $bulkGenerateRequestsManager,
        Keywords $keywords
    ) {
        parent::__construct($context);
        $this->apiManager = $apiManager;
        $this->remoteAddress = $remoteAddress;
        $this->scopeConfig = $scopeConfig;
        $this->filter = $filter;
        $this->collectionFactory = $collectionFactory;
        $this->helper = $helper;
        $this->formKey = $formKey;
        $this->storeHelper = $storeHelper;
        $this->bulkGenerateRequestsManager = $bulkGenerateRequestsManager;
        $this->keywords = $keywords;
    }

    /**
     * Execute
     *
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function execute()
    {
        $response = $this->resultFactory->create(ResultFactory::TYPE_JSON);

        try {
            $selectedFields = (array) $this->getRequest()->getPost('fields', []);
            $tones = $this->getRequest()->getPost('tones', explode(",", (string) $this->helper->getTones()));
            $style = $this->getRequest()->getPost('styles', (string) $this->helper->getStyles());
            $customTone = $this->getRequest()->getPost('custom_tone', "");
            $customStyle = $this->getRequest()->getPost('custom_style', "");
            $audience = $this->getRequest()->getPost('audience');
            $filters = (array) $this->getRequest()->getPost('filters', []);

            $pageTitleTemplate = $this->getRequest()->getPost('wtai_generate_template_page_title');
            $categoryDescriptionTemplate = $this->getRequest()->getPost('wtai_generate_template_category_description');
            $templatesUsed = [
                'page_title' => $pageTitleTemplate,
                'category_description' => $categoryDescriptionTemplate
            ];

            $descriptionMin = $this->getRequest()->getPost(
                'description_min',
                $this->helper->getDescriptionSettings('min')
            );
            $descriptionMax = $this->getRequest()->getPost(
                'description_max',
                $this->helper->getDescriptionSettings('max')
            );

            $voiceAndStyleMethod = $this->getRequest()->getPost('voice_and_style_method', 'manual');
            $useAiModel = $voiceAndStyleMethod === 'ai_model';
            $selectedAiModel = $this->getRequest()->getPost('wtai_selected_ai_model', '');

            $storeId = isset($filters['store_id']) ? (int) $filters['store_id'] : Store::DEFAULT_STORE_ID;

            $country = (string) $this->scopeConfig->getValue(
                'general/country/default',
                ScopeInterface::SCOPE_STORE,
                $storeId
            );
            $language = $this->storeHelper->getFormattedLanguage($storeId);
            $ipAddress = $this->remoteAddress->getRemoteAddress();

            $attributes = $this->getRequest()->getPost('attributes', []);
            $fetchImages = false;
            foreach ($attributes as $attribute) {
                    
                if (strtolower($attribute) === 'thumbnail') {
                    $fetchImages = true;
                }
            }
            $isProductResearchDataSelected = in_array('wtai_product_research_data', $attributes);

            $collection = $this->filter->getCollection(
                $this->collectionFactory->create()->addAttributeToSelect('*')
            );
            $collection->setStoreId($storeId);

            $texts = [];
            foreach ($collection as $category) {
                $fields = [];
                foreach ($selectedFields as $fieldName) {
                    if (!isset(Fields::CATEGORY_MAPPING[$fieldName])) {
                        continue;
                    }
                    $field = [
                        'field' => Fields::CATEGORY_MAPPING[$fieldName]
                    ];

                    if (isset($templatesUsed[$fieldName]) && $templatesUsed[$fieldName]) {
                        $field['templateId'] = $templatesUsed[$fieldName];
                    }

                    if ($fieldName === 'category_description') {
                        $field['minWords'] = $descriptionMin;
                        $field['maxWords'] = $descriptionMax;
                    }

                    $fields[] = $field;
                }

                if (empty($fields)) {
                    continue;
                }

                $texts[] = [
                    'name' => (string) $category->getName(),
                    'recordId' => (string) $category->getId(),
                    'fields' => $fields,
                    'url' => (string) $category->getUrl()
                ];
            }

            $params = [
                'type' => 'Category',
                'storeId' => (string) $storeId,
                'language' => $language,
                'countries' => [$country],
                'ipAddress' => $ipAddress,
                'texts' => $texts,
                'fetchImages' => $fetchImages,
                "fetchRecordData" => [
                    "attributes" => $attributes,
                    "hasProductNames" => false
                ],
                "generationParameters" => [
                    "enableResearch" => $isProductResearchDataSelected
                ]
            ];

            if (filter_var($useAiModel, FILTER_VALIDATE_BOOLEAN)) {
                $params['generationParameters']['brandVoiceId'] = $selectedAiModel;
            }

            if (!$useAiModel) {
                if (is_array($tones) && in_array('custom', $tones)) {
                    $params['generationParameters']['customTone'] = $customTone;
                } else {
                    $params['generationParameters']['tones'] = $tones;
                }

                if ($style === 'custom') {
                    $params['generationParameters']['customStyle'] = $customStyle;
                } else {
                    $params['generationParameters']['style'] = $style;
                }

                if (!empty($audience)) {
                    $params['generationParameters']['audiences'] = $audience;
                }
            }

            $autoOptimizeKeywords = filter_var(
                $this->getRequest()->getPost('auto_optimize_keywords'),
                FILTER_VALIDATE_BOOLEAN
            );
            $keywordOpParams = $this->getKeywordOptimizationParams($country);
            if (!empty($keywordOpParams)) {
                $params['keywordOptimization'] = $keywordOpParams;
                $params['development'] = filter_var($this->helper->getKoDev(), FILTER_VALIDATE_BOOLEAN);
            }
            if ($this->helper->getForceQueueSeconds()) {
                $params['developmentQueueWaitTimeInSeconds'] = $this->helper->getForceQueueSeconds();
            }

            $specialInstructions = $this->getRequest()->getPost('product_details', '');
            if ($specialInstructions) {
                $params['specialInstructions'] = $specialInstructions;
            }

            if (count($texts) < 2) {
                $params['queue'] = true;
            }

            $jsonParams = json_encode($params, JSON_INVALID_UTF8_IGNORE);

            $apiResponse = $this->apiManager->generate($jsonParams);

            if ($apiResponse['requestId'] !== null) {
                $records = array_column($texts, 'recordId');
                $user = $this->_auth->getUser();
                $userEmail = $user ? (string) $user->getEmail() : '';
                $this->bulkGenerateRequestsManager->setBulkRequest(
                    $apiResponse['requestId'],
                    $userEmail,
                    'Category',
                    $storeId,
                    $records
                );
            }

            $result = [
                'success' => true,
                'form_key' => $this->formKey->getFormKey(),
                'params' => $jsonParams,
                'api_response' => $apiResponse
            ];
        } catch (\WriteTextAI\WriteTextAI\Exception\UnauthorizedException $e) {
            $result = [
                'success' => false,
                'unauthorized' => true,
                'login_url' => $this->_url->getUrl('wtai/setup/index'),
                'message' => $e->getMessage()
            ];
        } catch (\Exception $e) {
            $message = $e->getMessage();
            if (!$message) {
                $message = __(
                    'A system error has occurred. Please try again. If the issue persists,'
                    . ' please contact our support team at support@writetext.ai.'
                );
            }

            $result = [
                'success' => false,
                'message' => $message,
                'params' => $jsonParams ?? []
            ];
        }

        $response->setData($result);
        return $response;
    }

    /**
     * Get keyword optimization params
     *
     * @param string $country
     * @return array
     */
    protected function getKeywordOptimizationParams($country)
    {
        $autoOptimizeKeywords = filter_var(
            $this->getRequest()->getPost('auto_optimize_keywords'),
            FILTER_VALIDATE_BOOLEAN
        );
        if (!$autoOptimizeKeywords) {
            return [];
        }

        $searchIntent = $this->getRequest()->getPost('search_intent');
        $clusterCount = $this->getRequest()->getPost('cluster_count');
        $action = $this->getRequest()->getPost('automatic_text_optimization');
        switch ($action) {
            case AutomaticTextOptimization::AUTO_REWRITE_AND_QUEUE:
                $action = 'AutomaticRewrite';
                break;
            case AutomaticTextOptimization::FLAG:
                $action = 'FlagForRewrite';
                break;
            case AutomaticTextOptimization::AUTO_REWRITE_AND_TRANSFER:
                $action = 'FullAutomation';
                break;
        }

        $triggers = $this->keywords->prepareDefaultTriggerSettingsParameters();
        foreach ($triggers as $key => $trigger) {
            $triggers[$key]['action'] = $action;
        }

        $params = [
            "intents" => explode(', ', $searchIntent),
            "countryCode" => $country,
            "clusters" => $clusterCount,
            "triggers" => $triggers
        ];
        
        if (filter_var($this->helper->getKoDev(), FILTER_VALIDATE_BOOLEAN)) {
            $params["developmentSettings"] = [
                "waitTimePerStep" => 1000,
                "maxSteps" => 9,
                "failAfterFirstStep" => filter_var($this->helper->getForceFailed(), FILTER_VALIDATE_BOOLEAN)
            ];
        }

        return $params;
    }
}
