<?php

namespace KupShop\MessengerBundle\Handler;

use KupShop\MessengerBundle\Message\Envelope\EnvelopeInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Exception\RecoverableMessageHandlingException;
use Symfony\Component\Messenger\Handler\MessageSubscriberInterface;

class EnvelopeHandler implements MessageSubscriberInterface
{
    private LoggerInterface $logger;

    public function __invoke(EnvelopeInterface $envelope): void
    {
        $startTime = getScriptTime();

        // Set logger's web parameter
        putenv("BRANCH={$envelope->getWeb()}");

        $data = json_encode([
            'envelope' => serialize($envelope),
            'last' => $envelope->getRetryCount() <= 0,
        ]);

        $log = function (string $message, $response = null) use ($startTime, $envelope) {
            $type = getenv('DISPATCHER_TYPE');
            $this->logger->notice(
                "AsyncMessage: {$type}: {$message}",
                [
                    'envelope' => get_class($envelope),
                    'type' => $type,
                    'retry' => $envelope->getRetryIndex(),
                    'response' => $response,
                    'duration' => getScriptTime() - $startTime,
                    'callback' => $envelope->getCallback(),
                    'email_id' => $envelope->getId(),
                ]
            );
        };

        // TODO: Odebrat tuhle podmínku, už se přestaly používat timestampy a řeší si to Symfony
        if ($envelope->getUnixTimeStamp() === null || $envelope->getUnixTimeStamp() <= time()) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
            curl_setopt($ch, CURLOPT_URL, $envelope->getCallback());
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HEADER, false);
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Content-Type: application/json',
                isLocalDevelopment() ? 'Cookie: XDEBUG_SESSION=ASYNC;' : '',
            ]);

            $response_raw = curl_exec($ch);
            $response = json_decode($response_raw);

            if (!$response || $response->status !== 200) {
                if (!$response) {
                    $response = [
                        'raw_status' => curl_getinfo($ch, CURLINFO_RESPONSE_CODE),
                        'raw_error_no' => curl_errno($ch),
                        'raw_error' => curl_error($ch),
                        'data_raw' => $response_raw,
                    ];
                }

                if ($envelope->getRetryCount() <= 0) {
                    $log('message has reached the maximum number of repetitions', $response);

                    return;
                }

                $envelope->decreaseRetryCount();
                $log('message failure', $response);

                throw new RecoverableMessageHandlingException(json_encode($response));
            } else {
                $log('message successfully sent', $response);
            }
        } else {
            if (isDevelopment()) {
                // na developmentu se message zahodi, aby to necyklylo
                return;
            }

            throw new RecoverableMessageHandlingException();
        }
    }

    /**
     * @required
     */
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }

    public static function getHandledMessages(): iterable
    {
        return [
            EnvelopeInterface::class,
        ];
    }
}
