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

use WriteTextAI\WriteTextAI\Api\RecordManagementInterface;
use Magento\Framework\Exception\InputException;
use Magento\Framework\Webapi\Exception as WebapiException;
use Magento\Framework\App\RequestInterface;
use WriteTextAI\WriteTextAI\Model\ApiManager;
use WriteTextAI\WriteTextAI\Helper\Store as StoreHelper;
use WriteTextAI\WriteTextAI\Model\OptionSource\Filter\Fields;
use WriteTextAI\WriteTextAI\Helper\Data as HelperData;
use WriteTextAI\WriteTextAI\Model\AiProductManager;
use WriteTextAI\WriteTextAI\Model\GeneratedText;
use WriteTextAI\WriteTextAI\Model\GeneratedTextOptimized;
use WriteTextAI\WriteTextAI\Helper\Product as ProductHelper;
use WriteTextAI\WriteTextAI\Helper\Categories\Fields as CategoryFields;
use Magento\Catalog\Model\ResourceModel\Product\Action as ProductAction;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Store\Model\Store;
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
use Magento\Catalog\Model\ResourceModel\Product\Gallery as ProductGallery;
use Magento\Catalog\Model\CategoryFactory;
use WriteTextAI\WriteTextAI\Model\Categories\GeneratedText as CategoryGeneratedText;
use WriteTextAI\WriteTextAI\Model\AiCategoryManager;
use WriteTextAI\WriteTextAI\Helper\Html;
use WriteTextAI\WriteTextAI\Helper\Categories\RepresentativeProducts as RepresentativeProductsHelper;
use Magento\User\Model\UserFactory;
use WriteTextAI\WriteTextAI\Model\Api\Session as ApiSession;
use Magento\Framework\App\Response\Http as HttpResponse;
use Magento\Framework\Webapi\Rest\Response as RestResponse;
use Magento\Framework\Exception\NoSuchEntityException;
use WriteTextAI\WriteTextAI\Model\ReviewStatus;

class RecordManagement implements RecordManagementInterface
{
    /**
     * @var RequestInterface
     */
    protected $request;

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

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

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

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

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

    /**
     * @var GeneratedTextOptimized
     */
    protected $generatedTextOptimized;

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

    /**
     * @var ProductAction
     */
    protected $productAction;

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

    /**
     * @var TimezoneInterface
     */
    protected $timezone;

    /**
     * @var ProductGallery
     */
    protected $productGalleryResource;

    /**
     * @var CategoryFactory
     */
    protected $categoryFactory;

    /**
     * @var CategoryFields
     */
    protected $categoryFields;

    /**
     * @var CategoryGeneratedText
     */
    protected $categoryGeneratedText;

    /**
     * @var AiCategoryManager
     */
    protected $aiCategoryManager;

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

    /**
     * @var RepresentativeProductsHelper
     */
    protected $representativeProductsHelper;

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

    /**
     * @var UserFactory
     */
    protected $userFactory;

    /**
     * @var RestResponse
     */
    protected $response;

    /**
     * @var ReviewStatus
     */
    protected $reviewStatus;

    /**
     * @var array
     */
    protected $skippedIds = [];

    /**
     * @var array
     */
    protected $failedIds = [];

    /**
     * @var array
     */
    protected $successIds = [];

    /**
     * @var array
     */
    protected $categoryResultsFields = [];

    /**
     * @var array
     */
    protected $perStoreIds = [];

