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

namespace WriteTextAI\WriteTextAI\Controller\Adminhtml\Edit;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Filter\FilterManager;
use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress;
use Magento\Framework\Escaper;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\StoreManagerInterface;
use WriteTextAI\WriteTextAI\Helper\Data;
use WriteTextAI\WriteTextAI\Helper\Html;
use WriteTextAI\WriteTextAI\Helper\Image;
use WriteTextAI\WriteTextAI\Helper\Generate as GenerateHelper;
use WriteTextAI\WriteTextAI\Helper\Product as ProductHelper;
use WriteTextAI\WriteTextAI\Model\ApiManager;
use WriteTextAI\WriteTextAI\Model\OptionSource\Filter\Fields;
use WriteTextAI\WriteTextAI\Model\GeneratedText;
use WriteTextAI\WriteTextAI\Model\AiProductManager;
use Magento\Backend\Model\UrlInterface;
use Magento\Catalog\Model\Product\Attribute\Source\Status as ProductStatus;
use WriteTextAI\WriteTextAI\ViewModel\Settings;
use Magento\Catalog\Helper\Output as OutputHelper;
use WriteTextAI\WriteTextAI\Model\MarkReview;
use WriteTextAI\WriteTextAI\Helper\Store as StoreHelper;
use WriteTextAI\WriteTextAI\Model\Api\Keywords;
use WriteTextAI\WriteTextAI\Model\KeywordIdeaFiltersManager;
use WriteTextAI\WriteTextAI\Model\Config\Source\AutomaticTextOptimization;
use WriteTextAI\WriteTextAI\Model\SingleGenerateRequestsManager;
use WriteTextAI\WriteTextAI\Model\Api\Session as ApiSession;
use Magento\Catalog\Helper\Image as MagentoImageHelper;
use WriteTextAI\WriteTextAI\Helper\Fields as FieldHelper;
use WriteTextAI\WriteTextAI\Model\Config\Source\ProductAttributes;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable as ConfigurableType;
use Magento\GroupedProduct\Model\Product\Type\Grouped as GroupedType;
use Magento\Bundle\Model\Product\Type as BundleType;

class Generate extends Action
{
    public const ADMIN_RESOURCE = 'WriteTextAI_WriteTextAI::generate';

    /**
     * @var ApiManager
     */
    protected $apiManager;

    /**
     * @var RemoteAddress
     */
    protected $remoteAddress;

    /**
     * @var ScopeConfigInterface
     */
    protected $scopeConfig;

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

    /**
     * @var ProductRepositoryInterface
     */
    protected $productRepository;

    /**
     * @var GeneratedText
     */
    protected $generatedText;

    /**
     * @var AiProductManager
     */
    protected $aiProductManager;

    /**
     * @var Html
     */
    protected $htmlHelper;

    /**
     * @var Image
     */
    protected $imageHelper;

    /**
     * @var GenerateHelper
     */
    protected $generateHelper;

    /**
     * @var ProductHelper
     */
    protected $productHelper;

    /**
     * @var FilterManager
     */
    protected $filterManager;

    /**
     * @var Escaper
     */
    protected $escaper;

    /**
     * @var UrlInterface
     */
    protected $urlBuilder;

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

    /**
     * @var OutputHelper
     */
    protected $outputHelper;

    /**
     * @var MarkReview
     */
    protected $markReview;

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

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

    /**
     * @var KeywordIdeaFiltersManager
     */
    protected $keywordIdeaFiltersManager;

    /**
     * @var SingleGenerateRequestsManager
     */
    protected $singleGenerateRequestsManager;

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

    /**
     * @var MagentoImageHelper
     */
    protected $magentoImageHelper;

    /**
     * @var FieldHelper
     */
    protected $fieldHelper;

    /**
     * @var ConfigurableType
     */
    protected $configurableType;

    /**
     * @var GroupedType
     */
    protected $groupedType;

    /**
     * @var BundleType
     */
    protected $bundleType;

    /**
     * @var CategoryCollectionFactory
     */
    protected $categoryCollectionFactory;

    /**
     * @var StoreManagerInterface
     */
    protected $storeManager;

