<?php

namespace App\Tests\MessageHandler;

use App\Entity\AnalyticsEvent;
use App\Entity\AnalyticsUniqId;
use App\Entity\User;
use App\Message\AnalyticsMessage;
use App\MessageHandler\AnalyticsMessageHandler;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use PHPUnit\Framework\TestCase;

class AnalyticsMessageHandlerTest extends TestCase
{
    private function createVisitor(): AnalyticsUniqId
    {
        $visitor = new AnalyticsUniqId();
        $visitor->setUid('test-uid');
        $visitor->setHash('test-hash');
        $visitor->setIpHash('test-ip');
        $visitor->setUserAgent('test-ua');

        return $visitor;
    }

    public function testPageViewCreatesEvent(): void
    {
        $visitor = $this->createVisitor();

        $visitorRepo = $this->createMock(EntityRepository::class);
        $visitorRepo->method('findOneBy')->with(['uid' => 'test-uid'])->willReturn($visitor);

        $em = $this->createMock(EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($visitorRepo);
        $em->expects(self::once())->method('persist')->with(self::callback(
            fn (AnalyticsEvent $e) => 'page_view' === $e->getEventName() && '/test' === $e->getUrl() && 'Test' === $e->getTitle()
        ));
        $em->expects(self::once())->method('flush');

        $handler = new AnalyticsMessageHandler($em);
        $handler(new AnalyticsMessage('test-uid', 'page_view', [
            'url' => '/test',
            'title' => 'Test',
            'referrer' => 'https://google.com',
        ]));
    }

    public function testSetUserLinksVisitorToUser(): void
    {
        $visitor = $this->createVisitor();
        $user = new User();
        $user->setEmail('test@test.fr');
        $user->setFirstName('Test');
        $user->setLastName('User');
        $user->setPassword('hashed');

        $visitorRepo = $this->createMock(EntityRepository::class);
        $visitorRepo->method('findOneBy')->willReturn($visitor);

        $userRepo = $this->createMock(EntityRepository::class);
        $userRepo->method('find')->with(42)->willReturn($user);

        $em = $this->createMock(EntityManagerInterface::class);
        $em->method('getRepository')->willReturnCallback(function (string $class) use ($visitorRepo, $userRepo) {
            return AnalyticsUniqId::class === $class ? $visitorRepo : $userRepo;
        });
        $em->expects(self::once())->method('flush');

        $handler = new AnalyticsMessageHandler($em);
        $handler(new AnalyticsMessage('test-uid', 'set_user', ['userId' => 42]));

        self::assertSame($user, $visitor->getUser());
    }

    public function testUnknownVisitorIsIgnored(): void
    {
        $repo = $this->createMock(EntityRepository::class);
        $repo->method('findOneBy')->willReturn(null);

        $em = $this->createMock(EntityManagerInterface::class);
        $em->method('getRepository')->willReturn($repo);
        $em->expects(self::never())->method('persist');
        $em->expects(self::never())->method('flush');

        $handler = new AnalyticsMessageHandler($em);
        $handler(new AnalyticsMessage('unknown', 'page_view', ['url' => '/']));
    }
}
