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

namespace WriteTextAI\WriteTextAI\Controller\Adminhtml\Grid;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\ResourceModel\Product\Action as ProductAction;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\Controller\ResultFactory;
use WriteTextAI\WriteTextAI\Helper\Data;
use WriteTextAI\WriteTextAI\Helper\Product as ProductHelper;
use WriteTextAI\WriteTextAI\Model\GeneratedText;
use WriteTextAI\WriteTextAI\Model\AiProductManager;
use WriteTextAI\WriteTextAI\Model\ApiManager;
use WriteTextAI\WriteTextAI\Model\OptionSource\Filter\Fields;
use WriteTextAI\WriteTextAI\Model\ReviewStatus;
use WriteTextAI\WriteTextAI\Helper\Store as StoreHelper;
use WriteTextAI\WriteTextAI\Helper\Html;
use Magento\Framework\Stdlib\DateTime\DateTime;
use WriteTextAI\WriteTextAI\Model\Api\Session as ApiSession;

class Transfer extends Action implements HttpPostActionInterface
{
    public const ADMIN_RESOURCE = 'WriteTextAI_WriteTextAI::transfer';

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

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

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

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

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

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

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

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

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

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

    /**
     * @var DateTime
     */
    protected $dateTime;

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

    /**
     * @var bool
     */
    protected $isAltIncluded = false;

    /**
     * Constructor
     *
     * @param Context $context
     * @param GeneratedText $generatedText
     * @param ProductAction $productAction
     * @param Data $helper
     * @param AiProductManager $aiProductManager
     * @param ProductHelper $productHelper
     * @param ProductRepositoryInterface $productRepository
     * @param ApiManager $apiManager
     * @param ReviewStatus $reviewStatus
     * @param StoreHelper $storeHelper
     * @param Html $htmlHelper
     * @param DateTime $dateTime
     * @param ApiSession $apiSession
     */
    public function __construct(
        Context $context,
        GeneratedText $generatedText,
        ProductAction $productAction,
        Data $helper,
        AiProductManager $aiProductManager,
        ProductHelper $productHelper,
        ProductRepositoryInterface $productRepository,
        ApiManager $apiManager,
        ReviewStatus $reviewStatus,
        StoreHelper $storeHelper,
        Html $htmlHelper,
        DateTime $dateTime,
        ApiSession $apiSession
    ) {
        $this->generatedText = $generatedText;
        $this->productAction = $productAction;
        $this->helper = $helper;
        $this->aiProductManager = $aiProductManager;
        $this->productHelper = $productHelper;
        $this->productRepository = $productRepository;
        $this->apiManager = $apiManager;
        $this->reviewStatus = $reviewStatus;
        $this->storeHelper = $storeHelper;
        $this->htmlHelper = $htmlHelper;
        $this->dateTime = $dateTime;
        $this->apiSession = $apiSession;
        parent::__construct($context);
    }