    /**
     * Constructor
     *
     * @param Context $context
     * @param ApiManager $apiManager
     * @param RemoteAddress $remoteAddress
     * @param ScopeConfigInterface $scopeConfig
     * @param Data $helper
     * @param ProductRepositoryInterface $productRepository
     * @param GeneratedText $generatedText
     * @param AiProductManager $aiProductManager
     * @param Html $htmlHelper
     * @param Image $imageHelper
     * @param GenerateHelper $generateHelper
     * @param ProductHelper $productHelper
     * @param FilterManager $filterManager
     * @param Escaper $escaper
     * @param UrlInterface $urlBuilder
     * @param Settings $settings
     * @param OutputHelper $outputHelper
     * @param MarkReview $markReview
     * @param StoreHelper $storeHelper
     * @param Keywords $keywords
     * @param KeywordIdeaFiltersManager $keywordIdeaFiltersManager
     * @param SingleGenerateRequestsManager $singleGenerateRequestsManager
     * @param ApiSession $apiSession
     * @param MagentoImageHelper $magentoImageHelper
     * @param FieldHelper $fieldHelper
     * @param ConfigurableType $configurableType
     * @param GroupedType $groupedType
     * @param BundleType $bundleType
     * @param CategoryCollectionFactory $categoryCollectionFactory
     * @param StoreManagerInterface $storeManager
     */
    public function __construct(
        Context $context,
        ApiManager $apiManager,
        RemoteAddress $remoteAddress,
        ScopeConfigInterface $scopeConfig,
        Data $helper,
        ProductRepositoryInterface $productRepository,
        GeneratedText $generatedText,
        AiProductManager $aiProductManager,
        Html $htmlHelper,
        Image $imageHelper,
        GenerateHelper $generateHelper,
        ProductHelper $productHelper,
        FilterManager $filterManager,
        Escaper $escaper,
        UrlInterface $urlBuilder,
        Settings $settings,
        OutputHelper $outputHelper,
        MarkReview $markReview,
        StoreHelper $storeHelper,
        Keywords $keywords,
        KeywordIdeaFiltersManager $keywordIdeaFiltersManager,
        SingleGenerateRequestsManager $singleGenerateRequestsManager,
        ApiSession $apiSession,
        MagentoImageHelper $magentoImageHelper,
        FieldHelper $fieldHelper,
        ConfigurableType $configurableType,
        GroupedType $groupedType,
        BundleType $bundleType,
        CategoryCollectionFactory $categoryCollectionFactory,
        StoreManagerInterface $storeManager
    ) {
        $this->apiManager = $apiManager;
        $this->remoteAddress = $remoteAddress;
        $this->scopeConfig = $scopeConfig;
        $this->helper = $helper;
        $this->productRepository = $productRepository;
        $this->generatedText = $generatedText;
        $this->aiProductManager = $aiProductManager;
        $this->htmlHelper = $htmlHelper;
        $this->imageHelper = $imageHelper;
        $this->generateHelper = $generateHelper;
        $this->productHelper = $productHelper;
        $this->filterManager = $filterManager;
        $this->escaper = $escaper;
        $this->urlBuilder = $urlBuilder;
        $this->settings = $settings;
        $this->outputHelper = $outputHelper;
        $this->markReview = $markReview;
        $this->storeHelper = $storeHelper;
        $this->keywords = $keywords;
        $this->keywordIdeaFiltersManager = $keywordIdeaFiltersManager;
        $this->singleGenerateRequestsManager = $singleGenerateRequestsManager;
        $this->apiSession = $apiSession;
        $this->magentoImageHelper = $magentoImageHelper;
        $this->fieldHelper = $fieldHelper;
        $this->configurableType = $configurableType;
        $this->groupedType = $groupedType;
        $this->bundleType = $bundleType;
        $this->categoryCollectionFactory = $categoryCollectionFactory;
        $this->storeManager = $storeManager;
        parent::__construct($context);
    }

