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

namespace WriteTextAI\WriteTextAI\Model\Categories;

use WriteTextAI\WriteTextAI\Model\ApiManager;
use WriteTextAI\WriteTextAI\Model\OptionSource\Filter\Fields;
use WriteTextAI\WriteTextAI\Helper\Store as StoreHelper;
use WriteTextAI\WriteTextAI\Model\GeneratedText as ProductGeneratedText;
use WriteTextAI\WriteTextAI\Helper\Categories\Fields as FieldsHelper;
use WriteTextAI\WriteTextAI\Model\UserFeedbackManager;

class GeneratedText extends ProductGeneratedText
{
    /**
     * @var ApiManager
     */
    protected $apiManager;

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

    /**
     * @var FieldsHelper
     */
    protected $fieldsHelper;

    /**
     * @var UserFeedbackManager
     */
    protected $userFeedbackManager;

    /**
     * Constructor
     *
     * @param ApiManager $apiManager
     * @param StoreHelper $storeHelper
     * @param FieldsHelper $fieldsHelper
     * @param UserFeedbackManager $userFeedbackManager
     */
    public function __construct(
        ApiManager $apiManager,
        StoreHelper $storeHelper,
        FieldsHelper $fieldsHelper,
        UserFeedbackManager $userFeedbackManager
    ) {
        $this->apiManager = $apiManager;
        $this->storeHelper = $storeHelper;
        $this->fieldsHelper = $fieldsHelper;
        $this->userFeedbackManager = $userFeedbackManager;

        parent::__construct(
            $apiManager,
            $storeHelper,
            $userFeedbackManager
        );
    }

    /**
     * Process generated text by store id
     *
     * @param string $ids
     * @param int $storeId
     * @param bool $isTransfer
     * @param array $text
     * @return mixed[]
     */
    public function getGeneratedByStoreId($ids, $storeId, $isTransfer = false, $text = [])
    {
        $response = !empty($text) ? $text : $this->getGenerated($ids, $storeId, 'Category');

        $generated = [];

        if (!isset($response['records'])) {
            return $generated;
        }

        foreach ($response['records'] as $record) {
            foreach ($record['stores'] as $store) {
                if ($store['storeId'] == $storeId) {
                    $generatedValue = $this->getGeneratedValue($store);

                    if ($isTransfer) {
                        $history = $this->getTextHistory($store);
                        $transferred = isset($history['publish']) && isset($history['reviewed']) ? (
                            $history['publish'] && $history['reviewed'] ? true : false
                        ) : false;
                        $generated[$record['recordId']]['status'][$store['field']] = $transferred;
                    }
                    
                    if ($generatedValue !== null) {
                        $generated[$record['recordId']][$store['field']] = $generatedValue;
                    }
                }
            }
        }

        return $generated;
    }

    /**
     * Get text fields
     *
     * @param int $id
     * @param int $storeId
     * @param bool $isTransfer
     * @param array $text
     * @return array
     */
    public function getTextFields($id, $storeId, $isTransfer = false, $text = [])
    {
        $mappingSettings = $this->fieldsHelper->getMappingSettings();
        $generated = $this->getGeneratedByStoreId($id, $storeId, $isTransfer, $text);
        $result = [
            'status' => []
        ];
        foreach ($mappingSettings as $key => $field) {
            $result[$key] = $generated[$id][Fields::CATEGORY_MAPPING[$key]] ?? '';
            $result['status'][$key] = $generated[$id]['status'][Fields::CATEGORY_MAPPING[$key]] ?? false;
        }

        return $result;
    }

    /**
     * Extract fields from generated data
     *
     * @param array $generated
     * @param string $key
     * @return array
     */
    protected function extractFieldsFromGenerated($generated, $key)
    {
        if (empty($generated) || !isset($generated['records']) ||
            empty($generated['records']) || !isset($generated['records'][0]['stores'])
        ) {
            return [];
        }

        $fields = [];
        foreach ($generated['records'][0]['stores'] as $field) {
            if (isset($field['texts'][0][$key])) {
                $fields[$field['field']] = $field['texts'][0][$key];
            }
        }

        return $fields;
    }

