<?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
{
    private BotDetectorInterface $botDetector;
    private CookieConsentRepository $cookieConsentRepository;
    private EntityManagerInterface $entityManager;

    public function __construct(
        BotDetectorInterface $botDetector,
        CookieConsentRepository $cookieConsentRepository,
        EntityManagerInterface $entityManager
    ) {
        $this->botDetector = $botDetector;
        $this->cookieConsentRepository = $cookieConsentRepository;
        $this->entityManager = $entityManager;
    }

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

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

        if (!$request->cookies->has('gdpr_analytics')) {
            $this->handleEntry($request);
            return;
        }

        $this->handleEntry($request, $request->cookies->get('gdpr_analytics') === 'true');
    }

    private function handleEntry(Request $request, ?bool $consent = null)
    {
        $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')));
    }
}
