<?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\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 Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
use WriteTextAI\WriteTextAI\Helper\Data;
use WriteTextAI\WriteTextAI\Helper\Store as StoreHelper;
use WriteTextAI\WriteTextAI\Model\ApiManager;
use WriteTextAI\WriteTextAI\Model\Config\Source\AutomaticTextOptimization;
use WriteTextAI\WriteTextAI\Model\FullAutomationRequestsManager;
use WriteTextAI\WriteTextAI\Model\Api\Keywords;
use WriteTextAI\WriteTextAI\Model\OptionSource\Filter\Fields;
use WriteTextAI\WriteTextAI\Ui\Component\MassAction\JsonFilter;
use WriteTextAI\WriteTextAI\ViewModel\Premium;

class MassFullAutomation 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 FullAutomationRequestsManager
     */
    protected $fullAutomationRequestsManager;

    /**
     * @var Premium
     */
    protected $premium;

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

    /**
     * Constructor
     *
     * @param Action\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 FullAutomationRequestsManager $fullAutomationRequestsManager
     * @param Premium $premium
     * @param Keywords $keywords
     */
    public function __construct(
        Action\Context $context,
        ApiManager $apiManager,
        RemoteAddress $remoteAddress,
        ScopeConfigInterface $scopeConfig,
        JsonFilter $filter,
        CategoryCollectionFactory $collectionFactory,
        Data $helper,
        FormKey $formKey,
        StoreHelper $storeHelper,
        FullAutomationRequestsManager $fullAutomationRequestsManager,
        Premium $premium,
        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->fullAutomationRequestsManager = $fullAutomationRequestsManager;
        $this->premium = $premium;
        $this->keywords = $keywords;
    }

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

        if (!$this->premium->getHasProAccess()) {
            $response->setData([
                'success' => false,
                'reload' => true,
                'message' => __('Premium is required to do this action.')
            ]);

            return $response;
        }

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

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

            $pageTitleTemplate = (string) $this->getRequest()->getPost('wtai_template_page_title', '');
            $categoryDescriptionTemplate = (string) $this->getRequest()->getPost(
                'wtai_template_category_description',
                ''
            );

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

            $filters = (array) $this->getRequest()->getPost('filters', []);
            $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 ($fieldName === 'category_description') {
                        $field['minWords'] = $descriptionMin;
                        $field['maxWords'] = $descriptionMax;
                    }

                    if ($fieldName === 'page_title' && $pageTitleTemplate) {
                        $field['templateId'] = $pageTitleTemplate;
                    }

                    if ($fieldName === 'category_description' && $categoryDescriptionTemplate) {
                        $field['templateId'] = $categoryDescriptionTemplate;
                    }

                    $fields[] = $field;
                }

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

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

            $forPublishing = filter_var(
                $this->getRequest()->getPost('transfer_to_magento'),
                FILTER_VALIDATE_BOOLEAN
            );

            $params = [
                'type' => 'Category',
                'forPublishing' => $forPublishing,
                'storeId' => (string) $storeId,
                'language' => $language,
                'countries' => [$country],
                'ipAddress' => $ipAddress,
                'keywordOptimization' => $this->getKeywordOptimizationParams($country),
                'development' => filter_var($this->helper->getKoDev(), FILTER_VALIDATE_BOOLEAN),
                'fetchImages' => false,
                'texts' => $texts,
                "fetchRecordData" => [
                    'hasProductNames' => false,
                    "attributes" => $attributes
                ],
                "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();
            }

            if ($otherDetails) {
                $params['specialInstructions'] = $otherDetails;
            }

            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->fullAutomationRequestsManager->setFullAutomationRequest(
                    $apiResponse['requestId'],
                    $userEmail,
                    'Category',
                    $storeId,
                    implode(',', $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 parameters
     *
     * @param string $country
     * @return array
     */
    protected function getKeywordOptimizationParams($country)
    {
        $searchIntent = (string) $this->getRequest()->getPost('search_intent');
        $clusterCount = $this->getRequest()->getPost('cluster_count');
        $autoTextOptimization = $this->getRequest()->getPost('automatic_text_optimization');
        $triggerActionLow = $this->getRequest()->getPost('trigger_action_low');
        $triggerActionLowMid = $this->getRequest()->getPost('trigger_action_low_mid');
        $triggerActionMid = $this->getRequest()->getPost('trigger_action_mid');
        $triggerActionMidHigh = $this->getRequest()->getPost('trigger_action_mid_high');
        $triggerActionNPositionLow = $this->getRequest()->getPost('trigger_action_n_position_low');
        $triggerActionNPositionLowMid = $this->getRequest()->getPost('trigger_action_n_position_low_mid');
        $triggerActionNPositionMid = $this->getRequest()->getPost('trigger_action_n_position_mid');
        $triggerActionNPositionMidHigh = $this->getRequest()->getPost('trigger_action_n_position_mid_high');
        $triggerActionNDaysLow = $this->getRequest()->getPost('trigger_action_n_days_low');
        $triggerActionNDaysLowMid = $this->getRequest()->getPost('trigger_action_n_days_low_mid');
        $triggerActionNDaysMid = $this->getRequest()->getPost('trigger_action_n_days_mid');
        $triggerActionNDaysMidHigh = $this->getRequest()->getPost('trigger_action_n_days_mid_high');
        $products = (array) $this->getRequest()->getPost('product_texts', []);

        $action = $this->helper->getKeywordOptimizationSettings(
            'automatic_text_optimization'
        ) ?? AutomaticTextOptimization::FLAG;

        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;
        }

        $triggerSettings = [
            'pipeline_keyword' => [
                'low' => [
                    'trigger_action' => $triggerActionLow,
                    'trigger_action_n_position' => $triggerActionNPositionLow,
                    'trigger_action_n_days' => $triggerActionNDaysLow
                ],
                'low_mid' => [
                    'trigger_action' => $triggerActionLowMid,
                    'trigger_action_n_position' => $triggerActionNPositionLowMid,
                    'trigger_action_n_days' => $triggerActionNDaysLowMid
                ],
                'mid' => [
                    'trigger_action' => $triggerActionMid,
                    'trigger_action_n_position' => $triggerActionNPositionMid,
                    'trigger_action_n_days' => $triggerActionNDaysMid
                ],
                'mid_high' => [
                    'trigger_action' => $triggerActionMidHigh,
                    'trigger_action_n_position' => $triggerActionNPositionMidHigh,
                    'trigger_action_n_days' => $triggerActionNDaysMidHigh
                ]
            ],
            'automatic_text_optimization' => $autoTextOptimization,
            'products' => implode(',', $products)
        ];

        $triggers = $this->keywords->prepareCustomTriggerSettingsParameters(
            'Category',
            $triggerSettings
        );

        return [
            'intents' => explode(', ', $searchIntent),
            'countryCode' => $country,
            'clusters' => $clusterCount,
            'triggers' => $triggers
        ];
    }
}
