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

namespace WriteTextAI\WriteTextAI\Model;

use WriteTextAI\WriteTextAI\Model\UserFieldsSelectedFactory;
use WriteTextAI\WriteTextAI\Api\UserFieldsSelectedRepositoryInterface;
use WriteTextAI\WriteTextAI\Model\Api\Session as ApiSession;
use WriteTextAI\WriteTextAI\Helper\Data;

class UserFieldsSelectedManager
{
    public const ACTION_TYPE_HIGHLIGHT_PRONOUNS = 'highlight_pronouns';

    public const ACTION_TYPE_GUIDE_STEPS = 'guide_steps';

    public const ACTION_TYPE_TONES = 'tones';

    public const ACTION_TYPE_STYLE = 'style';

    public const ACTION_TYPE_AUDIENCES = 'audiences';

    public const ACTION_TYPE_CUSTOM_TONE = 'custom_tone';

    public const ACTION_TYPE_CUSTOM_STYLE = 'custom_style';

    public const ACTION_TYPE_CATEGORY_IMAGE = 'category_image';

    public const ACTION_TYPE_THUMBNAIL = 'thumbnail';

    public const ACTION_TYPE_DESC_MIN = 'desc_min';

    public const ACTION_TYPE_DESC_MAX = 'desc_max';

    public const ACTION_TYPE_EXC_MIN = 'exc_min';

    public const ACTION_TYPE_EXC_MAX = 'exc_max';

    public const ACTION_TYPE_AUTO_GENERATE_AFTER_KO = 'auto_generate_after_ko';

    public const ACTION_TYPE_ENABLE_COMPARISON_POPUP = 'enable_comparison_popup';

    public const ACTION_TYPE_SPECIAL_INSTRUCTIONS = 'special_instructions';

    public const ACTION_TYPE_ATTRIBUTES_SELECTED = 'attributes_selected';

    public const ACTION_TYPE_AUTO_OPTIMIZE_KEYWORDS = 'auto_optimize_keywords';

    public const ACTION_TYPE_AUTO_TEXT_OPTIMIZATION = 'automatic_text_optimization';

    public const ACTION_TYPE_SEARCH_INTENT = 'search_intent';

    public const ACTION_TYPE_CLUSTER_COUNT = 'cluster_count';

    public const ACTION_TYPE_CLUSTER_COUNT_CATEGORY = 'cluster_count_category';

    public const ACTION_TYPE_BULK_GENERATE_FIELDS = 'generate';

    public const ACTION_TYPE_BULK_TRANSFER_FIELDS = 'transfer';

    public const ACTION_TYPE_SINGLE_EDITOR_FIELDS = 'single_editor';

    public const ACTION_TYPE_BULK_FULL_AUTOMATION_FIELDS = 'full_automation';

    public const ACTION_TYPE_GALLERY = 'gallery'; // alt text images select all checkbox

    public const ACTION_TYPE_PRODUCT_RESEARCH_DATA = 'wtai_product_research_data';
    
    public const ACTION_TYPE_REVIEW_NOTICE_DISMISSED = 'review_notice_dismissed';

    public const ACTION_TYPE_INVALID_IMAGE_POPUP_DO_NOT_SHOW_AGAIN = 'invalid_image_popup_do_not_show_again';

    /**
     * @var UserFieldsSelectedFactory
     */
    protected $userFieldsSelectedFactory;

    /**
     * @var UserFieldsSelectedRepositoryInterface
     */
    protected $userFieldsSelectedRepository;

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

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

    /**
     * Constructor
     *
     * @param UserFieldsSelectedFactory $userFieldsSelectedFactory
     * @param UserFieldsSelectedRepositoryInterface $userFieldsSelectedRepository
     * @param ApiSession $apiSession
     * @param Data $helper
     */
    public function __construct(
        UserFieldsSelectedFactory $userFieldsSelectedFactory,
        UserFieldsSelectedRepositoryInterface $userFieldsSelectedRepository,
        ApiSession $apiSession,
        Data $helper
    ) {
        $this->userFieldsSelectedFactory = $userFieldsSelectedFactory;
        $this->userFieldsSelectedRepository = $userFieldsSelectedRepository;
        $this->apiSession = $apiSession;
        $this->helper = $helper;
    }

