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

namespace WriteTextAI\WriteTextAI\Model;

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

/**
 * @api
 */
class BulkRequestsManager
{
    /**
     * @var ApiManager
     */
    protected $apiManager;

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

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

    /**
     * Get bulk generate status
     *
     * @return string
     */
    public function getBulkRequests()
    {
        $statuses = [];
        $status = [];
        $apiResponse = $this->apiManager->getBulkStatus();
        if (empty($apiResponse)) {
            return $statuses;
        }
        foreach ($apiResponse as $response) {
            if ($response['total'] === 1) {
                continue;
            }
            $failed = isset($response['failed']) ? $response['failed'] : 0;
            $completed = $response['completed'] !== $failed
                ? $response['completed'] - $failed
                : $response['completed'];

            $status = [
                'id' => $response['id'],
                'recordType' => $response['recordType'],
                'storeId' => $response['storeId'],
                'percent' => floor($response['completed'] / $response['total'] * 100),
                'startTime' => $response['startTime'],
                'endTime' => $response['endTime'],
                'estimatedEndTime' => $response['estimatedEndTime'],
                'status' => $response['status'],
                'queuedIds' => $response['queuedIds'],
                'completedIds' => $response['completedIds'],
                'failedIds' => $response['failedIds'] ?? [],
                'runningIds' => $response['runningIds'] ?? [],
                'completed' => $completed,
                'user' => $response['userName'],
                'subType' => $response['subType'] ?? 2,
                'failed' => $response['failed'] ?? 0,
                'total' => $response['total'] ?? 0,
                'language' => $response['language'] ?? 'en-US',
            ];
            if (isset($response['failedTransferIds']) && count($response['failedTransferIds']) > 0) {
                foreach ($response['failedTransferIds'] as $id) {
                    $status['failedIds'][$id] = $id; // dedupe by key
                }
                $status['failedIds'] = array_values($status['failedIds']); // normalize
                $status['failed'] = count($status['failedIds']);
            }
            $status['message'] = $this->getMessage(
                $response['subType'] ?? 0,
                $response['status'],
                $response['failed'] ?? 0,
                $response['total'] ?? 0,
                $response['runningIds'] ?? [],
                $this->calculateRemainingTime(
                    $response['estimatedEndTime'],
                    $response['startTime']
                )
            );
            if ($response['subType'] === 3) {
                $status['transfer'] = true;
            }
            $statuses[] = $status;
        }
        return $statuses;
    }