    /**
     * @param RequestInterface $request
     * @param ApiManager $apiManager
     * @param StoreHelper $storeHelper
     * @param HelperData $helperData
     * @param AiProductManager $aiProductManager
     * @param GeneratedText $generatedText
     * @param GeneratedTextOptimized $generatedTextOptimized
     * @param ProductHelper $productHelper
     * @param ProductAction $productAction
     * @param ProductRepositoryInterface $productRepository
     * @param TimezoneInterface $timezone
     * @param ProductGallery $productGalleryResource
     * @param CategoryFactory $categoryFactory
     * @param CategoryFields $categoryFields
     * @param CategoryGeneratedText $categoryGeneratedText
     * @param AiCategoryManager $aiCategoryManager
     * @param Html $htmlHelper
     * @param RepresentativeProductsHelper $representativeProductsHelper
     * @param ApiSession $apiSession
     * @param UserFactory $userFactory
     * @param RestResponse $response
     * @param ReviewStatus $reviewStatus
     */
    public function __construct(
        RequestInterface $request,
        ApiManager $apiManager,
        StoreHelper $storeHelper,
        HelperData $helperData,
        AiProductManager $aiProductManager,
        GeneratedText $generatedText,
        GeneratedTextOptimized $generatedTextOptimized,
        ProductHelper $productHelper,
        ProductAction $productAction,
        ProductRepositoryInterface $productRepository,
        TimezoneInterface $timezone,
        ProductGallery $productGalleryResource,
        CategoryFactory $categoryFactory,
        CategoryFields $categoryFields,
        CategoryGeneratedText $categoryGeneratedText,
        AiCategoryManager $aiCategoryManager,
        Html $htmlHelper,
        RepresentativeProductsHelper $representativeProductsHelper,
        ApiSession $apiSession,
        UserFactory $userFactory,
        RestResponse $response,
        ReviewStatus $reviewStatus
    ) {
        $this->request = $request;
        $this->apiManager = $apiManager;
        $this->storeHelper = $storeHelper;
        $this->helperData = $helperData;
        $this->aiProductManager = $aiProductManager;
        $this->generatedText = $generatedText;
        $this->generatedTextOptimized = $generatedTextOptimized;
        $this->productHelper = $productHelper;
        $this->productAction = $productAction;
        $this->productRepository = $productRepository;
        $this->timezone = $timezone;
        $this->productGalleryResource = $productGalleryResource;
        $this->categoryFactory = $categoryFactory;
        $this->categoryFields = $categoryFields;
        $this->categoryGeneratedText = $categoryGeneratedText;
        $this->aiCategoryManager = $aiCategoryManager;
        $this->htmlHelper = $htmlHelper;
        $this->representativeProductsHelper = $representativeProductsHelper;
        $this->apiSession = $apiSession;
        $this->userFactory = $userFactory;
        $this->response = $response;
        $this->reviewStatus = $reviewStatus;
    }

