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

declare(strict_types=1);

namespace WriteTextAI\WriteTextAI\Block\Adminhtml\Grid;

use Magento\Backend\Block\Template\Context;
use WriteTextAI\WriteTextAI\Helper\Data;
use WriteTextAI\WriteTextAI\Model\Config\Source\ProductAttributes;
use WriteTextAI\WriteTextAI\Model\Config\Source\TriggerActions;
use WriteTextAI\WriteTextAI\Model\Config\Source\AutomaticTextOptimization;
use WriteTextAI\WriteTextAI\Model\GenerateOptionsManager;
use WriteTextAI\WriteTextAI\Model\UserFieldsSelectedManager;
use WriteTextAI\WriteTextAI\ViewModel\Tooltip;
use WriteTextAI\WriteTextAI\ViewModel\Permissions;
use WriteTextAI\WriteTextAI\ViewModel\Settings;
use WriteTextAI\WriteTextAI\ViewModel\UserFieldsSelected;
use WriteTextAI\WriteTextAI\ViewModel\TemplateSettings;
use WriteTextAI\WriteTextAI\ViewModel\AiModels;
use Magento\Framework\View\LayoutInterface;
use WriteTextAI\WriteTextAI\Model\Config\Source\ProductTexts;
use WriteTextAI\WriteTextAI\Model\Config\Source\DefaultValues\ProductTexts as DefaultProductTexts;
use WriteTextAI\WriteTextAI\Helper\CronStatus;

class Prompt extends \Magento\Backend\Block\Template
{
    /**
     * @var string
     */
    protected $_template = 'WriteTextAI_WriteTextAI::grid/massactions/prompt.phtml';

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

    /**
     * @var ProductAttributes
     */
    protected $attributes;

    /**
     * @var GenerateOptionsManager
     */
    protected $generateOptionsManager;

    /**
     * @var UserFieldsSelected
     */
    protected $userFieldsSelected;

    /**
     * @var Tooltip
     */
    protected $tooltip;

    /**
     * @var Permissions
     */
    protected $permissions;

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

    /**
     * @var UserFieldsSelectedManager
     */
    protected $userFieldsSelectedManager;

    /**
     * @var LayoutInterface
     */
    protected $layout;

    /**
     * @var TemplateSettings
     */
    protected $templateSettings;

    /**
     * @var ProductTexts
     */
    protected $productTexts;

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

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

    /**
     * @var AiModels
     */
    protected $aiModels;

    /**
     * Constructor
     *
     * @param Context $context
     * @param Data $helper
     * @param ProductAttributes $attributes
     * @param GenerateOptionsManager $generateOptionsManager
     * @param UserFieldsSelected $userFieldsSelected
     * @param Tooltip $tooltip
     * @param Permissions $permissions
     * @param Settings $settings
     * @param UserFieldsSelectedManager $userFieldsSelectedManager
     * @param LayoutInterface $layout
     * @param TemplateSettings $templateSettings
     * @param ProductTexts $productTexts
     * @param DefaultProductTexts $defaultProductTexts
     * @param CronStatus $cronStatus
     * @param AiModels $aiModels
     * @param array $data
     */
    public function __construct(
        Context $context,
        Data $helper,
        ProductAttributes $attributes,
        GenerateOptionsManager $generateOptionsManager,
        UserFieldsSelected $userFieldsSelected,
        Tooltip $tooltip,
        Permissions $permissions,
        Settings $settings,
        UserFieldsSelectedManager $userFieldsSelectedManager,
        LayoutInterface $layout,
        TemplateSettings $templateSettings,
        ProductTexts $productTexts,
        DefaultProductTexts $defaultProductTexts,
        CronStatus $cronStatus,
        AiModels $aiModels,
        array $data = []
    ) {
        $this->helper = $helper;
        $this->attributes = $attributes;
        $this->generateOptionsManager = $generateOptionsManager;
        $this->userFieldsSelected = $userFieldsSelected;
        $this->tooltip = $tooltip;
        $this->permissions = $permissions;
        $this->settings = $settings;
        $this->userFieldsSelectedManager = $userFieldsSelectedManager;
        $this->layout = $layout;
        $this->templateSettings = $templateSettings;
        $this->productTexts = $productTexts;
        $this->defaultProductTexts = $defaultProductTexts;
        $this->cronStatus = $cronStatus;
        $this->aiModels = $aiModels;
        parent::__construct($context, $data);
    }