    /**
     * Get text fields template
     *
     * @param int $categoryId
     * @param int $storeId
     * @param array $text
     * @return array
     */
    public function getTextFieldsTemplate($categoryId, $storeId, $text = [])
    {
        $fieldsTemplate = $this->extractFieldsFromGenerated($text, 'templateId');
        if ($fieldsTemplate) {
            return [
                'category_page_title' => $fieldsTemplate[Fields::CATEGORY_PAGE_TITLE] ?? '',
                'category_description' => $fieldsTemplate[Fields::CATEGORY_DESCRIPTION] ?? ''
            ];
        }

        return [
            'category_page_title' => '',
            'category_description' => ''
        ];
    }

    /**
     * Get text fields model
     *
     * @param int $categoryId
     * @param int $storeId
     * @param array $text
     * @return array
     */
    public function getTextFieldsModel($categoryId, $storeId, $text = [])
    {
        $fieldsModel = $this->extractFieldsFromGenerated($text, 'modelId');
        if ($fieldsModel) {
            return [
                'category_page_title' => $fieldsModel[Fields::CATEGORY_PAGE_TITLE] ?? '',
                'category_page_description' => $fieldsModel[Fields::CATEGORY_PAGE_DESCRIPTION] ?? '',
                'category_description' => $fieldsModel[Fields::CATEGORY_DESCRIPTION] ?? ''
            ];
        }

        return [
            'category_page_title' => '',
            'category_page_description' => '',
            'category_description' => ''
        ];
    }

    /**
     * Get text fields date
     *
     * @param int $categoryId
     * @param int $storeId
     * @param array $text
     * @return array
     */
    public function getTextFieldsDate($categoryId, $storeId, $text = [])
    {
        $fieldsDate = $this->extractFieldsFromGenerated($text, 'date');
        if ($fieldsDate) {
            return [
                'category_page_title' => $fieldsDate[Fields::CATEGORY_PAGE_TITLE] ?? '',
                'category_page_description' => $fieldsDate[Fields::CATEGORY_PAGE_DESCRIPTION] ?? '',
                'category_description' => $fieldsDate[Fields::CATEGORY_DESCRIPTION] ?? ''
            ];
        }

        return [
            'category_page_title' => '',
            'category_page_description' => '',
            'category_description' => ''
        ];
    }

    /**
     * Get text fields statuses
     *
     * @param int $categoryId
     * @param int $storeId
     * @param array $generated
     * @return array
     */
    public function getTextFieldsStatuses($categoryId, $storeId, $generated = [])
    {
        if (!empty($generated) &&
            isset($generated['records']) &&
            !empty($generated['records']) &&
            isset($generated['records'][0]['stores'])
        ) {
            foreach ($generated['records'][0]['stores'] as $field) {
                $fieldTexts = $field['texts'] ?? [];
                $fieldTextsFirstHistory = $fieldTexts[0]['history'][0]['publish'] ?? false;
                $statuses['generated'][$field['field']] = !empty($fieldTexts);
                $statuses['transferred'][$field['field']] = !empty($fieldTexts) ? $fieldTextsFirstHistory : false;
            }
            
            $result = [];
            
            foreach (Fields::CATEGORY_MAPPING as $key => $field) {
                foreach (Fields::STATUSES as $status) {
                    $result["{$key}_{$status}"] = $statuses[$status][$field] ?? false;
                }
            }
            
            return $result;
        }

        $history = $this->getHistory($categoryId, $storeId);
        
        $result = [];

        foreach (Fields::CATEGORY_MAPPING as $key => $field) {
            foreach (Fields::STATUS_MAPPING as $statusKey => $statusValue) {
                $result["{$key}_{$statusKey}"] = $this->getFieldStatus($history, $field, $statusValue);
            }
        }
        
        return $result;
    }

