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

declare(strict_types=1);

namespace WriteTextAI\WriteTextAI\Controller\Adminhtml\Setup;

use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
use WriteTextAI\WriteTextAI\Helper\Settings;
use WriteTextAI\WriteTextAI\Helper\Statistics;
use WriteTextAI\WriteTextAI\Model\Config\Source\DefaultValues\CategoryTexts as DefaultCategoryTexts;
use WriteTextAI\WriteTextAI\Model\Config\Source\DefaultValues\ProductTexts as DefaultProductTexts;
use Magento\Framework\App\Config\ConfigResource\ConfigInterface;
use WriteTextAI\WriteTextAI\ViewModel\Premium;
use WriteTextAI\WriteTextAI\Helper\CronStatus;
use Magento\Framework\Module\ModuleListInterface;
use WriteTextAI\WriteTextAI\Model\Api\CurlBuilder;
use WriteTextAI\WriteTextAI\Helper\Data;
use WriteTextAI\WriteTextAI\Model\IntegrationApiManager;

class Save extends \Magento\Backend\App\Action implements HttpPostActionInterface
{
    public const MODULE_NAME = 'WriteTextAI_WriteTextAI';

    /**
     * Backend Config Model Factory
     *
     * @var \Magento\Config\Model\Config\Factory
     */
    protected $configFactory;

    /**
     * @var \WriteTextAI\WriteTextAI\Helper\Data
     */
    protected $helper;

    /**
     * @var \WriteTextAI\WriteTextAI\Helper\Statistics
     */
    protected $statisticsHelper;

    /**
     * @var DefaultCategoryTexts
     */
    protected $defaultCategoryTexts;

    /**
     * @var DefaultProductTexts
     */
    protected $defaultProductTexts;

    /**
     * @var ConfigInterface
     */
    protected $configManager;

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

    /**
     * @var CronStatus
     */
    protected $cronStatus;

    /**
     * @var ModuleListInterface
     */
    protected $moduleList;

    /**
     * @var CurlBuilder
     */
    protected $curlBuilder;

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

    /**
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Config\Model\Config\Factory $configFactory
     * @param \WriteTextAI\WriteTextAI\Helper\Data $helper
     * @param \WriteTextAI\WriteTextAI\Helper\Statistics $statisticsHelper
     * @param DefaultCategoryTexts $defaultCategoryTexts
     * @param DefaultProductTexts $defaultProductTexts
     * @param ConfigInterface $configManager
     * @param Premium $premium
     * @param CronStatus $cronStatus
     * @param ModuleListInterface $moduleList
     * @param CurlBuilder $curlBuilder
     * @param Data $helperData
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Config\Model\Config\Factory $configFactory,
        \WriteTextAI\WriteTextAI\Helper\Data $helper,
        \WriteTextAI\WriteTextAI\Helper\Statistics $statisticsHelper,
        DefaultCategoryTexts $defaultCategoryTexts,
        DefaultProductTexts $defaultProductTexts,
        ConfigInterface $configManager,
        Premium $premium,
        CronStatus $cronStatus,
        ModuleListInterface $moduleList,
        CurlBuilder $curlBuilder,
        Data $helperData
    ) {
        parent::__construct($context);
        
        $this->defaultCategoryTexts = $defaultCategoryTexts;
        $this->defaultProductTexts = $defaultProductTexts;
        $this->configFactory = $configFactory;
        $this->helper = $helper;
        $this->statisticsHelper = $statisticsHelper;
        $this->configManager = $configManager;
        $this->premium = $premium;
        $this->cronStatus = $cronStatus;
        $this->moduleList = $moduleList;
        $this->curlBuilder = $curlBuilder;
        $this->helperData = $helperData;
    }

    /**
     * Execute
     *
     * @return \Magento\Framework\Controller\Result\Redirect
     */
    public function execute()
    {
        $step = $this->getRequest()->getPost('step');

        switch ($step) {
            case 2:
                $this->saveStep2();
                $this->statisticsHelper->sendStatistics('step3');
                break;
            case 3:
                $this->saveStep3();
                try {
                    if ($this->premium->getHasProAccess()) {
                        $this->saveKeywords();
                    }
                } catch (\WriteTextAI\WriteTextAI\Exception\TermsException $e) {
                    // Do nothing
                    true; // suppresses empty catch warning
                }
                $this->statisticsHelper->sendStatistics('step4');
                break;
            case 4:
                $this->saveStep4();
                $this->statisticsHelper->sendStatistics('step5');
                break;
        }

        $this->setWelcomeNewVersionFlagToFalse();
        $this->helper->flushConfigCache();

        return $this->resultRedirectFactory->create()->setPath('wtai/*/');
    }