    /**
     * Get child skus for supported composite product types
     *
     * @param \Magento\Catalog\Model\Product $product
     * @return array
     */
    private function getChildProductName($product)
    {
        $typeId = (string)$product->getTypeId();
        $childProducts = [];

        try {
            if ($typeId === 'configurable') {
                $children = $this->configurableType->getUsedProducts($product);
                foreach ($children as $child) {
                    if ((int)$child->getStatus() === ProductStatus::STATUS_DISABLED) {
                        continue;
                    }
                    $productId = (int) $child->getId();
                    $productName = (string) $child->getName();
                    if ($productId && $productName) {
                        $childProducts[$productId] = [
                            'id' => (string) $productId,
                            'name' => $productName
                        ];
                    }
                }
            } elseif ($typeId === 'grouped') {
                $children = $this->groupedType->getAssociatedProducts($product);
                foreach ($children as $child) {
                    if ((int)$child->getStatus() === ProductStatus::STATUS_DISABLED) {
                        continue;
                    }
                    $productId = (int) $child->getId();
                    $productName = (string) $child->getName();
                    if ($productId && $productName) {
                        $childProducts[$productId] = [
                            'id' => (string) $productId,
                            'name' => $productName
                        ];
                    }
                }
            } elseif ($typeId === 'bundle') {
                $optionIds = $this->bundleType->getOptionsIds($product);
                $selections = $this->bundleType->getSelectionsCollection($optionIds, $product);
                foreach ($selections as $child) {
                    if ((int)$child->getStatus() === ProductStatus::STATUS_DISABLED) {
                        continue;
                    }
                    $productId = (int) $child->getId();
                    $productName = (string) $child->getName();
                    if ($productId && $productName) {
                        $childProducts[$productId] = [
                            'id' => (string) $productId,
                            'name' => $productName
                        ];
                    }
                }
            }
        } catch (\Exception $e) {
            return [];
        }

        return array_values($childProducts);
    }

    /**
     * Is virtual and/or downloadable
     *
     * @param string $type
     * @return array{isVirtual: bool, isDownloadable: bool}
     */
    private function getVirtualDownloadableFlags($type)
    {
        $typeId = (string)$type;
        $isVirtual = ($typeId === 'virtual');
        $isDownloadable = ($typeId === 'downloadable');

        if ($isDownloadable) {
            return ['isVirtual' =>true, 'isDownloadable' => $isDownloadable];
        }

        return ['isVirtual' => $isVirtual, 'isDownloadable' => $isDownloadable];
    }

    /**
     * Get product category paths
     *
     * @param \Magento\Catalog\Api\Data\ProductInterface $product
     * @param int $storeId
     * @return array
     */
    private function getProductCategoryPaths($product, int $storeId): array
    {
        try {
            $categoryIds = $product->getCategoryIds();
            if (!is_array($categoryIds) || empty($categoryIds)) {
                return [];
            }

            $rootCategoryId = null;
            try {
                $rootCategoryId = (int) $this->storeManager->getStore($storeId)->getRootCategoryId();
            } catch (\Exception $e) {
                $rootCategoryId = null;
            }

            $collection = $this->categoryCollectionFactory->create();
            $collection->setStoreId($storeId);
            $collection->addAttributeToSelect(['name', 'path']);
            $collection->addFieldToFilter('entity_id', ['in' => $categoryIds]);

            $allPathIds = [];
            $categoryPathIdsByCategoryId = [];
            foreach ($collection as $category) {
                $pathIds = $category->getPathIds();
                $filteredPathIds = [];
                foreach ($pathIds as $pathId) {
                    $pathId = (int) $pathId;
                    if ($pathId <= 2) {
                        continue;
                    }
                    if ($rootCategoryId !== null && $pathId === $rootCategoryId) {
                        continue;
                    }
                    $filteredPathIds[] = $pathId;
                    $allPathIds[$pathId] = true;
                }
                $categoryPathIdsByCategoryId[(int) $category->getId()] = $filteredPathIds;
            }

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

            $allCategoriesCollection = $this->categoryCollectionFactory->create();
            $allCategoriesCollection->setStoreId($storeId);
            $allCategoriesCollection->addAttributeToSelect(['name']);
            $allCategoriesCollection->addFieldToFilter('entity_id', ['in' => array_keys($allPathIds)]);

            $nameLookup = [];
            foreach ($allCategoriesCollection as $category) {
                $nameLookup[(int) $category->getId()] = (string) $category->getName();
            }

            $paths = [];
            foreach ($categoryPathIdsByCategoryId as $categoryId => $pathIds) {
                $pathData = [];
                $pathNames = [];
                // Only include parent categories, not the current category
                foreach ($pathIds as $pathId) {
                    if (isset($nameLookup[$pathId]) && $nameLookup[$pathId] !== '') {
                        $pathNames[] = $nameLookup[$pathId];
                    }
                }
                
                // Create a single entry with the full path
                if (!empty($pathNames)) {
                    $categoryName = array_pop($pathNames);
       
                    $fullPath = implode('/', $pathNames);
                    $paths[] = [
                        'id' => (string) end($pathIds), // Use the last parent category ID as string
                        'name' => $categoryName, // Use the last parent category name
                        'path' => $fullPath
                    ];
                }
            }

            return $paths;
        } catch (\Exception $e) {
            return [];
        }
    }

