<?php

namespace AutoAdmin\Bundle\Admin\EventListener;

use AutoAdmin\Bundle\Admin\Entity\CookieConsent;
use AutoAdmin\Bundle\Admin\Repository\CookieConsentRepository;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Setono\BotDetectionBundle\BotDetector\BotDetectorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class CookieConsentSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private readonly BotDetectorInterface $botDetector,
        private readonly CookieConsentRepository $cookieConsentRepository,
        private readonly EntityManagerInterface $entityManager
    ) {
    }

    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::REQUEST => ['onKernelRequest', -20],
        ];
    }

    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();
        if (
            !$event->isMainRequest()
            || $request->isXmlHttpRequest()
            || $this->botDetector->isBotRequest($request)
        ) {
            return;
        }

        if (!$request->cookies->has('gdpr_consent')) {
            $this->handleEntry($request);

            return;
        }

        $consentData = json_decode($request->cookies->get('gdpr_consent'), true);
        $analyticsConsent = $consentData['analytics_storage'] ?? null;

        $this->handleEntry($request, ($analyticsConsent === 'granted'));
    }

    private function handleEntry(Request $request, ?bool $consent = null): void
    {
        $hash = $this->handleHash($request);

        $cookieConsent = $this->cookieConsentRepository->findOneBy(['hash' => $hash]);
        if (!$cookieConsent) {
            $cookieConsent = new CookieConsent();
            $cookieConsent->setHash($hash);
        }

        $cookieConsent->setType($consent);

        $this->entityManager->persist($cookieConsent);
        $this->entityManager->flush();
    }

    private function handleHash(Request $request): string
    {
        $userAgent = $request->headers->get('User-Agent');
        $ip = $request->getClientIp();
        $date = new DateTime();

        return md5(sprintf('%s-%s-%s', $userAgent, $ip, $date->format('Y-m-d')));
    }
}