    /**
     * Set welcome new version flag to false
     *
     * @return void
     */
    protected function setWelcomeNewVersionFlagToFalse()
    {
        $welcomeNewVersion = $this->helper->conf('writetextai_settings/popups/welcome_new_version');

        if ($welcomeNewVersion !== $this->getModuleVersion()) {
            $this->configManager->saveConfig(
                'writetextai_settings/popups/welcome_new_version',
                $this->getModuleVersion(),
                'default'
            );
        }
    }

    /**
     * Get module version
     *
     * @return string
     */
    protected function getModuleVersion()
    {
        return $this->moduleList->getOne(self::MODULE_NAME)['setup_version'];
    }

    /**
     * Save keywords
     *
     * @return void
     */
    protected function saveKeywords()
    {
        try {
            $params = $this->getRequest();
            $clusterCount = $params->getPost('cluster_count');
            $clusterCountCategory = $params->getPost('cluster_count_category');
            $triggerAction = $params->getPost('trigger_action');
            $automaticTextOptimization = $params->getPost('automatic_text_optimization');
            $productTexts = $params->getPost('product_texts');
            $productTexts = $productTexts ?
                implode(',', $productTexts) : $this->defaultProductTexts->getDefaultValues();
            $categoryTexts = $params->getPost('category_texts');
            $categoryTexts = $categoryTexts ?
                implode(',', $categoryTexts) : $this->defaultCategoryTexts->getDefaultValues();
            $triggerActionNPosition = $params->getPost('trigger_action_n_position');
            $triggerActionNDays = $params->getPost('trigger_action_n_days');

            $configData = [
                'section' => Settings::SECTION_NAME
            ];

            $configData['groups']['keyword_optimization']
                ['fields']['cluster_based_pipelines_count']['value'] = $clusterCount;
            $configData['groups']['keyword_optimization']
                ['fields']['cluster_based_pipelines_count_category']['value'] = $clusterCountCategory;
            $configData['groups']['keyword_optimization']
                ['fields']['automatic_text_optimization']['value'] = $automaticTextOptimization;

            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['low']['fields']['trigger_action']['value'] = $triggerAction;
            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['low_mid']['fields']['trigger_action']['value'] = $triggerAction;
            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['mid']['fields']['trigger_action']['value'] = $triggerAction;
            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['mid_high']['fields']['trigger_action']['value'] = $triggerAction;

            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['low']['fields']['trigger_action_n_position']['value'] = $triggerActionNPosition;
            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['low_mid']['fields']['trigger_action_n_position']['value'] = $triggerActionNPosition;
            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['mid']['fields']['trigger_action_n_position']['value'] = $triggerActionNPosition;
            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['mid_high']['fields']['trigger_action_n_position']['value'] = $triggerActionNPosition;

            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['low']['fields']['trigger_action_n_days']['value'] = $triggerActionNDays;
            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['low_mid']['fields']['trigger_action_n_days']['value'] = $triggerActionNDays;
            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['mid']['fields']['trigger_action_n_days']['value'] = $triggerActionNDays;
            $configData['groups']['keyword_optimization']['groups']['pipeline_keyword']['groups']
                ['mid_high']['fields']['trigger_action_n_days']['value'] = $triggerActionNDays;
            
            $configData['groups']['keyword_optimization']['fields']['products']['value'] = $productTexts;
            $configData['groups']['keyword_optimization']['fields']['categories']['value'] = $categoryTexts;

            /** @var \Magento\Config\Model\Config $configModel */
            $configModel = $this->configFactory->create(['data' => $configData]);
            $configModel->save();
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            $messages = explode("\n", (string) $e->getMessage());
            if (empty($messages)) {
                $messages = [$e->getMessage()];
            }
            foreach ($messages as $message) {
                $this->messageManager->addError($message);
            }
        } catch (\Exception $e) {
            $this->messageManager->addException(
                $e,
                $e->getMessage()
            );
        }
    }