    /**
     * Get image URLs for a product
     *
     * @param array $gallery
     * @param array $galleryImagesFromPost
     * @return array
     */
    private function getImageUrls($gallery, $galleryImagesFromPost)
    {
        try {
            $imageUrls = [];
            $mainImage = [];
            foreach ($gallery as $image) {
                if (!in_array($image['id'], $galleryImagesFromPost)) {
                    continue;
                }

                if ($image['is_featured']) {
                    $mainImage = [
                        "url" => $image['noncached_url'],
                        "imageId" => $image['id']
                    ];
                    continue;
                }

                $imageUrls[] = [
                    "url" => $image['noncached_url'],
                    "imageId" => $image['id']
                ];
            }

            return [
                'main_image' => $mainImage,
                'gallery_images' => $imageUrls
            ];
        } catch (\Exception $e) {
            return [
                'main_image' => [],
                'gallery_images' => []
            ];
        }
    }

    // phpcs:disable Generic.Metrics.NestingLevel.TooHigh
    /**
     * Execute action
     *
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function execute()
    {
        $response = $this->resultFactory->create(ResultFactory::TYPE_JSON);

        try {
            $tones = $this->getRequest()->getPost('tones', explode(",", (string) $this->helper->getTones()));
            $style = $this->getRequest()->getPost('styles');
            $audience = $this->getRequest()->getPost('audience');
            $keywords = $this->getRequest()->getPost('keywords', []);
            $storeId = $this->getRequest()->getPost('store_id');
            $productId = $this->getRequest()->getPost('product_id');
            $descriptionMin = $this->getRequest()->getPost('desc_min', "");
            $descriptionMax = $this->getRequest()->getPost('desc_max', "");
            $excerptMin = $this->getRequest()->getPost('exc_min', "");
            $excerptMax = $this->getRequest()->getPost('exc_max', "");
            $attributes = $this->getRequest()->getPost('product_attributes', []);
            $attributes_selected = $this->getRequest()->getPost('product_attributes_selected', []);
            $otherProductDetails = $this->getRequest()->getPost('other_product_details', "");
            $additionalPrompt = $this->getRequest()->getPost('additional_prompt', "");
            $selectedFields = $this->getRequest()->getPost('selected_fields', []);
            $selectedImages = $this->getRequest()->getPost('selected_images', []);
            $gallery = $this->getRequest()->getPost('images', []);
            $customTone = $this->getRequest()->getPost('custom_tone', "");
            $customStyle = $this->getRequest()->getPost('custom_style', "");
            $customAudience = $this->getRequest()->getPost('custom_audience', "");
            $galleryImagesFromPost = $this->getRequest()->getPost('gallery_images', []);
            $failedImages = $this->getRequest()->getPost('failed_images', []);
            $templatesUsed = $this->getRequest()->getPost('templates_used', []);
            $keywordAnalysisViews = $this->getRequest()->getPost('keyword_analysis_views');
            $useAiModel = $this->getRequest()->getPost('use_ai_model', false);
            $selectedAiModel = $this->getRequest()->getPost('selected_ai_model', '');
            $keywordAnalysis = filter_var(
                $this->getRequest()->getPost('keyword_analysis'),
                FILTER_VALIDATE_BOOLEAN
            );
            
            $product = $this->productRepository->getById($productId, false, $storeId);
            $productName = $this->outputHelper->productAttribute(
                $product,
                $product->getName(),
                'name'
            );
            $mappingSettings = $this->helper->getMappingSettings();
            $country =  $this->scopeConfig->getValue(
                'general/country/default',
                ScopeInterface::SCOPE_STORE,
                $storeId
            );
            $language = $this->storeHelper->getFormattedLanguage($storeId);
            $ipAddress = $this->remoteAddress->getRemoteAddress();
            $frontendStoreId = $this->storeHelper->getFrontendStoreId($storeId);

            $rules = $this->settings->getSettings('rules');

            $isProductResearchDataSelected = false;

            $isThumbnailSelected = false;

            $failedThumbnailImages = [];

            if (!empty($selectedFields) || !empty($selectedImages)) {
                $maxOutputWords = $rules['maxOutputWords'] ?? '';
                $maxReferenceTextLength = $rules['maxReferenceTextLength'] ?? '';
                $additionalReferenceTextLength = $rules['additionalReferenceTextLength'] ?? '';
                $maxAttributes = $rules['maxAttributes'] ?? '';
                $maxAttributeValueLength = $rules['maxAttributeValueLength'] ?? '';

                $credits = $this->settings->getSettings('credits');
                $wordsPerCredit = $credits['wordsPerCredit'] ?? '';

                $maxInputChar = ((($maxOutputWords / $wordsPerCredit) - 1) * $additionalReferenceTextLength)
                    + $maxReferenceTextLength;

                // get attributes
                $attributesData = [];
                $images = [];
                $galleryById = [];
                if (is_array($gallery)) {
                    foreach ($gallery as $galleryImage) {
                        if (isset($galleryImage['id'])) {
                            $galleryById[$galleryImage['id']] = $galleryImage;
                        }
                    }
                }
                foreach ($attributes as $attribute) {
                    if (!in_array($attribute['attribute_code'], $attributes_selected)) {
                        continue;
                    }
                    
                    /*if ($maxAttributes <= count($attributesData)) {
                        continue;
                    }*/