    /**
     * {@inheritdoc}
     */
    public function processRecords()
    {
        try {
            // $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/wtai-recordmanagement.log');
            // $logger = new \Zend_Log();
            // $logger->addWriter($writer);
            $body = $this->request->getContent();
            $data = json_decode($body, true);

            if (!is_array($data)) {
                throw new InputException(__('Invalid request format.'));
            }

            // Get input parameters
            $type = $data['type'] ?? 'Product';
            $storeId = (string)$data['storeId'] ?? '0';
            $records = $data['records'] ?? [];
            $targetStoreIds = $data['targetStoreId'] ?? ""; //comma separated
            $userName = $data['userName'] ?? ''; //email
            $isAutomatic = $data['isAutomatic'] ?? false;

            // If targetStoreIds is empty, transfer to all stores
            if (empty($targetStoreIds)) {
                $targetStoreIds = [$storeId];
            } else {
                $targetStoreIds = explode(',', $targetStoreIds);
            }

            // Log processing
            //$logger->info('RecordManagement API called: ' . json_encode([
            //     'type' => $type,
            //     'sourceStoreId' => $storeId, 
            //     'targetStoreIds' => $targetStoreIds,
            //     'recordCount' => count($records)
            // ]));

            $user = $this->getUserByEmail($userName);
            if (!$user) {
                throw new InputException(__('User not found.'));
            }
            $this->apiSession->setCurrentUser($user);

            // Reset tracking arrays
            $this->successIds = [];
            $this->failedIds = [];
            $this->skippedIds = [];
            $this->perStoreIds = [];
            
            // Initialize per-store tracking
            foreach ($targetStoreIds as $targetStoreId) {
                $this->perStoreIds[$targetStoreId] = [
                    'success' => [],
                    'failed' => [],
                    'skipped' => []
                ];
            }

            foreach ($records as $record) {
                $recordId = $record['id'] ?? '';
                if (!$recordId) {
                    continue;
                }

                $fields = $record['fields'] ?? [];
                $imageIds = $record['imageIds'] ?? [];

                // Only load product and process images for Product type, not Category
                if ($type === 'Product') {
                    try {
                        $product = $this->productRepository->getById($recordId, false, $storeId);
                    } catch (NoSuchEntityException $e) {
                        //$logger->info('Failed to get product for record ' . $recordId . $e->getMessage());
                        $this->failedIds[] = (string)$recordId;
                        foreach ($targetStoreIds as $targetStoreId) {
                            $this->perStoreIds[$targetStoreId]['failed'][] = (string)$recordId;
                        }
                        continue;
                    }
                    
                    // Only process 'all' imageIds for products (categories don't have gallery)
                    if ($imageIds == ['all']) {
                        try {
                            $imageIds = $this->productHelper->getImageIds($product);
                        } catch (\Exception $e) {
                            //$logger->info('Failed to get all image IDs for record ' . $recordId . $e->getMessage());
                            $imageIds = [];
                        }
                    }
                } else {
                    // For categories, clear imageIds since they don't have galleries
                    $imageIds = [];
                }

                //$logger->info('Processing record ' . $recordId . ': ' . json_encode([
                //     'fields' => $fields,
                //     'imageIds' => $imageIds
                // ]));

                try {
                    $imageTransferStatus = null;
                    $imageWasProcessed = false;
                    
                    // Process image alt text transfer if imageIds provided (only for products)
                    if (!empty($imageIds) && $type === 'Product') {
                        $imageWasProcessed = true;
                        $imageTransferStatus = $this->processImageTransfer(
                            $recordId,
                            $storeId,
                            $targetStoreIds,
                            $imageIds,
                            $fields,
                            $isAutomatic
                        );
                        //$logger->info('Image transfer status for record ' . $recordId . ': ' . $imageTransferStatus);
                        
                        // Only fail on image transfer if no fields are being processed
                        if ($imageTransferStatus === 'failed' && empty($fields)) {
                            $this->failedIds[] = (string)$recordId;
                            continue;
                        }
                        
                        // Track skipped images if no fields are being processed
                        if ($imageTransferStatus === 'skipped' && empty($fields)) {
                            $this->skippedIds[] = (string)$recordId;
                            continue;
                        }
                    }

                    // Process field transfers for each target store
                    if (!empty($fields)) {
                        $fieldTransferSuccess = $this->processFieldTransfer(
                            $recordId,
                            $type,
                            $storeId,
                            $targetStoreIds,
                            $fields,
                            $isAutomatic
                        );
                        if (!$fieldTransferSuccess) {
                            $this->failedIds[] = (string)$recordId;
                            continue;
                        }
                    }
                    
                    //$logger->info("skippedIds: " . json_encode($this->skippedIds));

                    $this->processResultPerRecord(
                        $recordId,
                        $imageWasProcessed,
                        $imageTransferStatus,
                        $targetStoreIds,
                        $fields
                    );

                } catch (\Exception $e) {
                    //$logger->info('Failed to process record ' . $recordId . $e->getMessage());
                    $this->failedIds[] = (string)$recordId;
                    // Add to per-store failed tracking
                    foreach ($targetStoreIds as $targetStoreId) {
                        $this->perStoreIds[$targetStoreId]['failed'][] = (string)$recordId;
                    }
                }
            }

            // Create structured response
            $responseData = [];
            
            // If multiple target stores, use per-store structure
            if (count($targetStoreIds) > 1) {
                // Sort store IDs in descending order to prevent JSON encoding as sequential array
                // This forces json_encode() to treat it as an associative object
                $sortedStoreIds = $targetStoreIds;
                rsort($sortedStoreIds);
                
                $storeResults = [];
                foreach ($sortedStoreIds as $storeId) {
                    $storeResults[$storeId] = [
                        'success' => array_values(array_unique($this->perStoreIds[$storeId]['success'] ?? [])),
                        'failed' => array_values(array_unique($this->perStoreIds[$storeId]['failed'] ?? [])),
                        'skipped' => array_values(array_unique($this->perStoreIds[$storeId]['skipped'] ?? []))
                    ];
                }
                $responseData['storeIds'] = $storeResults;
            } else {
                // Single store - use flat structure
                $responseData['success'] = array_values(array_unique($this->successIds));
                $responseData['failed'] = array_values(array_unique($this->failedIds));
                $responseData['skipped'] = array_values(array_unique($this->skippedIds));
            }

            // Set security headers
            $this->setSecurityHeaders();
            //$logger->info('RecordManagement API response: ' . json_encode($responseData));

            return $this->response->setBody(json_encode($responseData))->sendResponse();
            
        } catch (\Exception $e) {
            // Return error response format instead of throwing exception
            $errorCode = $e instanceof WebapiException ? $e->getHttpCode() : 500;
            
            // Create structured error response
            $errorResponse = [
                'error' => [
                    'code' => $errorCode,
                    'message' => $e->getMessage()
                ]
            ];
            
            // Set security headers even for error responses
            $this->setSecurityHeaders();
            $this->response->setHttpResponseCode($errorCode);
            
            return $this->response->setBody(json_encode($errorResponse))->sendResponse();
        }
    }