    /**
     * Save step 2
     *
     * @return void
     */
    protected function saveStep2()
    {
        try {
            $configData = [
                'section' => Settings::SECTION_NAME
            ];

            $fields = array_keys($this->helper->getDataMappingFields());
            $categoryFields = array_keys($this->helper->getCategoryDataMappingFields());

            foreach ($fields as $field) {
                $value = $this->getRequest()->getPost($field);
                $configData['groups']['mapping']['fields'][$field]['value'] = $value;
            }

            foreach ($categoryFields as $field) {
                $postField = $field;
                if ($field === 'page_title') {
                    $postField = 'category_page_title';
                } elseif ($field === 'page_description') {
                    $postField = 'category_page_description';
                }
                $value = $this->getRequest()->getPost($postField);
                $configData['groups']['category_mapping']['fields'][$field]['value'] = $value;
            }

            /**
             * Save custom open graph
             */
            $customOpenGraph = $this->getRequest()->getPost('custom_open_graph');
            $configData['groups']['mapping']['fields']['custom_open_graph']['value'] = $customOpenGraph ?? 0;
            if (!$customOpenGraph) {
                $configData['groups']['mapping']['fields']['open_graph']['value'] = '';
            }

            if ($this->cronStatus->isCronRunning(CronStatus::DEFAULT_CRON_MINUTES_CHECK)) {
                //send token time to api
                try {
                    $tokenTime = $this->curlBuilder->getTokenTime();
                    if (!$tokenTime) {
                        $configScheduledCronTime = $this->helper->getAutotransferSettings('cron_schedule');
                        $cronTime = $this->helper->cronToTime($configScheduledCronTime);
                        $tokenTime = $this->helper->convertToConfigTimezone($cronTime);
                        $bodyTokenTime = [
                            'time' => $tokenTime
                        ];
                        $tokenTimeResponse = $this->curlBuilder->sendTokenTime($bodyTokenTime);
                    }
                } catch (\Exception $e) {
                    $tokenTimeResponse = null;
                    $this->messageManager->addError($message);
                    $this->messageManager->addException(
                        $e,
                        $e->getMessage()
                    );
                }
            }

            $configData['groups']['setup']['fields']['finalized']['value'] = true;

            /** @var \Magento\Config\Model\Config $configModel */
            $configModel = $this->configFactory->create(['data' => $configData]);
            $configModel->save();
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            $messages = explode("\n", (string) $e->getMessage());
            if (empty($messages)) {
                $messages = [$e->getMessage()];
            }
            foreach ($messages as $message) {
                $this->messageManager->addError($message);
            }
        } catch (\Exception $e) {
            $this->messageManager->addException(
                $e,
                $e->getMessage()
            );
        }
    }
    
    /**
     * Save step 3
     *
     * @return void
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Exception
     */
    protected function saveStep3()
    {
        $request = $this->getRequest();
        $configData = [
            'section' => Settings::SECTION_NAME
        ];

        // tones/styles/audience
        foreach (['tones', 'styles', 'audiences'] as $field) {
            if ($field != 'styles') {
                $value = implode(",", $request->getPost($field, []));
            } else {
                $value = $this->getRequest()->getPost($field) ;
            }

            $configData['groups']['general']['fields'][$field]['value'] = $value;
        }

        // attributes
        $attributes = implode(",", $request->getPost('attributes', []));
        $configData['groups']['attributes']['fields']['attributes']['value'] = $attributes;

        // min/max
        foreach (['min', 'max'] as $field) {
            $description    = $request->getPost('description_'. $field);
            $excerpt        = $request->getPost('excerpt_'. $field);
            $category_description    = $request->getPost('category_description_'. $field);

            $configData['groups']['description']['fields'][$field]['value'] = $description;
            $configData['groups']['excerpt']['fields'][$field]['value'] = $excerpt;
            $configData['groups']['category_description']['fields'][$field]['value'] = $category_description;
        }

        $autotransferSchedule = $this->getRequest()->getPost('auto_transfer_schedule');
        if ($this->cronStatus->isCronRunning(CronStatus::DEFAULT_CRON_MINUTES_CHECK)) {
            $configData['groups']['autotransfer']['fields']['cron_schedule']['value'] = $autotransferSchedule;
            //send token time to api
            try {
                $cronTime = $this->helper->cronToTime($autotransferSchedule);
                $tokenTime = $this->helper->convertToConfigTimezone($cronTime);
                $bodyTokenTime = [
                    'time' => $tokenTime
                ];
                $tokenTimeResponse = $this->curlBuilder->sendTokenTime($bodyTokenTime);
            } catch (\Exception $e) {
                $tokenTimeResponse = null;
                $this->messageManager->addError($message);
                $this->messageManager->addException(
                    $e,
                    $e->getMessage()
                );
            }
        }

        try {
            /** @var \Magento\Config\Model\Config $configModel */
            $configModel = $this->configFactory->create(['data' => $configData]);
            $configModel->save();
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            $messages = explode("\n", (string) $e->getMessage());
            if (empty($messages)) {
                $messages = [$e->getMessage()];
            }
            foreach ($messages as $message) {
                $this->messageManager->addError($message);
            }
        } catch (\Exception $e) {
            $this->messageManager->addException(
                $e,
                $e->getMessage()
            );
        }
    }

    /**
     * Save step 4
     *
     * @return void
     */
    protected function saveStep4()
    {
        try {
            $configData = ['section' => Settings::SECTION_NAME];
            $finalized = $this->getRequest()->getPost('finalized');
            $configData['groups']['setup']['fields']['finalized']['value'] = $finalized;

            /** @var \Magento\Config\Model\Config $configModel */
            $configModel = $this->configFactory->create(['data' => $configData]);
            $configModel->save();
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            $messages = explode("\n", (string) $e->getMessage());
            if (empty($messages)) {
                $messages = [$e->getMessage()];
            }
            foreach ($messages as $message) {
                $this->messageManager->addError($message);
            }
        } catch (\Exception $e) {
            $this->messageManager->addException(
                $e,
                $e->getMessage()
            );
        }
    }
}