    /**
     * Get texts feedback
     *
     * @param array $generated
     * @return array
     */
    public function getTextsFeedback($generated = [])
    {
        $mapping = [
            Fields::CATEGORY_PAGE_TITLE => 'page_title',
            Fields::CATEGORY_PAGE_DESCRIPTION => 'page_description',
            Fields::CATEGORY_DESCRIPTION => 'category_description'
        ];

        if (!empty($generated) &&
            isset($generated['records']) &&
            !empty($generated['records']) &&
            isset($generated['records'][0]['stores'])
        ) {
            $feedback = [];
            foreach ($generated['records'][0]['stores'] as $field) {
                $fieldTexts = $field['texts'] ?? [];
                if (isset($mapping[$field['field']])) {
                    $feedback[$mapping[$field['field']]] = $fieldTexts[0]['feedback'] ?? [];
                }
            }
            return $feedback;
        }

        return [];
    }

    /**
     * Save text
     *
     * @param int $storeId
     * @param int $categoryId
     * @param array $selectedFields
     * @param bool $transfer
     * @param bool $isReviewed
     * @param bool $isAutomatic
     *
     * @return void
     */
    public function saveCategoryText(
        $storeId,
        $categoryId,
        $selectedFields,
        $transfer = true,
        $isReviewed = true,
        $isAutomatic = false
    ) {
        $ids = $this->getTextIds($categoryId, $storeId);

        $fields = [];
        foreach ($selectedFields as $field => $value) {
            if (isset($ids[$field]) && !empty($value)) {
                $fields[] = [
                    "textId" => $ids[$field],
                    "field" => Fields::CATEGORY_MAPPING[$field],
                    "value" => $value,
                    "publish" => $transfer,
                    "reviewed" => $isReviewed,
                    "isAutomatic" => $isAutomatic,
                    "platform" => "Magento"
                ];
            }
        }

        $language = $this->storeHelper->getFormattedLanguage($storeId);

        $params = [
            'type' => 'Category',
            'language' => $language,
            'recordId' => $categoryId,
            'storeId' => $storeId,
            'fields' => $fields
        ];

        if (!empty($fields)) {
            $this->apiManager->save($params);
        }
    }
    
    /**
     * Get text ids
     *
     * @param int $categoryId
     * @param int $storeId
     * @return array
     */
    public function getTextIds($categoryId, $storeId)
    {
        $item = [];
        
        $generated = $this->getTextIdsFromGenerated($categoryId, $storeId, 'Category');

        if (isset($generated[$categoryId])) {
            foreach (Fields::CATEGORY_MAPPING as $key => $field) {
                if (isset($generated[$categoryId][$field])) {
                    $item[$key] = $generated[$categoryId][$field];
                }
            }
        }

        return $item;
    }

    /**
     * Get texts keywords used
     *
     * @param array $generated
     * @return array
     */
    public function getTextsKeywordsUsed($generated = [])
    {
        $mapping = [
            Fields::CATEGORY_PAGE_TITLE => 'page_title',
            Fields::CATEGORY_PAGE_DESCRIPTION => 'page_description',
            Fields::CATEGORY_DESCRIPTION => 'category_description'
        ];

        if (!empty($generated) &&
            isset($generated['records']) &&
            !empty($generated['records']) &&
            isset($generated['records'][0]['stores'])
        ) {
            $keywords = [];
            foreach ($generated['records'][0]['stores'] as $field) {
                $fieldTexts = $field['texts'] ?? [];
                if (isset($fieldTexts[0]['keywords'])) {
                    $keywords[$mapping[$field['field']]] = $fieldTexts[0]['keywords'] ?? [];
                }
            }
            return $keywords;
        }

        return [];
    }
}