    /**
     * Process result per record
     * 
     * @param int $recordId
     * @param bool $imageWasProcessed
     * @param string $imageTransferStatus
     * @param int $sourceStoreId
     * @param array $targetStoreIds
     * @param array $fields
     * @return void
     */
    private function processResultPerRecord(
        $recordId,
        $imageWasProcessed,
        $imageTransferStatus,
        $targetStoreIds,
        $fields
    ) {
        // $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/wtai-recordmanagement.log');
        // $logger = new \Zend_Log();
        // $logger->addWriter($writer);

        // If fields were processed but record was skipped, and images were processed, use image results
        $wasSkippedByFields = !empty($fields) && in_array((string)$recordId, $this->skippedIds);
        //check wess was skipped by fields per store
        
        if ($wasSkippedByFields && $imageWasProcessed) {
            //$logger->info('Fields were skipped for record ' . $recordId . ', checking image status: ' . $imageTransferStatus);
            
            // Remove from skipped since we'll use image results instead
            $this->skippedIds = array_diff($this->skippedIds, [(string)$recordId]);
            
            // Clean up per-store skipped entries added by field processing OR image processing
            foreach ($targetStoreIds as $targetStoreId) {
                if (isset($this->perStoreIds[$targetStoreId]['skipped'])) {
                    $this->perStoreIds[$targetStoreId]['skipped'] = array_diff(
                        $this->perStoreIds[$targetStoreId]['skipped'],
                        [(string)$recordId]
                    );
                }
            }
            
            if ($imageTransferStatus === 'success') {
                // Image success tracking is already handled in processImageAltTextTransfer perStoreIds
                // Will be picked up by the success check below
            } elseif ($imageTransferStatus === 'failed') {
                // Image failed, mark record as failed
                $this->failedIds[] = (string)$recordId;
                // Add to per-store failed
                foreach ($targetStoreIds as $targetStoreId) {
                    $this->perStoreIds[$targetStoreId]['failed'][] = (string)$recordId;
                }
            } elseif ($imageTransferStatus === 'skipped') {
                // Images were also skipped, keep in skipped
                $this->skippedIds[] = (string)$recordId;
                // Re-add to per-store skipped since both fields and images skipped
                foreach ($targetStoreIds as $targetStoreId) {
                    $this->perStoreIds[$targetStoreId]['skipped'][] = (string)$recordId;
                }
            }
        }

        // Only mark as success if not already marked as failed or skipped
        if (!in_array((string)$recordId, $this->failedIds) && !in_array((string)$recordId, $this->skippedIds)) {
            $this->successIds[] = (string)$recordId;
        }
    }

    /**
     * Process field transfer for a record
     *
     * @param string $recordId
     * @param string $type
     * @param string $sourceStoreId
     * @param array $targetStoreIds
     * @param array $fields
     * @param bool $isAutomatic
     * @return bool
     */
    private function processFieldTransfer(
        $recordId,
        $type,
        $sourceStoreId,
        $targetStoreIds,
        $fields,
        $isAutomatic = false
    ) {
        // $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/wtai-recordmanagement.log');
        // $logger = new \Zend_Log();
        // $logger->addWriter($writer);
        try {
            if ($type === 'Product') {
                $resultgenerated = $this->generatedTextOptimized->getGeneratedByStoreId((string)$recordId, (int)$sourceStoreId);
                
                if (empty($resultgenerated) || !isset($resultgenerated[$recordId])) {
                    //add to skipped
                    $this->skippedIds[] = (string)$recordId;
                    foreach ($targetStoreIds as $targetStoreId) {
                        // Only add to per-store skipped if not already in success (from image processing)
                        if (!in_array((string)$recordId, $this->perStoreIds[$targetStoreId]['success'] ?? [])) {
                            $this->perStoreIds[$targetStoreId]['skipped'][] = (string)$recordId;
                        }
                    }
                    //$logger->info('Field transfer skipped for record ' . $recordId . ' in store ' . $targetStoreId);
                    return true;
                }
                
                $item = $resultgenerated[$recordId] ?? [];
                $mappingSettings = $this->helperData->getMappingSettings();
                foreach ($targetStoreIds as $targetStoreId) {
                    $language = $this->storeHelper->getFormattedLanguage($targetStoreId);
                    $this->processProductFieldTransfer(
                        $resultgenerated,
                        $recordId,
                        $sourceStoreId,
                        $targetStoreId,
                        $language,
                        $fields,
                        $mappingSettings
                    );    
                }
        
                $productFields = $this->getProductFields($fields);
                // Save to WriteTextAI storage
                $reviewed = false;
                $this->generatedTextOptimized->saveText(
                    $sourceStoreId,
                    (string)$recordId,
                    isset($item[Fields::PAGE_TITLE]) ? $item[Fields::PAGE_TITLE] : '',
                    isset($item[Fields::PAGE_DESCRIPTION]) ? $item[Fields::PAGE_DESCRIPTION] : '',
                    isset($item[Fields::PRODUCT_DESCRIPTION]) ? $item[Fields::PRODUCT_DESCRIPTION] : '',
                    isset($item[Fields::EXCERPT]) ? $item[Fields::EXCERPT] : '',
                    isset($item[Fields::OPEN_GRAPH]) ? $item[Fields::OPEN_GRAPH] : '',
                    $productFields,
                    $reviewed,
                    $isAutomatic
                ); 
                
                $this->reviewStatus->updateReview($productFields, $recordId, $targetStoreIds);
            } elseif ($type === 'Category') {
                $resultgenerated = $this->categoryGeneratedText->getGeneratedByStoreId((string)$recordId, (int)$sourceStoreId);
                if (empty($resultgenerated) || !isset($resultgenerated[$recordId])) {
                    //add to skipped
                    $this->skippedIds[] = (string)$recordId;
                    foreach ($targetStoreIds as $targetStoreId) {
                        // Only add to per-store skipped if not already in success (from image processing)
                        if (!in_array((string)$recordId, $this->perStoreIds[$targetStoreId]['success'] ?? [])) {
                            $this->perStoreIds[$targetStoreId]['skipped'][] = (string)$recordId;
                        }
                    }
                    //$logger->info('Category field transfer skipped for record ' . $recordId . ' in store ' . $targetStoreId);
                    return true;
                }
                
                $mappingSettings = $this->categoryFields->getMappingSettings();
                foreach ($targetStoreIds as $targetStoreId) {
                    $language = $this->storeHelper->getFormattedLanguage($targetStoreId);
                    $this->processCategoryFieldTransfer(
                        $resultgenerated,
                        $recordId,
                        $sourceStoreId,
                        $targetStoreId,
                        $language,
                        $fields,
                        $mappingSettings
                    );
                }
                $transfered = true;
                $reviewed = false;
                $this->categoryGeneratedText->saveCategoryText(
                    $sourceStoreId,
                    (string)$recordId,
                    $this->categoryResultsFields,
                    $transfered,
                    $reviewed,
                    $isAutomatic
                );
            }
            
            return true;
        } catch (\Exception $e) {
            //$logger->info('Field transfer failed for record ' . $recordId . $e->getMessage());
            return false;
        }
    }