    /**
     * Check if user preference exists
     *
     * @param string $field
     * @param string $entityType
     * @param string $scope
     *
     * @return array
     */
    public function checkUserFieldsSelected(
        $field,
        $entityType,
        $scope = null
    ) {
        $userId = $this->getUser()->getId();

        $userFieldsSelected = $this->userFieldsSelectedFactory->create();

        $userFieldsSelected = $userFieldsSelected->getCollection()
            ->addFieldToFilter('user_id', $userId)
            ->addFieldToFilter('field', $field);
        if ($entityType) {
            $userFieldsSelected->addFieldToFilter('entity_type', $entityType);
        }
        if ($scope) {
            $userFieldsSelected->addFieldToFilter('scope', $scope);
        }
        $userFieldsSelected = $userFieldsSelected->getFirstItem();

        if ($userFieldsSelected->getId()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Get user's last text types selected
     *
     * @param string $field
     * @param string $entityType
     * @param string $scope
     *
     * @return array
     */
    public function getUserFieldsSelected($field, $entityType, $scope)
    {
        $userId = $this->getUser()->getId();

        $userFieldsSelected = $this->userFieldsSelectedFactory->create();

        $userFieldsSelected = $userFieldsSelected->getCollection()
            ->addFieldToFilter('user_id', $userId)
            ->addFieldToFilter('field', $field);
        if ($entityType) {
            $userFieldsSelected->addFieldToFilter('entity_type', $entityType);
        }
        if ($scope) {
            $userFieldsSelected->addFieldToFilter('scope', $scope);
        }
        $userFieldsSelected = $userFieldsSelected->getFirstItem();
        
        if ($userFieldsSelected->getId()) {
            return $this->formatValue($field, (string)$userFieldsSelected->getValue());
        } else {
            return $this->getDefaultValue($field, $entityType);
        }
    }

    /**
     * Format value
     *
     * @param string $field
     * @param string $value
     *
     * @return mixed
     */
    protected function formatValue($field, $value)
    {
        switch ($field) {
            case self::ACTION_TYPE_TONES:
            case self::ACTION_TYPE_AUDIENCES:
            case self::ACTION_TYPE_ATTRIBUTES_SELECTED:
                if (!$value) {
                    return [];
                }
                $items = array_map('trim', explode(",", (string) $value));
                return array_values(array_filter($items, static fn ($item) => $item !== ''));
            case self::ACTION_TYPE_SINGLE_EDITOR_FIELDS:
            case self::ACTION_TYPE_BULK_GENERATE_FIELDS:
            case self::ACTION_TYPE_BULK_FULL_AUTOMATION_FIELDS:
            case self::ACTION_TYPE_BULK_TRANSFER_FIELDS:
                if (!$value) {
                    return [];
                }
                $arrayValue = array_map('trim', explode(",", (string) $value));
                $arrayValue = array_values(array_filter($arrayValue, static fn ($item) => $item !== ''));
                /**
                 * If custom open graph is disabled, remove open graph from the selected fields
                 */
                if (!$this->helper->getCustomOpenGraph()) {
                    foreach (array_keys($arrayValue, 'open_graph', true) as $key) {
                        unset($arrayValue[$key]);
                    }
                }
                return $arrayValue;
            default:
                return $value;
        }
    }

    /**
     * Get default value
     *
     * @param string $field
     * @param string $entityType
     *
     * @return mixed
     */
    protected function getDefaultValue($field, $entityType)
    {
        switch ($field) {
            case self::ACTION_TYPE_SEARCH_INTENT:
                if ($entityType === 'product') {
                    return "transactional";
                } elseif ($entityType === 'category') {
                    return "commercial";
                }
                return "transactional";
            case self::ACTION_TYPE_CLUSTER_COUNT:
                return $this->helper->getKeywordOptimizationSettings('cluster_based_pipelines_count');
            case self::ACTION_TYPE_CLUSTER_COUNT_CATEGORY:
                return $this->helper->getKeywordOptimizationSettings('cluster_based_pipelines_count_category');
            case self::ACTION_TYPE_THUMBNAIL:
                $defaultProductAttributes = $this->helper->getAttributesSettings('attributes');
                if ($defaultProductAttributes) {
                    $selectedAttributes = explode(",", (string) $defaultProductAttributes);
                    if (in_array('thumbnail', $selectedAttributes)) {
                        return "true";
                    }
                }
                return "false";
            case self::ACTION_TYPE_PRODUCT_RESEARCH_DATA:
                $defaultProductAttributes = $this->helper->getAttributesSettings('attributes');
                if ($defaultProductAttributes) {
                    $selectedAttributes = explode(",", (string) $defaultProductAttributes);
                    if (in_array(self::ACTION_TYPE_PRODUCT_RESEARCH_DATA, $selectedAttributes)) {
                        return "true";
                    }
                }
                return "false";
            case self::ACTION_TYPE_ENABLE_COMPARISON_POPUP:
            case self::ACTION_TYPE_AUTO_OPTIMIZE_KEYWORDS:
            case self::ACTION_TYPE_AUTO_GENERATE_AFTER_KO:
            case self::ACTION_TYPE_REVIEW_NOTICE_DISMISSED:
            case self::ACTION_TYPE_INVALID_IMAGE_POPUP_DO_NOT_SHOW_AGAIN:
                return "false";
            case self::ACTION_TYPE_CATEGORY_IMAGE:
            case self::ACTION_TYPE_GALLERY:
            case self::ACTION_TYPE_HIGHLIGHT_PRONOUNS:
                return "true";
            case self::ACTION_TYPE_TONES:
            case self::ACTION_TYPE_AUDIENCES:
                return [];
            case self::ACTION_TYPE_ATTRIBUTES_SELECTED:
                $defaultProductAttributes = $this->helper->getAttributesSettings('attributes');
                if ($defaultProductAttributes) {
                    $selectedAttributes = explode(",", (string) $defaultProductAttributes);
                    return $selectedAttributes;
                }
                return [];
            case self::ACTION_TYPE_GUIDE_STEPS:
                return false;
            case self::ACTION_TYPE_BULK_GENERATE_FIELDS:
            case self::ACTION_TYPE_BULK_FULL_AUTOMATION_FIELDS:
            case self::ACTION_TYPE_BULK_TRANSFER_FIELDS:
                return $this->getDefaultSelectedFields($entityType);
            case self::ACTION_TYPE_SINGLE_EDITOR_FIELDS:
                if ($entityType == 'category') {
                    $fields = [
                        'page_title',
                        'page_description',
                        'category_description'
                    ];
                } else {
                    $fields = [
                        'page_title',
                        'page_description',
                        'product_description',
                        'short_product_description'
                    ];
                    if ($this->helper->getCustomOpenGraph()) {
                        $fields[] = 'open_graph';
                    }
                }
                return $fields;
            default:
                return '';
        }
    }
    
    /**
     * Get default selected fields
     *
     * @param string $entityType
     *
     * @return array
     */
    public function getDefaultSelectedFields($entityType = 'product')
    {
        if ($entityType === 'category') {
            return [
                'page_title',
                'page_description',
                'category_description'
            ];
        }

        $fields = [
            'page_title',
            'page_description',
            'product_description',
            'short_product_description',
            'alt_text'
        ];

        if ($this->helper->getCustomOpenGraph()) {
            $fields[] = 'open_graph';
        }

        return $fields;
    }

    /**
     * Save user fields selected
     *
     * @param array $value
     * @param string $field
     * @param string $entityType
     * @param string $scope
     *
     * @return void
     */
    public function saveUserFieldsSelected($value, $field, $entityType, $scope)
    {
        $userId = $this->getUser()->getId();

        $userFieldsSelected = $this->userFieldsSelectedFactory->create();

        $existing = $userFieldsSelected->getCollection()
            ->addFieldToFilter('user_id', $userId)
            ->addFieldToFilter('field', $field);
        if ($entityType) {
            $existing->addFieldToFilter('entity_type', $entityType);
        }
        if ($scope) {
            $existing->addFieldToFilter('scope', $scope);
        }
        $existing = $existing->getFirstItem();

        if (is_array($value) &&
            in_array($field, [
                self::ACTION_TYPE_TONES,
                self::ACTION_TYPE_AUDIENCES,
                self::ACTION_TYPE_SINGLE_EDITOR_FIELDS,
                self::ACTION_TYPE_BULK_GENERATE_FIELDS,
                self::ACTION_TYPE_BULK_FULL_AUTOMATION_FIELDS,
                self::ACTION_TYPE_BULK_TRANSFER_FIELDS,
                self::ACTION_TYPE_ATTRIBUTES_SELECTED
            ])
        ) {
            $value = implode(",", $value);
        }

        if ($existing->getId()) {
            // Update the existing record
            $existing->setValue($value);
            $userFieldsSelected = $existing;
        } else {
            // Record not found, create a new one
            $userFieldsSelected->setData([
                "user_id" => $userId,
                "value" => $value,
                "field" => $field,
                "entity_type" => $entityType,
                "scope" => $scope
            ]);
        }

        $this->userFieldsSelectedRepository->save($userFieldsSelected);
    }

    /**
     * Get current user
     *
     * @return \Magento\User\Model\User
     */
    private function getUser()
    {
        return $this->apiSession->getCurrentUser();
    }

    /**
     * Delete all settings of current user per type
     *
     * @param string $entityType
     * @return void
     */
    public function deleteAllPerType($entityType)
    {
        $userId = $this->getUser()->getId();

        $userFieldsSelected = $this->userFieldsSelectedFactory->create();

        $userFieldsSelected->getCollection()
            ->addFieldToFilter('user_id', $userId)
            // include empty entity type to delete shared settings
            ->addFieldToFilter('entity_type', [
                ['eq' => $entityType],
                ['null' => true],
                ['eq' => '']
            ])
            // exclude grid scope to delete edit and shared settings
            ->addFieldToFilter('scope', [
                ['eq' => 'edit'],
                ['null' => true],
                ['eq' => '']
            ])
            ->walk('delete');
    }

    /**
     * Delete grid settings of current user
     *
     * @param string $entityType
     * @return void
     */
    public function deleteGridSettings($entityType)
    {
        $userId = $this->getUser()->getId();

        $userFieldsSelected = $this->userFieldsSelectedFactory->create();
        $userFieldsSelected->getCollection()
            ->addFieldToFilter('user_id', $userId)
            // include empty entity type to delete shared settings
            ->addFieldToFilter('entity_type', [
                ['eq' => $entityType],
                ['null' => true],
                ['eq' => '']
            ])
            // exclude edit scope to delete grid and shared settings
            ->addFieldToFilter('scope', [
                ['eq' => 'grid'],
                ['null' => true],
                ['eq' => '']
            ])
            ->walk('delete');

        $customToneAndStyle = $this->userFieldsSelectedFactory->create();
        $customToneAndStyle->getCollection()
            ->addFieldToFilter('user_id', $userId)
            ->addFieldToFilter('field', [
                'custom_tone',
                'custom_style'
            ])
            ->walk('delete');

        $tonesAndStyle = $this->userFieldsSelectedFactory->create();
        $tonesAndStyle->getCollection()
            ->addFieldToFilter('user_id', $userId)
            ->addFieldToFilter('field', [
                'tones',
                'style'
            ])
            ->addFieldToFilter('scope', 'edit')
            ->addFieldToFilter('entity_type', [
                ['null' => true],
                ['eq' => '']
            ])
            ->walk('delete');
    }

    /**
     * Delete specific settings of current user per type
     *
     * @param string $entityType
     * @param string $field
     * @param string $scope
     * @return void
     */
    public function deleteSpecificSettings($entityType, $field, $scope)
    {
        $userId = $this->getUser()->getId();

        $userFieldsSelected = $this->userFieldsSelectedFactory->create();

        $userFieldsSelected->getCollection()
            ->addFieldToFilter('user_id', $userId)
            ->addFieldToFilter('entity_type', $entityType)
            ->addFieldToFilter('scope', $scope)
            ->addFieldToFilter('field', $field)
            ->walk('delete');
    }
}
