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

namespace WriteTextAI\WriteTextAI\Model;

use WriteTextAI\WriteTextAI\Model\BulkKeywordAnalysisRequestsFactory;
use WriteTextAI\WriteTextAI\Api\BulkKeywordAnalysisRequestsRepositoryInterface;
use WriteTextAI\WriteTextAI\Model\ApiManager;
use WriteTextAI\WriteTextAI\Model\Api\Keywords;

class BulkKeywordAnalysisRequestsManager
{
    /**
     * @var BulkKeywordAnalysisRequestsFactory
     */
    protected $BulkKeywordAnalysisRequestsFactory;

    /**
     * @var BulkKeywordAnalysisRequestsRepositoryInterface
     */
    protected $BulkKeywordAnalysisRequestsRepository;

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

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

    /**
     * Constructor
     *
     * @param BulkKeywordAnalysisRequestsFactory $BulkKeywordAnalysisRequestsFactory
     * @param BulkKeywordAnalysisRequestsRepositoryInterface $BulkKeywordAnalysisRequestsRepository
     * @param ApiManager $apiManager
     * @param Keywords $keywords
     */
    public function __construct(
        BulkKeywordAnalysisRequestsFactory $BulkKeywordAnalysisRequestsFactory,
        BulkKeywordAnalysisRequestsRepositoryInterface $BulkKeywordAnalysisRequestsRepository,
        ApiManager $apiManager,
        Keywords $keywords
    ) {
        $this->BulkKeywordAnalysisRequestsFactory = $BulkKeywordAnalysisRequestsFactory;
        $this->BulkKeywordAnalysisRequestsRepository = $BulkKeywordAnalysisRequestsRepository;
        $this->apiManager = $apiManager;
        $this->keywords = $keywords;
    }

    /**
     * Normalize record ID
     *
     * @param mixed $recordId
     * @return string|null
     */
    private function normalizeRecordId($recordId): ?string
    {
        if ($recordId === null) {
            return null;
        }

        if (is_array($recordId)) {
            return implode(',', $recordId);
        }

        return (string) $recordId;
    }

    /**
     * Set bulk request
     *
     * @param string $requestId
     * @param string $user
     * @param string $entityType
     * @param string $storeId
     * @param string $recordId = null
     *
     * @return void
     */
    public function setBulkRequest($requestId, $user, $entityType, $storeId, $recordId = null)
    {
        $BulkKeywordAnalysisRequests = $this->BulkKeywordAnalysisRequestsFactory->create();

        $recordId = $this->normalizeRecordId($recordId);

        $existing = $BulkKeywordAnalysisRequests->getCollection()
            ->addFieldToFilter('user', $user)
            ->getFirstItem();

        if ($existing->getId()) {
            // Update the existing record
            $existing->setRequestId($requestId);
            $existing->setRecordId($recordId);
            $existing->setEntityType($entityType);
            $existing->setStoreId($storeId);
            $BulkKeywordAnalysisRequests = $existing;
        } else {
            // Record not found, create a new one
            $BulkKeywordAnalysisRequests->setData([
                "user" => $user,
                "request_id" => $requestId,
                "record_id" => $recordId,
                "entity_type" => $entityType,
                "store_id" => $storeId
            ]);
        }

        $this->BulkKeywordAnalysisRequestsRepository->save($BulkKeywordAnalysisRequests);
    }

    /**
     * Delete bulk request
     *
     * @param string $requestId
     * @return void
     */
    public function delete($requestId)
    {
        $BulkKeywordAnalysisRequests = $this->BulkKeywordAnalysisRequestsFactory->create();

        $existing = $BulkKeywordAnalysisRequests->getCollection()
            ->addFieldToFilter('request_id', $requestId)
            ->getFirstItem();

        if ($existing->getId()) {
            $this->BulkKeywordAnalysisRequestsRepository->delete($existing);
        }
    }

    /**
     * Delete bulk request by user
     *
     * @param string $user
     * @return void
     */
    public function deleteByUser($user)
    {
        $BulkKeywordAnalysisRequests = $this->BulkKeywordAnalysisRequestsFactory->create();

        $existing = $BulkKeywordAnalysisRequests->getCollection()
            ->addFieldToFilter('user', $user)
            ->getFirstItem();

        if ($existing->getId()) {
            $this->BulkKeywordAnalysisRequestsRepository->delete($existing);
        }
    }

    /**
     * Delete all bulk requests
     *
     * @return void
     */
    public function deleteAll()
    {
        $BulkKeywordAnalysisRequests = $this->BulkKeywordAnalysisRequestsFactory->create();
        $BulkKeywordAnalysisRequests->getCollection()->walk('delete');
    }