    /**
     * Process product field transfer
     *
     * @param array $resultgenerated
     * @param string $recordId
     * @param string $sourceStoreId
     * @param string $targetStoreId
     * @param string $language
     * @param array $fields
     * @param array $mappingSettings
     * @return void
     */
    private function processProductFieldTransfer(
        $resultgenerated,
        $recordId,
        $sourceStoreId,
        $targetStoreId,
        $language,
        $fields,
        $mappingSettings
    ) {
        
        // $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/wtai-recordmanagement.log');
        // $logger = new \Zend_Log();
        // $logger->addWriter($writer);
        try {
        $product = $this->productRepository->getById($recordId, false, $targetStoreId);
        $item = $resultgenerated[$recordId] ?? [];
        $images = $this->productHelper->getPublishedImages($product, $targetStoreId, $language);
        $productFields = $this->removeEmptyAndTransferredFields($item, $fields);

        //$logger->info("productFields: " . json_encode($productFields, JSON_PRETTY_PRINT));
        if (empty($productFields)) {
            //add to skipped
            $this->skippedIds[] = (string)$recordId;
            // Only add to per-store skipped if not already in success (from image processing)
            if (!in_array((string)$recordId, $this->perStoreIds[$targetStoreId]['success'] ?? [])) {
                $this->perStoreIds[$targetStoreId]['skipped'][] = (string)$recordId;
            }
            //$logger->info('Field transfer skipped for record ' . $recordId . ' in store ' . $targetStoreId);
            return;
        }
        
        $productFields = $this->getProductFields($fields);

        // Transfer to Magento attributes
        $this->transferToMagento(
            $recordId,
            $targetStoreId,
            $productFields,
            $item,
            $mappingSettings,
            $images
        );
        
        $this->successIds[] = (string)$recordId;
        // Track success per store
        $this->perStoreIds[$targetStoreId]['success'][] = (string)$recordId;
        
        } catch (\Exception $e) {
            //$logger->info('Failed to process product field transfer for record ' . $recordId . $e->getMessage());
            $this->failedIds[] = (string)$recordId;
            $this->perStoreIds[$targetStoreId]['failed'][] = (string)$recordId;
        }
    }