    /**
     * Get message
     *
     * @param int $subType
     * @param string $status
     * @param int $failed
     * @param int $total
     * @param array $runningIds
     * @param array $remaining
     * @return string
     */
    public function getMessage(
        $subType,
        $status,
        $failed,
        $total,
        $runningIds,
        $remaining
    ) {
        $message = '';
        $isMinutes = $remaining['is_minutes'] ?? false;
        switch ($subType) {
            case 0:
                if ($failed === $total && $failed > 0) {
                    return __('Error encountered');
                }
                switch ($status) {
                    case 'Pending':
                        $message = __('Queued for text generation...')
                            . '<br>'
                            . __('Waiting for other processes to finish before starting.');
                        break;
                    case 'Running':
                        if (count($runningIds) === 0) {
                            $message = __('Generating text...');
                            break;
                        }
                        
                        if ($remaining['is_minutes']) {
                            $text = __('Generating text... (Estimated time remaining %s minute/s)');
                        } else {
                            $text = __('Generating text... (Estimated time remaining %s second/s)');
                        }
                        $message = sprintf($text, $remaining['remaining']);
                        break;
                    case 'Completed':
                        $message = __('WriteText.ai is done generating text for your selected products.');
                        if ($failed > 0) {
                            $message = __('Error encountered');
                        }
                        break;
                    case 'Cancelling':
                        $message = __('Cancelling pending items only...')
                            . '<br>'
                            . __('Items already in progress will continue.');
                        break;
                    case 'Cancelled':
                        $message = __('This process has been cancelled.');
                        break;
                    case 'TimedOut':
                        $message = __('WriteText.ai is currently experiencing a high '
                            . 'volume of requests and has timed out.');
                        break;
                    case 'Failed':
                        $message = __('Error encountered');
                        break;
                    default:
                        $message = __('Generating text...');
                        break;
                }
                break;
            case 1:
                if ($failed === $total && $failed > 0) {
                    return sprintf(__('Full automation failed, you can restart to try again.'));
                }
                switch ($status) {
                    case 'Pending':
                        $message = __('Queued for full automation...')
                            . '<br>'
                            . __('Waiting for other processes to finish before starting.');
                        break;
                    case 'Running':
                        if ($remaining['remaining'] === 0) {
                            $message = __('Running full automation...');
                            break;
                        }
                        if ($isMinutes) {
                            $text = __('Running full automation... (Estimated time remaining %s minute/s)');
                        } else {
                            $text = __('Running full automation... (Estimated time remaining %s second/s)');
                        }
                        $message = sprintf($text, $remaining['remaining']);
                        break;
                    case 'Completed':
                        $message = __('WriteText.ai has completed full automation for your selected products.');
                        if ($failed > 0) {
                            $message = __('Error encountered');
                        }
                        break;
                    case 'Cancelling':
                        $message = __('Cancelling pending items only...')
                            . '<br>'
                            . __('Items already in progress will continue.');
                        break;
                    case 'Cancelled':
                        $message = __('This process has been cancelled.');
                        break;
                    case 'TimedOut':
                        $message = __('WriteText.ai is currently experiencing a high '
                            . 'volume of requests and has timed out.');
                        break;
                    case 'Failed':
                        $message = __('Error encountered');
                        break;
                }
                break;
            case 2:
                if ($failed === $total && $failed > 0) {
                    return __('Error encountered');
                }
                switch ($status) {
                    case 'Pending':
                        $message = __('Queued for keyword analysis...')
                            . '<br>'
                            . __('Waiting for other processes to finish before starting.');
                        break;
                    case 'Completed':
                        $message = __('Keyword analysis completed');
                        if ($failed > 0) {
                            $message = __('Error encountered');
                        }
                        break;
                    case 'Cancelling':
                        $message = __('Cancelling pending items only...')
                            . '<br>'
                            . __('Items already in progress will continue.');
                        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;
                    case 'Failed':
                        $message = __('Error encountered');
                        // fall through
                    default:
                        $message = __('Keyword analysis currently in progress');
                        break;
                }
                break;
            case 3:
                if ($failed === $total && $failed > 0) {
                    return __('Error encountered');
                }
                switch ($status) {
                    case 'Pending':
                        $message = __('Queued for transfer...')
                            . '<br>'
                            . __('Waiting for other processes to finish before starting.');
                        break;
                    case 'Completed':
                        $message = __('Done transferring text for your selected products.');
                        if ($failed > 0) {
                            $message = __('Error encountered');
                        }
                        break;
                    case 'Cancelling':
                        $message = __('Cancelling pending items only...')
                            . '<br>'
                            . __('Items already in progress will continue.');
                        break;
                    case 'Cancelled':
                        $message = __('Transfer cancelled');
                        break;
                    case 'TimedOut':
                        $message = __('Transfer timed out');
                        break;
                    case 'Running':
                        $message = __('Transferring text...');
                        break;
                    case 'Failed':
                        $message = __('Error encountered');
                        // fall through
                    default:
                        $message = __('Transferring text...');
                        break;
                }
                break;
            default:
                break;
        }
        return $message;
    }

    /**
     * Calculate remaining time
     *
     * @param string $estimatedEndTime
     * @param string $startTime
     * @return array
     */
    protected function calculateRemainingTime($estimatedEndTime, $startTime)
    {
        $remaining = 0;
        $isMinutes = false;
        $result = [];
        $currentDatetime;
        $interval;

        if ($estimatedEndTime !== null && $startTime !== null) {
            $estimatedEndTime = new \DateTime($estimatedEndTime);
            $startTime = new \DateTime($startTime);
            $interval = $estimatedEndTime->getTimestamp() - $startTime->getTimestamp();
            // Convert seconds to minutes if it's more than or equal to 60 seconds
            $remaining = ceil($interval / 60);

            if ($remaining >= 60) {
                // Convert minutes to hours if it's more than or equal to 60 minutes
                $remaining = ceil($remaining / 60);
                $isMinutes = true;
            }
        }

        $result['remaining'] = $remaining;
        $result['is_minutes'] = $isMinutes;

        return $result;
    }
}
