<?php

namespace App\EventSubscriber;

use ApiPlatform\Symfony\EventListener\EventPriorities;
use App\Dto\Output\ClientOutput;
use App\Entity\Client;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Mercure\Update;

class MercureSubscriber implements EventSubscriberInterface
{
    private LoggerInterface $logger;

    public function __construct(
        LoggerInterface $logger,
        private readonly HubInterface $hub,
        private readonly KernelInterface $kernel
    )
    {
        $this->logger = $logger;
    }

    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::VIEW => ['onKernelView', EventPriorities::POST_WRITE],
        ];
    }

    public function onKernelView(ViewEvent $event): void
    {
        if ('test' === $this->kernel->getEnvironment()) {
            return;
        }

        $request = $event->getRequest();
        $method = $request->getMethod();

        $clientOutput = $event->getControllerResult();

        if (!in_array($method, ['POST', 'PUT', 'PATCH', 'DELETE'])) {
            return;
        }

        $method = $event->getRequest()->getMethod();

        if (!$clientOutput instanceof ClientOutput || (Request::METHOD_POST !== $method && Request::METHOD_PUT !== $method && Request::METHOD_PATCH !== $method)) {
            return;
        }

        /** @var Client $client */
        $client = $clientOutput->getEntity();

        $data[] = [
            '@id' => '/clients/' . $client->getUuid(),
            'status' => $client->getStatus(),
        ];

        try {
            $update = new Update(
                'clients',
                json_encode($data)
            );

            $this->hub->publish($update);

            $this->logger->info('Evento Mercure disparado', [
                'method' => $method,
                'path' => $request->getPathInfo()
            ]);
        } catch (\Exception $e) {
            $this->logger->error('Error setting method for Mercure update', [
                'method' => $method,
                'path' => $request->getPathInfo(),
                'error' => $e->getMessage(),
            ]);
            return;
        }
    }
}