    /**
     * Is Attribute Allowed
     *
     * @return bool
     */
    public function isAttrAllowed()
    {
        return $this->permissions->isAttrAllowed();
    }

    /**
     * Is Tone Style Allowed
     *
     * @return bool
     */
    public function isToneStyleAllowed()
    {
        return $this->permissions->isToneStyleAllowed();
    }

    /**
     * Is Words Allowed
     *
     * @return bool
     */
    public function isWordsAllowed()
    {
        return $this->permissions->isWordsAllowed();
    }

    /**
     * Get tooltip
     *
     * @param string $block
     * @return string
     */
    public function getTooltip($block)
    {
        return $this->tooltip->getTooltip($block);
    }

    /**
     * Get no AI model assigned tooltip
     *
     * @return string
     */
    public function getNoAiModelAssignedTooltip()
    {
        return $this->tooltip->getNoAiModelAssignedTooltip();
    }

    /**
     * Get tones
     *
     * @return array
     */
    public function getTones()
    {
        return $this->generateOptionsManager->getOptions('tones');
    }

    /**
     * Get tones selected
     *
     * @return array
     */
    public function getTonesSelected()
    {
        $userPreference = $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_TONES,
            'global',
            'grid'
        );

        if (!empty($userPreference)) {
            return $userPreference;
        } else {
            return $this->getTonesFromGlobalSettings();
        }
    }

    /**
     * Get custom tone
     *
     * @return string
     */
    public function getCustomTone()
    {
        return $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_CUSTOM_TONE,
            'global',
            'grid'
        );
    }

    /**
     * Get custom style
     *
     * @return string
     */
    public function getCustomStyle()
    {
        return $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_CUSTOM_STYLE,
            'global',
            'grid'
        );
    }

    /**
     * Get global settings
     *
     * @return array
     */
    public function getGlobalSettings()
    {
        return [
            'tones' => $this->getTonesFromGlobalSettings(),
            'styles' => $this->getStylesFromGlobalSettings(),
            'custom_tone' => '',
            'custom_style' => '',
            'audience' => $this->getAudienceFromGlobalSettings(),
            'attributes' => $this->getAttributesSelectedFromGlobalSettings(),
            'desc_min' => $this->helper->getDescriptionSettings('min'),
            'desc_max' => $this->helper->getDescriptionSettings('max'),
            'exc_min' => $this->helper->getExcerptSettings('min'),
            'exc_max' => $this->helper->getExcerptSettings('max'),
            'special_instructions' => '',
            'use_keywords' => true,
            'fields' => $this->userFieldsSelectedManager->getDefaultSelectedFields(),
            'auto_optimize_keywords' => false,
            'automatic_text_optimization' => $this->getKeywordOptimizationSettings(
                'automatic_text_optimization'
            ) ?? AutomaticTextOptimization::FLAG,
            'search_intent' => explode(',', $this->helper->getKeywordOptimizationSettings('search_intent')),
            'cluster_count' => $this->getKeywordOptimizationSettings('cluster_based_pipelines_count'),
            'cluster_count_category' => $this->getKeywordOptimizationSettings(
                'cluster_based_pipelines_count_category'
            ),
            'product_fields' => $this->getGlobalProductFields()
        ];
    }

    /**
     * Get tones from global settings
     *
     * @return array
     */
    private function getTonesFromGlobalSettings()
    {
        $tones = $this->getTones();

        if (!is_array($tones)) {
            return [];
        }

        $tonesSelected = array_filter($tones, function ($tone) {
            return isset($tone['default']) && $tone['default'] === true;
        });

        if (empty($tonesSelected)) {
            return [];
        }

        $tonesSelected = array_column($tonesSelected, 'id');

        return $tonesSelected;
    }

    /**
     * Get styles
     *
     * @return array
     */
    public function getStyles()
    {
        return $this->generateOptionsManager->getOptions('styles');
    }

    /**
     * Get styles selected
     *
     * @return string
     */
    public function getStylesSelected()
    {
        $userPreference = $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_STYLE,
            'global',
            'grid'
        );

        if ($userPreference) {
            return $userPreference;
        } else {
            return $this->getStylesFromGlobalSettings();
        }
    }

    /**
     * Get styles from global settings
     *
     * @return string
     */
    private function getStylesFromGlobalSettings()
    {
        $styles = $this->getStyles();

        if (!is_array($styles)) {
            return [];
        }

        $stylesSelected = array_filter($styles, function ($style) {
            return isset($style['default']) && $style['default'] === true;
        });

        if (empty($stylesSelected)) {
            return [];
        }

        $stylesSelected = array_column($stylesSelected, 'id');

        return array_shift($stylesSelected);
    }

    /**
     * Get audience
     *
     * @return array
     */
    public function getAudience()
    {
        return $this->generateOptionsManager->getOptions('audience');
    }

    /**
     * Get audiences selected
     *
     * @return array
     */
    public function getAudienceSelected()
    {
        $userPreference = $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_AUDIENCES,
            'global',
            'grid'
        );

        if ($userPreference) {
            return $userPreference;
        } else {
            return $this->getAudienceFromGlobalSettings();
        }
    }

    /**
     * Get audience selected from global settings
     *
     * @return array
     */
    private function getAudienceFromGlobalSettings()
    {
        $audience = $this->getAudience();

        if (!is_array($audience)) {
            return [];
        }

        $audienceSelected = array_filter($audience, function ($audience) {
            return isset($audience['default']) && $audience['default'] === true;
        });

        if (empty($audienceSelected)) {
            return [];
        }

        $audienceSelected = array_column($audienceSelected, 'id');

        return $audienceSelected;
    }

    /**
     * Get attributes
     *
     * @return array
     */
    public function getAttributes()
    {
        return $this->generateOptionsManager->getOptions('attributes');
    }

    /**
     * Get attributes selected from global settings
     *
     * @return array
     */
    private function getAttributesSelectedFromGlobalSettings()
    {
        $attributes = $this->getAttributes();

        $defaultAttributes = array_filter($attributes, function ($attribute) {
            return $attribute['default'];
        });
        $attributesSelected = array_map(function ($attribute) {
            return $attribute['value'];
        }, $defaultAttributes);

        return array_values($attributesSelected);
    }

    /**
     * Get attributes selected
     *
     * @return array
     */
    public function getAttributesSelected()
    {
        $userPreference = $this->userFieldsSelectedManager->checkUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_ATTRIBUTES_SELECTED,
            'product',
            'grid'
        );

        $productResearchDataSelected = $this->userFieldsSelectedManager->checkUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_PRODUCT_RESEARCH_DATA,
            '',
            ''
        );

        if ($userPreference) {
            $selectedAttributes = $this->userFieldsSelected->getUserFieldsSelected(
                UserFieldsSelectedManager::ACTION_TYPE_ATTRIBUTES_SELECTED,
                'product',
                'grid'
            );
            if ($productResearchDataSelected) {
                $selectedAttributes = $this->processProductResearchData(
                    $selectedAttributes,
                    $productResearchDataSelected
                );
            }

            return $selectedAttributes;
        } else {
            $globalAttributes = $this->getAttributesSelectedFromGlobalSettings();
            if ($productResearchDataSelected) {
                $globalAttributes = $this->processProductResearchData($globalAttributes, $productResearchDataSelected);
            }
            return $globalAttributes;
        }
    }

    /**
     * Process product research data
     *
     * @param array $selectedAttributes
     * @param string $researchDataUserPreference
     * @return array
     */
    public function processProductResearchData($selectedAttributes, $researchDataUserPreference)
    {
        $researchDataUserPreference = $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_PRODUCT_RESEARCH_DATA,
            '',
            ''
        );

        if ($researchDataUserPreference === 'true') {
            if (!in_array('wtai_product_research_data', $selectedAttributes)) {
                $selectedAttributes[] = 'wtai_product_research_data';
            }
        }

        if ($researchDataUserPreference === 'false') {
            $selectedAttributes = array_values(array_filter($selectedAttributes, function ($attribute) {
                return $attribute !== 'wtai_product_research_data';
            }));
        }
        return $selectedAttributes;
    }

    /**
     * Get special instructions
     *
     * @return string
     */
    public function getSpecialInstructions()
    {
        return $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_SPECIAL_INSTRUCTIONS,
            'product',
            'grid'
        );
    }

    /**
     * Get description min
     *
     * @return string
     */
    public function getDescriptionMin()
    {
        // global settings by default
        return $this->helper->getDescriptionSettings('min');
    }

    /**
     * Get description max
     *
     * @return string
     */
    public function getDescriptionMax()
    {
        // global settings by default
        return $this->helper->getDescriptionSettings('max');
    }

    /**
     * Get excerpt min
     *
     * @return string
     */
    public function getExcerptMin()
    {
        // global settings by default
        return $this->helper->getExcerptSettings('min');
    }

    /**
     * Get excerpt max
     *
     * @return string
     */
    public function getExcerptMax()
    {
        // global settings by default
        return $this->helper->getExcerptSettings('max');
    }

    /**
     * Get rules
     *
     * @return array
     */
    public function getRules()
    {
        return $this->settings->getSettings('rules');
    }

    /**
     * Get disallowed combinations
     *
     * @return array
     */
    public function getDisallowedCombinations()
    {
        return $this->settings->getSettings('disallowedCombinations');
    }
    
    /**
     * Get text types
     *
     * @return array
     */
    public function getFields()
    {
        $fields = [[
            'value' => 'page_title',
            'label' =>  __('Meta title'),
            'hasTemplate' => true
        ], [
            'value' => 'page_description',
            'label' =>  __('Meta description'),
            'hasTemplate' => false
        ], [
            'value' => 'product_description',
            'label' =>  __('Description'),
            'hasTemplate' => true
        ], [
            'value' => 'short_product_description',
            'label' => __('Short description'),
            'hasTemplate' => true
        ]];

        if ($this->helper->getCustomOpenGraph()) {
            $fields[] = [
                'value' => 'open_graph',
                'label' => __('Open Graph text'),
                'hasTemplate' => false
            ];
        }

        return $fields;
    }

    /**
     * Get fields selected
     *
     * @return array
     */
    public function getFieldsSelected()
    {
        return $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_BULK_GENERATE_FIELDS,
            'product',
            'grid'
        );
    }

    /**
     * Get auto optimize keywords
     *
     * @return bool
     */
    public function getAutoOptimizeKeywords()
    {
        return $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_AUTO_OPTIMIZE_KEYWORDS,
            'product',
            'grid'
        );
    }

    /**
     * Get search intent
     *
     * @return array
     */
    public function getSearchIntent()
    {
        $searchIntent = $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_SEARCH_INTENT,
            'product',
            ''
        );
        if ($searchIntent) {
            $searchIntent = explode(',', $searchIntent);
        } else {
            $searchIntent = explode(',', $this->helper->getKeywordOptimizationSettings('search_intent'));
        }
        return $searchIntent;
    }

    /**
     * Get cluster count
     *
     * @return int
     */
    public function getClusterCount()
    {
        return $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_CLUSTER_COUNT,
            'product',
            'grid'
        );
    }

    /**
     * Get global settings for keyword optimization
     *
     * @param string $path
     * @return string
     */
    public function getKeywordOptimizationSettings($path)
    {
        return $this->helper->getKeywordOptimizationSettings($path);
    }

    /**
     * Get default monitor keywords ranking
     *
     * @return bool
     */
    public function isGlobalMonitorKeywordsRanking()
    {
        $configValue = $this->getKeywordOptimizationSettings('pipeline_keyword/trigger_action');
        if ($configValue === TriggerActions::WHEN_PAGE_IS_RANKING) {
            return true;
        }
        return false;
    }

    /**
     * Get default automatic optimize keywords
     *
     * @return bool
     */
    public function isGlobalAutomaticOptimizeKeywords()
    {
        $configValue = $this->getKeywordOptimizationSettings('automatic_text_optimization');
        if ($configValue === AutomaticTextOptimization::AUTO_REWRITE_AND_QUEUE) {
            return true;
        }
        return false;
    }

    /**
     * Get automatic text optimization options
     *
     * @return array
     */
    public function getAutomaticTextOptimizationOptions()
    {
        return $this->helper->getAutomaticTextOptimizationOptions();
    }

    /**
     * Get automatic text optimization selected
     *
     * @return string
     */
    public function getAutomaticTextOptimizationSelected()
    {
        $userPreference = $this->userFieldsSelected->getUserFieldsSelected(
            UserFieldsSelectedManager::ACTION_TYPE_AUTO_TEXT_OPTIMIZATION,
            'product',
            'grid'
        );

        if ($userPreference) {
            return $userPreference;
        } else {
            $global = $this->getKeywordOptimizationSettings('automatic_text_optimization');
            return $global ? $global : AutomaticTextOptimization::FLAG;
        }
    }

    /**
     * Get template settings
     *
     * @return array
     */
    public function getCurrentTemplateSettings()
    {
        return $this->templateSettings->getCurrentTemplateSettings();
    }

    /**
     * Get template options per field
     *
     * @param string $field
     * @return array
     */
    public function getTemplateOptionPerField($field)
    {
        return $this->templateSettings->getCurrentTemplateSettings($field);
    }

    /**
     * Create block content
     *
     * @param string $template
     * @param string $class
     * @param bool $hasProBadge
     *
     * @return string
     */
    public function createBlockContent(
        $template,
        $class = \Magento\Framework\View\Element\Template::class,
        $hasProBadge = false
    ) {
        $block = $this->layout->createBlock($class)->setTemplate($template);

        if ($hasProBadge) {
            $childBlock = $this->layout->createBlock(\WriteTextAI\WriteTextAI\Block\Adminhtml\Grid\ProBadge::class);
            $block->setChild('wtai.pro.badge', $childBlock);
        }

        return $block->toHtml();
    }

    /**
     * Get trigger actions
     *
     * @return array
     */
    public function getTriggerActions()
    {
        $lowTriggerAction = $this->getKeywordOptimizationSettings('pipeline_keyword/low');
        $lowMidTriggerAction = $this->getKeywordOptimizationSettings('pipeline_keyword/low_mid');
        $midTriggerAction = $this->getKeywordOptimizationSettings('pipeline_keyword/mid');
        $midHighTriggerAction = $this->getKeywordOptimizationSettings('pipeline_keyword/mid_high');
        
        $triggerActions = [
            'low' => $lowTriggerAction,
            'low_mid' => $lowMidTriggerAction,
            'mid' => $midTriggerAction,
            'mid_high' => $midHighTriggerAction
        ];

        return $triggerActions;
    }

    /**
     * Get trigger action page is ranking value string
     *
     * @return string
     */
    public function getTriggerActionPageIsRankingValue()
    {
        return TriggerActions::WHEN_PAGE_IS_RANKING;
    }

    /**
     * Get trigger action after N days value string
     *
     * @return string
     */
    public function getTriggerActionAfterNDaysValue()
    {
        return TriggerActions::AFTER_N_DAYS;
    }

    /**
     * Get trigger action none value string
     *
     * @return string
     */
    public function getTriggerActionNoneValue()
    {
        return TriggerActions::NONE;
    }

    /**
     * Get product texts
     *
     * @return array
     */
    public function getProductFields()
    {
        return $this->productTexts->toOptionArray();
    }

    /**
     * Get global product fields
     *
     * @return array
     */
    public function getGlobalProductFields()
    {
        $selected = $this->helper->getKeywordOptimizationSettings('products');
        if ($selected) {
            return explode(',', $selected);
        }

        return [];
    }

    /**
     * Get default product texts
     *
     * @return array
     */
    public function getDefaultProductTexts()
    {
        $selected = $this->helper->getKeywordOptimizationSettings('products');
        if ($selected) {
            return explode(',', $selected);
        }

        $defaultProductTexts = $this->defaultProductTexts->getDefaultValues();

        return explode(',', $defaultProductTexts);
    }

    /**
     * Format trigger action name for JavaScript binding
     *
     * @param string $triggerAction
     * @return string
     */
    public function formatTriggerActionName($triggerAction)
    {
        return str_replace('_', '', ucwords($triggerAction, '_'));
    }

    /**
     * Returns true if cron is available (running recently)
     *
     * @return bool
     */
    public function isCronRunning(): bool
    {
        return $this->cronStatus->isCronRunning();
    }

    /**
     * Get cron job disabled message
     *
     * @return string
     */
    public function getCronJobDisabledAutoTransferMessage()
    {
        return __('Website cron jobs are currently disabled.'
        . ' The auto-transfer option requires a cron job to function properly.'
        . ' You can still view products with re-generated text and queued for transfer by filtering them in the grid.'
        . ' Please enable cron jobs to ensure proper operation.'
        . ' You may need to contact your hosting provider or developer for assistance.');
    }

    /**
     * Check if AI models are available
     *
     * @return bool
     */
    public function hasAiModels()
    {
        return $this->aiModels->hasAiModels();
    }

    /**
     * Get AI models
     *
     * @return array
     */
    public function getAiModels()
    {
        return $this->aiModels->getAiModels();
    }
}