    /**
     * Execute
     *
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function execute()
    {
        $result = $this->resultFactory->create(ResultFactory::TYPE_JSON);

        $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,
        ];
        
        try {
            $fields = $this->getRequest()->getPost('fields', []);
            $stores = $this->getRequest()->getPost('stores', []);
            $productId = $this->getRequest()->getPost('record_id');
            $storeFilter = $this->getRequest()->getPost('store_id');

            $language = $this->storeHelper->getFormattedLanguage($storeFilter);
            
            // Send initial "Running" notification
            $this->sendTransferNotification(
                $productId,
                $storeFilter,
                'Running',
                [$productId],
                [],
                [],
                $language
            );
            
            $resultData = [
                'success' => false,
                'message' => __(
                    'Transfer failed because there are no generated' .
                    ' texts yet for the products selected.' .
                    ' Generate text first before transferring.'
                )
            ];
            
            $item = $this->generatedText->getTextFields($productId, $storeFilter, true);
            $productFields = $this->removeEmptyAndTransferredFields($item, $fields);

            $images = [];
            $productSelected = $this->productRepository->getById($productId, true, $storeFilter);
            $images = $this->productHelper->getPublishedImages($productSelected, $storeFilter, $language);
            
            if (in_array("alt_text", $fields)) {
                $images = $this->productHelper->getImages($productSelected, $storeFilter, $language);
                $this->isAltIncluded = true;

                /**
                 * Transfer alt text
                 */
                if (!empty($images)) {
                    $this->transferAltText($stores, $productId, $images, $language, $resultData);
                }
            }

            if (!empty($productFields)) {
                $resultData = [
                    'success' => true,
                    'fields' => $productFields
                ];

                $this->generatedText->saveText(
                    $storeFilter,
                    $productId,
                    $item['page_title'],
                    $item['page_description'],
                    $item['product_description'],
                    $item['short_product_description'],
                    $item['open_graph'],
                    $productFields
                );

                /**
                 * Transfer fields
                 */
                foreach ($stores as $storeId) {
                    $this->transfer(
                        $productId,
                        (int)$storeId,
                        $productFields,
                        $images,
                        $item['page_title'],
                        $item['page_description'],
                        $item['product_description'],
                        $item['short_product_description'],
                        $item['open_graph']
                    );
                }
            }

            $textTypes = [];
            foreach ($fields as $selectedField) {
                if (isset($fieldConfig[$selectedField])) {
                    $textTypes[] = $fieldConfig[$selectedField];
                }
            }
            
            $this->reviewStatus->updateReview($productFields, $productId, $stores);
            
            // Send "Completed" notification on success
            if ($resultData['success']) {
                $this->sendTransferNotification(
                    $productId,
                    $storeFilter,
                    'Completed',
                    [],
                    [],
                    [$productId],
                    $language
                );
            } else {
                // Send "Failed" notification if no fields to transfer
                $this->sendTransferNotification(
                    $productId,
                    $storeFilter,
                    'Failed',
                    [],
                    [],
                    [],
                    $language
                );
            }

            $result->setData($resultData);
        } 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.'
                );
            }
            
            // Send "Failed" notification on exception
            if (isset($productId, $storeFilter, $language)) {
                try {
                    $this->sendTransferNotification(
                        $productId,
                        $storeFilter,
                        'Failed',
                        [],
                        [],
                        [],
                        $language
                    );
                } catch (\Exception $notificationException) {
                    // Ignore notification errors
                }
            }

            $result->setData([
                'success' => false,
                'message' => $message
            ]);
        }

        return $result;
    }

    /**
     * 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;
    }

    /**
     * Transfer
     *
     * @param int $productId
     * @param int $storeId
     * @param array $selectedFields
     * @param array $images
     * @param string $pageTitle
     * @param string $pageDescription
     * @param string $productDescription
     * @param string $productShortDescription
     * @param string $openGraph
     * @return void
     */
    private function transfer(
        $productId,
        $storeId,
        $selectedFields,
        $images,
        $pageTitle,
        $pageDescription,
        $productDescription,
        $productShortDescription,
        $openGraph
    ) {
        $mappingSettings = $this->helper->getMappingSettings();

        //$productDescription = $this->productHelper->convertNewLinesToBr($productDescription);
        //$productShortDescription = $this->productHelper->convertNewLinesToBr($productShortDescription);

        $fields = [
            'page_title' => $pageTitle,
            'page_description' => $pageDescription,
            'product_description' => $productDescription,
            'short_product_description' => $productShortDescription,
            'open_graph' => $openGraph
        ];
        
        $toUpdate = [];
        foreach ($fields as $field => $value) {
            if (isset($mappingSettings[$field]) && in_array($field, $selectedFields)) {
                if ($images) {
                    $value = $this->htmlHelper->addAltTextToContentViaPreg($value, $images, $this->isAltIncluded);
                }
                $toUpdate[$mappingSettings[$field]] = $value;
            }
        }

        $this->productAction->updateAttributes(
            [$productId],
            $toUpdate,
            $storeId
        );

        $this->aiProductManager->saveDate($productId, $storeId, 'transferred');
        $this->aiProductManager->saveDate($productId, $storeId, 'reviewed');
    }

    /**
     * Transfer alt text
     *
     * @param array $stores
     * @param int $productId
     * @param array $images
     * @param string $language
     * @param array $resultData
     * @return void
     */
    public function transferAltText($stores, $productId, $images, $language, &$resultData)
    {
        $imagesToUpdate = [];
        foreach ($stores as $storeId) {
            /**
             * get store product to transfer image alt text
             */
            $product = $this->productRepository->getById($productId, true, $storeId);

            $mediaGalleryEntries = $product->getMediaGalleryEntries();
    
            foreach ($images as $image) {
                foreach ($mediaGalleryEntries as $mediaGalleryEntry) {
                    if ($mediaGalleryEntry->getId() == $image['id']) {
                        $mediaGalleryEntry->setLabel($image['writetext_alt']);
                        break;
                    }
                }

                try {
                    $getParams = [
                        "storeId" => $storeId,
                        "language" => $language,
                        "imageId" => $image['id']
                    ];

                    $altText = $this->apiManager->getImage($getParams);

                    if (isset($altText['altText']['id'])) {
                        $resultData['success'] = true;
                        $imagesToUpdate[] = [
                            "storeId" => $storeId,
                            "language" => $language,
                            "imageId" => $altText['imageId'],
                            "textId" => $altText['altText']['id'],
                            "value" => $image['writetext_alt'],
                            "publish" => true,
                            "reviewed" => true
                        ];
                    }
                } catch (\WriteTextAI\WriteTextAI\Exception\ApiException $e) {
                    if ($e->getCode() !== 404) {
                        throw $e;
                    }
                }
            }
        
            $product->setMediaGalleryEntries($mediaGalleryEntries);

            $this->productRepository->save($product);

            $this->aiProductManager->saveDate($productId, $storeId, 'transferred');
            $this->aiProductManager->saveDate($productId, $storeId, 'reviewed');
        }

        if (!empty($imagesToUpdate)) {
            $this->apiManager->batchUpdateAltText(json_encode([
                "images" => $imagesToUpdate
            ]));
        }
    }
    
    /**
     * Send transfer notification for single product transfer
     *
     * @param int $productId
     * @param int $storeFilter
     * @param string $status
     * @param array $queuedIds
     * @param array $runningIds
     * @param array $completedIds
     * @param string $language
     * @return void
     */
    private function sendTransferNotification(
        int $productId,
        int $storeFilter,
        string $status,
        array $queuedIds,
        array $runningIds,
        array $completedIds,
        string $language
    ): void {
        try {
            // Generate a unique transfer ID for single transfers
            $transferId = 'single_' . $productId . '_' . time();
            
            // Get current user (simplified - you might want to get this from session)
            $user = $this->apiSession->getCurrentUser();
            $email = $user->getEmail();
            
            $completed = count($completedIds);
            $failed = ($status === 'Failed') ? 1 : 0;
            $total = 1; // Always 1 for single product transfer
            
            $notificationData = [
                'type' => "8",
                'subType' => 'transfer',
                'id' => $transferId,
                'userName' => $userName,
                'recordType' => 'Product',
                'storeId' => (string) $storeFilter,
                'status' => $status,
                'startTime' => $this->dateTime->gmtDate(),
                'endTime' => $this->dateTime->gmtDate(),
                'queuedIds' => $queuedIds,
                'runningIds' => $runningIds,
                'completedIds' => $completedIds,
                'failedIds' => ($status === 'Failed') ? [$productId] : [],
                'completed' => $completed,
                'failed' => $failed,
                'total' => $total,
                'language' => $language,
                'metaData' => []
            ];
            
            // Send notification with single retry
            try {
                $this->apiManager->sendCustomNotification($notificationData);
            } catch (\Exception $retryException) {
                // Single retry attempt
                $this->apiManager->sendCustomNotification($notificationData);
            }
            
        } catch (\Exception $e) {
            // Don't throw exception - notification failure shouldn't stop the process
        }
    }
}