    /**
     * Process category field transfer
     *
     * @param array $resultgenerated
     * @param string $recordId
     * @param string $sourceStoreId
     * @param string $targetStoreId
     * @param string $language
     * @param array $fields
     * @param array $mappingSettings
     * @return void
     */
    private function processCategoryFieldTransfer(
        $resultgenerated,
        $recordId,
        $sourceStoreId,
        $targetStoreId,
        $language,
        $fields,
        $mappingSettings
    ) {
        // $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/wtai-recordmanagement.log');
        // $logger = new \Zend_Log();
        // $logger->addWriter($writer);
        
        try {
        
        $fieldsList = [
            Fields::CATEGORY_PAGE_TITLE => 'page_title',
            Fields::CATEGORY_PAGE_DESCRIPTION => 'page_description',
            Fields::CATEGORY_DESCRIPTION => 'category_description',
        ];
        
        $selectedRepresentativeProducts = $this->getSelectedRepresentativeProducts($recordId, $targetStoreId);
        
        // Get image alt texts for representative products
        $imageAltTexts = [];
        foreach ($selectedRepresentativeProducts as $productData) {
            try {
                $product = $this->productRepository->getById($productData->value, false, $targetStoreId, true);
                $productImages = $this->productHelper->getPublishedImages($product, $targetStoreId, $language);
                if (is_array($productImages)) {
                    $imageAltTexts = array_merge($imageAltTexts, $productImages);
                }
            } catch (\Exception $e) {
                continue;
            }
        }

        $category = $this->categoryFactory->create()->setStoreId($targetStoreId)->load($recordId);
        if (!$category->getId()) {
            //add to skipped - category not found
            $this->skippedIds[] = (string)$recordId;
            // Only add to per-store skipped if not already in success (from image processing)
            if (!in_array((string)$recordId, $this->perStoreIds[$targetStoreId]['success'] ?? [])) {
                $this->perStoreIds[$targetStoreId]['skipped'][] = (string)$recordId;
            }
            //$logger->info('Category not found for record ' . $recordId . ' in store ' . $targetStoreId);
            return;
        }
        
        $resultFields = [];
        foreach ($resultgenerated[$recordId] as $field => $value) {
            if (in_array($field, $fields)) {
                if ($imageAltTexts) {
                    $value = $this->htmlHelper->addAltTextToContentViaPreg($value, $imageAltTexts);
                }
                $category->setData($mappingSettings[$fieldsList[$field]], $value);
                $resultFields[$fieldsList[$field]] = $value;
                $this->categoryResultsFields[$fieldsList[$field]] = $value;
            }
        }

        $category->save();
        
        $this->aiCategoryManager->saveDate($recordId, $targetStoreId, 'transferred');
        $this->aiCategoryManager->saveDate($recordId, $targetStoreId, 'reviewed');
        
        // Track success per store
        $this->successIds[] = (string)$recordId;
        $this->perStoreIds[$targetStoreId]['success'][] = (string)$recordId;
        
        } catch (\Exception $e) {
            //$logger->info('Failed to process category field transfer for record ' . $recordId . $e->getMessage());
            $this->failedIds[] = (string)$recordId;
            $this->perStoreIds[$targetStoreId]['failed'][] = (string)$recordId;
        }
    }

    /**
     * Process image alt text transfer
     *
     * @param string $recordId
     * @param string $sourceStoreId
     * @param array $targetStoreIds
     * @param array $imageIds
     * @param array $fields
     * @param bool $isAutomatic
     * @return string 'success', 'failed', or 'skipped'
     */
    private function processImageTransfer(
        $recordId,
        $sourceStoreId,
        $targetStoreIds,
        $imageIds,
        $fields = [],
        $isAutomatic = false
    ) {
        // $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/wtai-recordmanagement.log');
        // $logger = new \Zend_Log();
        // $logger->addWriter($writer);
        
        try {
            $hasSuccess = false;
            $hasSkipped = false;
            $hasFailed = false;
            
            foreach ($targetStoreIds as $targetStoreId) {
                $language = $this->storeHelper->getFormattedLanguage($targetStoreId);
                $status = $this->processImageAltTextTransfer(
                    $recordId,
                    $sourceStoreId,
                    $targetStoreId,
                    $language,
                    $imageIds,
                    $fields,
                    $isAutomatic
                );
                
                if ($status === 'success') {
                    $hasSuccess = true;
                } elseif ($status === 'skipped') {
                    $hasSkipped = true;
                } elseif ($status === 'failed') {
                    $hasFailed = true;
                }
            }
            
            // Determine overall status
            if ($hasFailed) {
                return 'failed';
            } elseif ($hasSuccess) {
                return 'success';
            } else {
                return 'skipped';
            }
        } catch (\Exception $e) {
            ////$logger->info('Image transfer failed for record ' . $recordId, ['error' => $e->getMessage()]);
            return 'failed';
        }
    }