    /**
     * Get bulk requests
     *
     * @return bool
     */
    public function getBulkRequest()
    {
        $BulkKeywordAnalysisRequests = $this->BulkKeywordAnalysisRequestsFactory->create();
        $BulkKeywordAnalysisRequests = $BulkKeywordAnalysisRequests->getCollection()->getFirstItem();

        $apiResponse = [];
        $statuses = [];
        $status = [];
        if (!$BulkKeywordAnalysisRequests->getId()) {
            return $statuses;
        }

        try {
            $apiResponse = $this->apiManager->getBulkRequestById($BulkKeywordAnalysisRequests->getRequestId());
            if (!empty($apiResponse)) {
                $failed = isset($apiResponse['failed']) ? $apiResponse['failed'] : 0;
                $completed = $apiResponse['completed'] !== $failed
                    ? $apiResponse['completed'] - $failed
                    : $apiResponse['completed'];

                $status = [
                    'id' => $BulkKeywordAnalysisRequests->getRequestId(),
                    'message' => $this->getMessage(
                        $apiResponse['status'],
                        $apiResponse['failed'] ?? 0,
                        $apiResponse['total'] ?? 0,
                        $apiResponse['runningIds'] ?? []
                    ),
                    'percent' => floor($apiResponse['completed'] / $apiResponse['total'] * 100),
                    'status' => $apiResponse['status'],
                    'queuedIds' => $apiResponse['queuedIds'],
                    'completedIds' => $apiResponse['completedIds'],
                    'completed' => $completed,
                    'user' => $apiResponse['userName'],
                    'subType' => $apiResponse['subType'] ?? 2,
                    'failed' => $apiResponse['failed'] ?? 0,
                    'failedIds' => $apiResponse['failedIds'] ?? [],
                    'runningIds' => $apiResponse['runningIds'] ?? [],
                    'total' => $apiResponse['total'] ?? 0
                ];
            }
        } catch (\WriteTextAI\WriteTextAI\Exception\ApiException $e) {
            if ($e->getCode() === 404) {
                $apiResponse = $this->keywords->getOptimization(
                    $BulkKeywordAnalysisRequests->getStoreId(),
                    $BulkKeywordAnalysisRequests->getRecordId(),
                    $BulkKeywordAnalysisRequests->getEntityType()
                );
                if (isset($apiResponse['status']) && $apiResponse['status'] === 'Failed') {
                    $status = [
                        'id' => $BulkKeywordAnalysisRequests->getRequestId(),
                        'message' => __('Error encountered'),
                        'status' => 'Completed',
                        'percent' => $apiResponse['completedSteps'] / $apiResponse['totalSteps'] * 100,
                        'completed' => 1,
                        'total' => 1,
                        'queuedIds' => [],
                        'completedIds' => [],
                        'user' => $BulkKeywordAnalysisRequests->getUser(),
                        'subType' => 2,
                        'failed' => 1,
                        'failedIds' => [$apiResponse['recordId']],
                        'runningIds' => []
                    ];
                } else {
                    $status = [
                        'id' => $BulkKeywordAnalysisRequests->getRequestId(),
                        'message' => $this->getMessage('Completed', 0, 1, []),
                        'status' => 'Completed',
                        'percent' => 100,
                        'completed' => 1,
                        'total' => 1,
                        'queuedIds' => [],
                        'completedIds' => [],
                        'user' => $BulkKeywordAnalysisRequests->getUser(),
                        'subType' => 2,
                        'failed' => 0,
                        'failedIds' => [],
                        'runningIds' => []
                    ];
                }
            } else {
                throw $e;
            }
        }

        $statuses[] = $status;

        return $statuses;
    }

    /**
     * Get message
     *
     * @param string $requestStatus
     * @param int $failed
     * @param int $total
     * @param array $runningIds
     *
     * @return {String}
     */
    protected function getMessage($requestStatus, $failed, $total, $runningIds)
    {
        $message = '';

        if ($failed === $total && $failed > 0) {
            return sprintf(__('Error encountered'));
        }

        switch ($requestStatus) {
            case 'Pending':
                $message = __('Keyword analysis currently in queue');
                break;
            case 'Completed':
                $message = __('Keyword analysis completed');
                break;
            case 'Cancelling':
                $message = __('Some products have already been queued up for processing.'
                    . ' Cancelling unqueued items only…');
                break;
            case 'Cancelled':
                $message = __('Keyword analysis cancelled');
                break;
            case 'TimedOut':
                $message = __('Keyword analysis timed out');
                break;
            case 'Running':
                $message = __('Keyword analysis currently in progress');
                break;
            default:
                $message = __('Keyword analysis currently in queue');
                break;
        }

        return $message;
    }
}