                    if (strtolower($attribute['attribute_code']) ===
                        ProductAttributes::PRODUCT_RESEARCH_DATA_ATTRIBUTE_CODE) {
                        $isProductResearchDataSelected = true;
                        continue;
                    }
                    try {
                        if (strtolower($attribute['attribute']) !== 'thumbnail') {
                            if (is_array($attribute['details'])) {
                                $attribute['details'] = $attribute['details'][$attribute['value']] ?? '';
                            }
                            if (!empty(trim($attribute['details']))) {
                                $attributeValue = str_replace("<br />", "\n", $attribute['details']);
                                $attributeValue = $this->filterManager->stripTags($attributeValue);
                                // phpcs:ignore Magento2.Functions.DiscouragedFunction.DiscouragedWithAlternative
                                $attributeValue = htmlspecialchars(
                                    $attributeValue,
                                    ENT_QUOTES | ENT_SUBSTITUTE,
                                    'UTF-8'
                                );
                                $attributesData[] = [
                                    "name" => $attribute['attribute'],
                                    "value" => $attributeValue,
                                    "isCustom" => "false"
                                ];
                            }
                        } else {
                                $isThumbnailSelected = true;
                                $images[] = $this->imageHelper->getImageApiId(
                                    $storeId,
                                    $ipAddress,
                                    $language,
                                    $attribute['value'],
                                    $attribute['details']
                                );
                        }
                    } catch (\WriteTextAI\WriteTextAI\Exception\ImageUnsupported $e) {
                        if (strtolower($attribute['attribute']) === 'thumbnail' && !empty($attribute['details'])) {
                            $failedThumbnailImages[] = $galleryById[$attribute['value']]['noncached_url']
                                ?? $galleryById[$attribute['value']]['orig_url']
                                ?? $attribute['details'];
                        }
                        continue;
                    } catch (\WriteTextAI\WriteTextAI\Exception\ImageInvalid $e) {
                        if (strtolower($attribute['attribute']) === 'thumbnail' && !empty($attribute['details'])) {
                            $failedThumbnailImages[] = $galleryById[$attribute['value']]['noncached_url']
                                ?? $galleryById[$attribute['value']]['orig_url']
                                ?? $attribute['details'];
                        }
                        continue;
                    } catch (\Exception $e) {
                        if (strtolower($attribute['attribute']) === 'thumbnail' && !empty($attribute['details'])) {
                            $failedThumbnailImages[] = $galleryById[$attribute['value']]['noncached_url']
                                ?? $galleryById[$attribute['value']]['orig_url']
                                ?? $attribute['details'];
                        }
                        continue;
                    }
                }

                // fields to generate
                $fieldConfig = [
                    'page_title' => Fields::PAGE_TITLE,
                    'page_description' => Fields::PAGE_DESCRIPTION,
                    'product_description' => Fields::PRODUCT_DESCRIPTION,
                    'short_product_description' => Fields::EXCERPT,
                    'open_graph' => Fields::OPEN_GRAPH,
                ];

                $fields = [];
                foreach ($fieldConfig as $fieldName => $fieldConstant) {
                    if (in_array($fieldName, $selectedFields)) {
                        $field = [
                            "field" => $fieldConstant
                        ];

                        if ($fieldName == 'product_description') {
                            $field["minWords"] = $descriptionMin;
                            $field["maxWords"] = $descriptionMax;
                        } elseif ($fieldName == 'short_product_description') {
                            $field["minWords"] = $excerptMin;
                            $field["maxWords"] = $excerptMax;
                        }

                        if (isset($templatesUsed[$fieldName]) && $templatesUsed[$fieldName]) {
                            $field['templateId'] = $templatesUsed[$fieldName];
                        }

                        $fields[] = $field;
                    }
                }
                $productType = $this->getProductTypeMapping($product->getTypeId());

                $textData = [
                    "name" => $productName,
                    "recordId" => $productId,
                    "sku" => $product->getSku(),
                    "productType" => $productType,
                    "options" => 1,
                    "autoselectFirst" => true,
                    "attributes" => $attributesData,
                    "otherDetails" => $this->filterManager->stripTags($otherProductDetails),
                    "fields" => $fields,
                    "keywordAnalysisViews" => $keywordAnalysisViews,
                    "url" => $product->setStoreId($frontendStoreId)->getUrlInStore(),
                    "enableResearch" => $isProductResearchDataSelected
                ];
                $typeFlags = $this->getVirtualDownloadableFlags($product->getTypeId());
                $textData['isVirtual'] = $typeFlags['isVirtual'];
                $textData['isDownloadable'] = $typeFlags['isDownloadable'];
                $textData['categories'] = $this->getProductCategoryPaths($product, (int) $frontendStoreId);
               
                if (in_array((string)$product->getTypeId(), ['configurable', 'grouped', 'bundle'], true)) {
                    $childProductNames = $this->getChildProductName($product);
                    if (!empty($childProductNames)) {
                        $textData['childProducts'] = $childProductNames;
                    }
                }

                if (filter_var($useAiModel, FILTER_VALIDATE_BOOLEAN)) {
                    $textData['brandVoiceId'] = $selectedAiModel;
                }

                if (!empty($images)) {
                    $textData["images"] = $images;
                }
                
                $altTextImages = in_array('alt_text', $selectedFields) && !empty($galleryImagesFromPost)
                    ? $galleryImagesFromPost
                    : $selectedImages;
                $imageAltTextParams = $this->getAltTextParam(
                    $altTextImages,
                    $gallery
                );
                if ($imageAltTextParams) {
                    $textData["imageAltTexts"] = $imageAltTextParams;
                }
                
                if (!filter_var($useAiModel, FILTER_VALIDATE_BOOLEAN)) {
                    if ($customAudience) {
                        $textData['customAudience'] = $customAudience;
                    }

                    if (!empty($audience)) {
                        $textData['audiences'] = $audience;
                    }

                    if (in_array('custom', $tones)) {
                        $textData['customTone'] = $customTone;
                    } else {
                        $textData['tones'] = $tones;
                    }

                    if ($style == 'custom') {
                        $textData['customStyle'] = $customStyle;
                    } else {
                        $textData['style'] = $style;
                    }
                }
                
                $galleryImages = $this->productHelper->getImages($product, $storeId, $language);
                $imageUrls = $this->getImageUrls($galleryImages, $galleryImagesFromPost);
                if (isset($imageUrls['main_image']) && $imageUrls['main_image']) {
                    $textData['featuredImage'] = $imageUrls['main_image'];
                }
                if (isset($imageUrls['gallery_images']) && $imageUrls['gallery_images']) {
                    $textData['galleryImages'] = $imageUrls['gallery_images'];
                }

                if (!$isThumbnailSelected
                    && isset($textData['featuredImage'])
                    && is_array($textData['featuredImage'])
                ) {
                    $textData['featuredImage']['imageId'] = '';
                }

                $failedImagesForFeatured = $failedImages;
                if (!empty($failedThumbnailImages)) {
                    $failedImagesForFeatured = array_values(
                        array_unique(array_merge($failedImagesForFeatured, $failedThumbnailImages))
                    );
                }

                if (!empty($failedImagesForFeatured)) {
                    if (isset($textData['featuredImage']['url']) && $textData['featuredImage']['url']
                        && in_array($textData['featuredImage']['url'], $failedImagesForFeatured)) {
                        $textData['featuredImage']['imageId'] = '';
                    }

                    if (empty($textData['featuredImage'])) {
                        if (!empty($failedThumbnailImages)) {
                            $textData['featuredImage'] = [
                                'url' => $failedThumbnailImages[0],
                                'imageId' => ''
                            ];
                        }

                        foreach ($galleryImages as $galleryImage) {
                            if (empty($galleryImage['is_featured'])
                                || !in_array($galleryImage['id'], $galleryImagesFromPost)) {
                                continue;
                            }

                            $failedFeaturedUrl = $galleryImage['noncached_url'] ?? '';
                            if ($failedFeaturedUrl && in_array($failedFeaturedUrl, $failedImagesForFeatured)) {
                                $textData['featuredImage'] = [
                                    'url' => $failedFeaturedUrl,
                                    'imageId' => ''
                                ];
                                break;
                            }
                        }
                    }

                    if (empty($failedImages)) {
                        $failedImages = [];
                    }

                    $existingGalleryUrls = [];
                    if (isset($textData['galleryImages']) && is_array($textData['galleryImages'])) {
                        $existingGalleryUrls = array_column($textData['galleryImages'], 'url');
                    } else {
                        $textData['galleryImages'] = [];
                    }

                    foreach ($failedImages as $failedUrl) {
                        if (!empty($failedThumbnailImages) && in_array($failedUrl, $failedThumbnailImages)) {
                            continue;
                        }

                        if (!$failedUrl || in_array($failedUrl, $existingGalleryUrls)) {
                            continue;
                        }

                        $textData['galleryImages'][] = [
                            'url' => $failedUrl,
                            'imageId' => ''
                        ];
                        $existingGalleryUrls[] = $failedUrl;
                    }
                }

                if ($this->shouldStripGalleryImageIdsBySelectedTemplates($templatesUsed)) {
                    if (isset($textData['galleryImages']) && is_array($textData['galleryImages'])) {
                        foreach ($textData['galleryImages'] as $index => $galleryImage) {
                            if (!is_array($galleryImage)) {
                                continue;
                            }
                            $textData['galleryImages'][$index]['imageId'] = '';
                        }
                    }
                }

                if (!$isThumbnailSelected
                    && isset($textData['featuredImage'])
                    && is_array($textData['featuredImage'])
                ) {
                    $textData['featuredImage']['imageId'] = '';
                }

                $publishedContents = [
                    'product_description' => $this->fieldHelper->getAttributesValues($product, 'product_description'),
                    'short_product_description' => $this->fieldHelper->getAttributesValues(
                        $product,
                        'short_product_description'
                    )
                ];
                
                $params = [
                    "type" => "Product",
                    "storeId" => $storeId,
                    "language" => $language,
                    "countries" => [$country],
                    "ipAddress" => $ipAddress,
                    "texts" => [$textData],
                    "queue" => true
                ];

                if ($keywordAnalysis) {
                    $params['keywordOptimization'] = $this->getKeywordOptimizationParams($storeId);
                    $params['development'] = filter_var($this->helper->getKoDev(), FILTER_VALIDATE_BOOLEAN);
                }
                if ($this->helper->getForceQueueSeconds()) {
                    $params['developmentQueueWaitTimeInSeconds'] = $this->helper->getForceQueueSeconds();
                }

                if ($additionalPrompt) {
                    $params['specialInstructions'] = $additionalPrompt;
                }
                $apiResponse = $this->apiManager->generate(json_encode($params));

                if ($apiResponse && isset($apiResponse['requestId']) && $apiResponse['requestId']) {
                    $this->singleGenerateRequestsManager->setSingleGenerateRequest(
                        $apiResponse['requestId'],
                        $this->apiSession->getCurrentUser()->getEmail(),
                        'Product',
                        $storeId,
                        $productId
                    );
                }
            }
            
            $this->aiProductManager->saveDate($productId, $storeId, 'generated');
            $this->aiProductManager->saveDate($productId, $storeId, 'edited');

            $result = [
                'success' => true,
                'reviewed' => $this->markReview->getReviewed($productId, $storeId),
                'response' => $apiResponse ?? [],
                'params' => $params ?? []
            ];
        } catch (\WriteTextAI\WriteTextAI\Exception\UnauthorizedException $e) {
            $result = [
                'success' => false,
                'unauthorized' => true,
                'login_url' => $this->urlBuilder->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,
                'params' => $params ?? [],
            ];
            $result['message'] = $message;
        }

        $response->setData($result);

        return $response;
    }
    // phpcs:enable Generic.Metrics.NestingLevel.TooHigh
    /**
     * Check if gallery image IDs should be stripped based on selected templates
     *
     * @param array $templatesUsed
     * @return bool
     */
    private function shouldStripGalleryImageIdsBySelectedTemplates($templatesUsed): bool
    {
        if (!is_array($templatesUsed) || empty($templatesUsed)) {
            return true;
        }

        $templateIds = array_values(
            array_unique(
                array_filter(
                    array_map('strval', $templatesUsed),
                    static function ($v) {
                        return $v !== '';
                    }
                )
            )
        );

        if (empty($templateIds)) {
            return true;
        }

        foreach ($templateIds as $templateId) {
            try {
                $apiResponse = $this->apiManager->getTempatesHasImage($templateId);
                if ($this->extractHasGeneratedImageBlocks($apiResponse)) {
                    return false;
                }
            } catch (\Exception $e) {
                continue;
            }
        }

        return true;
    }

    /**
     * Extract hasGeneratedImageBlocks from API response
     *
     * @param array $apiResponse
     * @return bool
     */
    private function extractHasGeneratedImageBlocks($apiResponse): bool
    {
        if (!is_array($apiResponse)) {
            return false;
        }

        if (array_key_exists('hasGeneratedImageBlocks', $apiResponse)) {
            return (bool) $apiResponse['hasGeneratedImageBlocks'];
        }

        foreach ($apiResponse as $value) {
            if (is_array($value)) {
                $found = $this->extractHasGeneratedImageBlocks($value);
                if ($found) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Get keyword optimization params
     *
     * @param int $storeId
     *
     * @return array
     */
    private function getKeywordOptimizationParams($storeId)
    {
        $searchIntent = $this->getRequest()->getPost('search_intent_selected');
        
        $action = $this->getDefaultAutomaticTextOptimization();
        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;
        }

        $triggers = $this->keywords->prepareDefaultTriggerSettingsParameters();
        foreach ($triggers as $key => $trigger) {
            $triggers[$key]['action'] = $action;
        }

        $params = [
            "intents" => $searchIntent,
            "countryCode" => $this->keywordIdeaFiltersManager->getCountryCode($storeId),
            "clusters" => $this->helper->getKeywordOptimizationSettings('cluster_based_pipelines_count'),
            "triggers" => $triggers,
            "doKeywordOptimizationOnly" => false
        ];
        
        if (filter_var($this->helper->getKoDev(), FILTER_VALIDATE_BOOLEAN)) {
            $params["developmentSettings"] = [
                "waitTimePerStep" => 1000,
                "maxSteps" => 9,
                "failAfterFirstStep" => filter_var($this->helper->getForceFailed(), FILTER_VALIDATE_BOOLEAN)
            ];
        }

        return $params;
    }

    /**
     * Get default automatic text optimization
     *
     * @return string
     */
    public function getDefaultAutomaticTextOptimization()
    {
        $selected = $this->helper->getKeywordOptimizationSettings('automatic_text_optimization');
        if ($selected) {
            return $selected;
        }
        return AutomaticTextOptimization::AUTO_REWRITE_AND_QUEUE;
    }

    /**
     * Generate alt text for images
     *
     * @param array $selectedImages
     * @param array $gallery
     *
     * @return array
     */
    private function getAltTextParam(
        $selectedImages,
        $gallery
    ) {
        if (empty($selectedImages)) {
            return [];
        }

        $images = [];
        foreach ($gallery as $image) {
            if (in_array($image['id'], $selectedImages)) {
                $images[] = [
                    "imageId" => $image['id']
                ];
            }
        }

        return $images;
    }

    /**
     * Get product type mapping
     *
     * @param string $type
     * @return string
     */
    private function getProductTypeMapping($type)
    {
        if ($type === 'virtual' || $type === 'downloadable' || $type === 'simple') {
            return 'Simple';
        } elseif ($type === 'configurable') {
            return 'Variable';
        } elseif ($type === 'grouped') {
            return 'Grouped';
        } elseif ($type === 'bundle') {
            return 'Bundle';
        }
        return $type;
    }
}