    /**
     * Process image alt text transfer for specific record and images
     *
     * @param string $recordId
     * @param string $sourceStoreId
     * @param string $targetStoreId
     * @param string $language
     * @param array $imageIds
     * @param array $fields
     * @param bool $isAutomatic
     * @return string 'success', 'failed', or 'skipped'
     */
    private function processImageAltTextTransfer(
        $recordId,
        $sourceStoreId,
        $targetStoreId,
        $language,
        $imageIds,
        $fields = [],
        $isAutomatic = false
    ) {
        // $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/wtai-recordmanagement.log');
        // $logger = new \Zend_Log();
        // $logger->addWriter($writer);
        try {
            $product = $this->productRepository->getById($recordId, true, $targetStoreId);
            $mediaGalleryEntries = $product->getMediaGalleryEntries();
            $updated = false;
            $imagesToUpdate = [];
            $currentImageIds = [];
            $archivedImageIds = [];
            foreach ($mediaGalleryEntries as $mediaGalleryEntry) {
                $currentImageIds[] = $mediaGalleryEntry->getId();
                if (!in_array($mediaGalleryEntry->getId(), $imageIds)) {
                    continue;
                }

                $getParams = [
                    "storeId" => $sourceStoreId,
                    "language" => $language,
                    "imageId" => $mediaGalleryEntry->getId()
                ];

                $altText = $this->apiCallWithRetry(function() use ($getParams) {
                    return $this->apiManager->getImage($getParams);
                }, 1);
                
                if ($altText === null || !isset($altText['altText']['value'])) {
                    continue;
                }
                
                $mediaGalleryEntry->setLabel($altText['altText']['value']);
                $updated = true;
                
                // Add to batch update for API
                if (isset($altText['altText']['id'])) {
                    $imagesToUpdate[] = [
                        "storeId" => $targetStoreId,
                        "language" => $language,
                        "imageId" => $mediaGalleryEntry->getId(),
                        "textId" => $altText['altText']['id'],
                        "value" => $altText['altText']['value'],
                        "publish" => true,
                        "reviewed" => true,
                        "isAutomatic" => $isAutomatic
                    ];
                }
            }
            foreach ($imageIds as $imageId) {
                if (!in_array($imageId, $currentImageIds)) {
                    $archiveBody = [
                        "imageId" => (string)$imageId,
                    ];
                    $this->apiCallWithRetry(function() use ($archiveBody) {
                        return $this->apiManager->archiveProductImage($archiveBody);
                    }, 1);
                    $archivedImageIds[] = $imageId;
                }
            }

            if ($updated) {
                $product->setMediaGalleryEntries($mediaGalleryEntries);
                $this->productRepository->save($product);
            
                $this->aiProductManager->saveDate($recordId, $targetStoreId, 'transferred');
                $this->aiProductManager->saveDate($recordId, $targetStoreId, 'reviewed');
                
                // Track success per store if: no fields OR fields will be checked later for skip
                // Always track here, will be used if fields are skipped
                $this->perStoreIds[$targetStoreId]['success'][] = (string)$recordId;
            }

            // Batch update alt text via API
            if (!empty($imagesToUpdate)) {
                $this->apiCallWithRetry(function() use ($imagesToUpdate) {
                    return $this->apiManager->batchUpdateAltText(json_encode([
                        "images" => $imagesToUpdate
                    ]));
                }, 1);
            }

            // Determine status and track accordingly
            if (empty($imagesToUpdate) && empty($archivedImageIds) && !$updated) {
                // No images were updated, no images to archive - this is a skip
                //$logger->info('Image transfer skipped for record ' . $recordId . ' - no alt text found');
                if (empty($fields)) {
                    $this->skippedIds[] = (string)$recordId;
                    $this->perStoreIds[$targetStoreId]['skipped'][] = (string)$recordId;
                }
                return 'skipped';
            } elseif (empty($imagesToUpdate) && !empty($archivedImageIds)) {
                // Images archived but no updates - this is a failure
                // Only add to global failed if no fields are being processed
                if (empty($fields)) {
                    $this->failedIds[] = (string)$recordId;
                    $this->perStoreIds[$targetStoreId]['failed'][] = (string)$recordId;
                }
                return 'failed';
            }
            
            return 'success';

        } catch (\Exception $e) {
            //$logger->info('Failed to process image alt text for record ' . $recordId . $e->getMessage());
            // Track image failures - will be used if fields are empty or fields are skipped
            $this->perStoreIds[$targetStoreId]['failed'][] = (string)$recordId;
            // Only add to global failed if no fields are being processed
            if (empty($fields)) {
                // Don't re-throw, just track the failure
                return 'failed';
            }
            throw $e;
        }
    }

