<?php
declare(strict_types=1);
namespace Autogedal\AwbRetry\Model\Queue;

use Autogedal\AwbRetry\Model\AwbErrorLogManager;
use Magento\Framework\MessageQueue\PublisherInterface;
use Psr\Log\LoggerInterface;
class RetryRequestPublisher
{
    public const TOPIC_NAME = 'autogedal.awb_retry.process';
    public const RETRY_MODE_MANUAL = 'manual';
    public const RETRY_MODE_AUTOMATIC = 'automatic';

    public function __construct(
        private readonly PublisherInterface $publisher,
        private readonly AwbErrorLogManager $errorLogManager,
        private readonly LoggerInterface $logger
    ) {
    }

    public function queue(int $errorLogId, string $retryMode = self::RETRY_MODE_MANUAL, array $extraPayload = []): void
    {
        try {
            $this->errorLogManager->markQueued($errorLogId);
            $this->publisher->publish(
                self::TOPIC_NAME,
                $this->encodeMessage($errorLogId, $retryMode, $extraPayload)
            );
        } catch (\Throwable $throwable) {
            try {
                $this->errorLogManager->markFailed($errorLogId, $throwable->getMessage());
            } catch (\Throwable $markFailedException) {
                $this->logger->error(
                    (string) __('AWB retry log %1 could not be reverted to failed state after queue publish error: %2', $errorLogId, $markFailedException->getMessage()),
                    ['exception' => $markFailedException]
                );
            }

            throw $throwable;
        }
    }

    private function encodeMessage(int $errorLogId, string $retryMode, array $extraPayload = []): string
    {
        return (string) json_encode(array_merge([
            'error_log_id' => $errorLogId,
            'retry_mode' => $retryMode,
        ], $extraPayload), JSON_THROW_ON_ERROR);
    }
}
