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

namespace WriteTextAI\WriteTextAI\Controller\Adminhtml\CategoriesGrid;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress;
use Magento\Store\Model\Store;
use WriteTextAI\WriteTextAI\Helper\Data;
use WriteTextAI\WriteTextAI\Helper\Store as StoreHelper;
use WriteTextAI\WriteTextAI\Model\ApiManager;
use WriteTextAI\WriteTextAI\Model\OptionSource\Filter\Fields;

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

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

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

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

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

    /**
     * Constructor
     *
     * @param Context $context
     * @param ApiManager $apiManager
     * @param StoreHelper $storeHelper
     * @param RemoteAddress $remoteAddress
     * @param Data $helper
     */
    public function __construct(
        Context $context,
        ApiManager $apiManager,
        StoreHelper $storeHelper,
        RemoteAddress $remoteAddress,
        Data $helper
    ) {
        parent::__construct($context);
        $this->apiManager = $apiManager;
        $this->storeHelper = $storeHelper;
        $this->remoteAddress = $remoteAddress;
        $this->helper = $helper;
    }

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

        try {
            $contentType = $this->getRequest()->getHeader('Content-Type');
            if ($contentType && strpos($contentType, 'application/json') !== false) {
                $content = $this->getRequest()->getContent();
                if ($content) {
                    $lastBrace = strrpos($content, '}');
                    if ($lastBrace !== false && $lastBrace < strlen($content) - 1) {
                        $afterBrace = substr($content, $lastBrace + 1);
                        if (strpos($afterBrace, '&') === 0 || strpos($afterBrace, '?') === 0) {
                            $content = substr($content, 0, $lastBrace + 1);
                        }
                    }

                    $jsonData = json_decode($content, true);
                    if (json_last_error() === JSON_ERROR_NONE && is_array($jsonData)) {
                        foreach ($jsonData as $key => $value) {
                            $this->getRequest()->setPostValue($key, $value);
                        }
                    }
                }
            }

            $params = $this->getRequest()->getParams();
            $filters = (array) ($params['filters'] ?? []);

            $storeId = isset($filters['store_id'])
                ? (int) $filters['store_id']
                : (isset($params['store_id']) ? (int) $params['store_id'] : Store::DEFAULT_STORE_ID);
            $body = [
                'type' => 'Category',
                'storeId' => (string) $storeId,
                'userName' => $params['user'] ?? '',
            ];

            $language = $this->storeHelper->getFormattedLanguage($storeId);
            $body['language'] = $language;
            $body['ipAddress'] = $this->remoteAddress->getRemoteAddress();
            $targetStores = $this->normalizeTargetStores($params['stores'] ?? [], $storeId);
            $body['targetStoreId'] = implode(',', $targetStores);

            $mappedFields = [];
            foreach ((array) ($params['fields'] ?? []) as $field) {
                if (!isset(Fields::CATEGORY_MAPPING[$field])) {
                    continue;
                }
                $mappedFields[] = Fields::CATEGORY_MAPPING[$field];
            }

            $records = [];
            foreach ((array) ($params['queue_ids'] ?? []) as $record) {
                $records[] = [
                    'id' => $record,
                    'fields' => $mappedFields
                ];
            }

            $body['records'] = $records;

            if ($this->helper->getForceQueueSeconds()) {
                $body['developmentQueueWaitTimeInSeconds'] = $this->helper->getForceQueueSeconds();
            }

            $apiResponse = $this->apiManager->transferViaApi($body);

            $result = [
                'success' => true,
                'api_params' => $body,
                'api_response' => $apiResponse
            ];
        } catch (\WriteTextAI\WriteTextAI\Exception\UnauthorizedException $e) {
            $result = [
                'success' => false,
                'unauthorized' => true,
                'login_url' => $this->_url->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,
                'message' => $message
            ];
        }

        $response->setData($result);
        return $response;
    }

    /**
     * Normalize target stores for transfer.
     *
     * @param array|mixed $stores
     * @param int $fallbackStoreId
     * @return array
     */
    private function normalizeTargetStores($stores, int $fallbackStoreId): array
    {
        $stores = array_values(array_unique(array_filter(
            array_map(
                static function ($storeId): string {
                    return (string) (int) $storeId;
                },
                (array) $stores
            ),
            static function (string $storeId): bool {
                return $storeId !== '';
            }
        )));

        if (empty($stores)) {
            return [(string) $fallbackStoreId];
        }

        if (in_array('0', $stores, true) && count($stores) > 1) {
            $stores = array_values(array_filter(
                $stores,
                static function (string $storeId): bool {
                    return $storeId !== '0';
                }
            ));
        }

        return $stores;
    }
}