    /**
     * Transfer data to Magento attributes
     *
     * @param int $recordId
     * @param int $storeId
     * @param array $selectedFields
     * @param array $item
     * @param array $mappingSettings
     * @param array $images
     * @return void
     */
    private function transferToMagento($recordId, $storeId, $selectedFields, $item, $mappingSettings, $images)
    {
        $equivalentFields = [
            Fields::PAGE_TITLE => 'page_title',
            Fields::PAGE_DESCRIPTION => 'page_description',
            Fields::PRODUCT_DESCRIPTION => 'product_description',
            Fields::EXCERPT => 'short_product_description',
            Fields::OPEN_GRAPH => 'open_graph'
        ];
        
        $toUpdate = [];
        foreach ($item as $field => $value) {
            $fieldEquivalent = $equivalentFields[$field] ?? $field;
            if (isset($mappingSettings[$fieldEquivalent]) && in_array($fieldEquivalent, $selectedFields)) {
                $value = $this->htmlHelper->addAltTextToContentViaPreg($value, $images, true);
                $toUpdate[$mappingSettings[$fieldEquivalent]] = $value;
            }
        }
        
        if (!empty($toUpdate)) {
            $this->productAction->updateAttributes(
                [$recordId],
                $toUpdate,
                $storeId
            );
            $this->aiProductManager->saveDate($recordId, $storeId, 'transferred');
            $this->aiProductManager->saveDate($recordId, $storeId, 'reviewed');
        }
    }

    /**
     * Remove empty and already transferred fields
     *
     * @param array $fields
     * @return array
     */
    private function getProductFields($fields)
    {
        $fieldsList = [
            Fields::PAGE_TITLE => 'page_title',
            Fields::PAGE_DESCRIPTION => 'page_description',
            Fields::PRODUCT_DESCRIPTION => 'product_description',
            Fields::EXCERPT => 'short_product_description',
            Fields::OPEN_GRAPH => 'open_graph',
        ];
        $productFields = [];
        foreach ($fields as $field) {
            if (isset($fieldsList[$field])) {
                $productFields[] = $fieldsList[$field];
            }
        }
        return $productFields;
    }

    /**
     * Get selected representative products
     *
     * @param int $categoryId
     * @param int $storeId
     * @return array
     */
    private function getSelectedRepresentativeProducts($categoryId, $storeId)
    {
        $aiCategory = $this->aiCategoryManager->getCategory($categoryId, $storeId);
        $selectedRepresentativeProducts = $this->representativeProductsHelper
            ->getRepresentativeProductsSelected($aiCategory);

        return $selectedRepresentativeProducts;
    }

    /**
     * API call with retry logic
     *
     * @param callable $apiCall
     * @param int $maxRetries
     * @return mixed|null
     */
    private function apiCallWithRetry($apiCall, $maxRetries = 3)
    {
        
        // $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/wtai-recordmanagement.log');
        // $logger = new \Zend_Log();
        // $logger->addWriter($writer);
        $attempt = 0;
        $lastException = null;
        
        while ($attempt < $maxRetries) {
            try {
                $attempt++;
                $result = $apiCall();
                return $result;
            } catch (\Exception $e) {
                $lastException = $e;
                //$logger->info("API call attempt {$attempt} failed: " . $e->getMessage());
                
                if ($attempt < $maxRetries) {
                    usleep(500000); // 0.5 second delay before retry
                }
            }
        }
        
        // if ($lastException) {
        //     $logger->info("All {$maxRetries} retry attempts failed. Last error: " . $lastException->getMessage());
        // }
        
        return null;
    }

    /**
     * Get user by email
     *
     * @param string $email
     * @return bool|\Magento\User\Model\User
     */
    private function getUserByEmail($email)
    {
        $model = $this->userFactory->create();
        //filter by email
        $model->load($email, 'email');

        if ($model->getId()) {
            return $model;
        }

        return false;
    }

    /**
     * Set security headers for API response
     *
     * @return void
     */
    private function setSecurityHeaders()
    {
        // Try both methods to ensure headers are set
        $this->response->setHeader('X-Content-Type-Options', 'nosniff', true);
        $this->response->setHeader('X-Frame-Options', 'DENY', true);
        $this->response->setHeader('X-XSS-Protection', '1; mode=block', true);
        
        // // Also try setting raw headers
        // $this->response->setRawHeader('X-Content-Type-Options: nosniff');
        // $this->response->setRawHeader('X-Frame-Options: DENY');
        // $this->response->setRawHeader('X-XSS-Protection: 1; mode=block');
        
        // // Try with headers_set if available
        // if (function_exists('header') && !headers_sent()) {
        //     header('X-Content-Type-Options: nosniff');
        //     header('X-Frame-Options: DENY');
        //     header('X-XSS-Protection: 1; mode=block');
        // }
    }

    /**
     * Remove empty and already transferred fields
     *
     * @param array $item
     * @param array $fields
     * @return array
     */
    private function removeEmptyAndTransferredFields($item, $fields)
    {
        $productFields = [];

        foreach ($fields as $field) {
            if (isset($item[$field]) &&
                $item[$field] != '' &&
                $item[$field] != null
            ) {
                $productFields[] = $field;
            }
        }

        return $productFields;
    }
}