<?php

namespace App\Tests\Entity;

use App\Entity\Category;
use App\Entity\Event;
use PHPUnit\Framework\TestCase;

class CategoryTest extends TestCase
{
    public function testNewCategoryDefaults(): void
    {
        $category = new Category();

        self::assertNull($category->getId());
        self::assertNull($category->getName());
        self::assertNull($category->getEvent());
        self::assertSame(0, $category->getPosition());
        self::assertFalse($category->isHidden());
        self::assertInstanceOf(\DateTimeImmutable::class, $category->getCreatedAt());
        self::assertInstanceOf(\DateTimeImmutable::class, $category->getStartAt());
        self::assertInstanceOf(\DateTimeImmutable::class, $category->getEndAt());
    }

    public function testSetAndGetName(): void
    {
        $category = new Category();
        $result = $category->setName('VIP');

        self::assertSame('VIP', $category->getName());
        self::assertSame($category, $result);
    }

    public function testSetAndGetPosition(): void
    {
        $category = new Category();
        $result = $category->setPosition(3);

        self::assertSame(3, $category->getPosition());
        self::assertSame($category, $result);
    }

    public function testSetAndGetStartAt(): void
    {
        $category = new Category();
        $date = new \DateTimeImmutable('2026-06-01 10:00:00');
        $result = $category->setStartAt($date);

        self::assertSame($date, $category->getStartAt());
        self::assertSame($category, $result);
    }

    public function testSetAndGetEndAt(): void
    {
        $category = new Category();
        $date = new \DateTimeImmutable('2026-06-15 18:00:00');
        $result = $category->setEndAt($date);

        self::assertSame($date, $category->getEndAt());
        self::assertSame($category, $result);
    }

    public function testSetAndGetIsHidden(): void
    {
        $category = new Category();
        $result = $category->setIsHidden(true);

        self::assertTrue($category->isHidden());
        self::assertSame($category, $result);

        $category->setIsHidden(false);
        self::assertFalse($category->isHidden());
    }

    public function testSetEventSetsEndAtToOneDayBeforeEventStart(): void
    {
        $event = new Event();
        $event->setStartAt(new \DateTimeImmutable('+60 days'));

        $category = new Category();
        $result = $category->setEvent($event);

        self::assertSame($event, $category->getEvent());
        self::assertSame($category, $result);

        $expectedEnd = $event->getStartAt()->modify('-1 day');
        self::assertSame(
            $expectedEnd->format('Y-m-d H:i:s'),
            $category->getEndAt()->format('Y-m-d H:i:s')
        );
    }

    public function testSetEventWithPastStartAtUsesEventStartAt(): void
    {
        $event = new Event();
        $event->setStartAt(new \DateTimeImmutable('-1 day'));

        $category = new Category();
        $category->setEvent($event);

        // endCandidate (-2 days) < startAt (now), so endAt = event.startAt
        self::assertSame(
            $event->getStartAt()->format('Y-m-d H:i:s'),
            $category->getEndAt()->format('Y-m-d H:i:s')
        );
    }

    public function testSetEventNull(): void
    {
        $category = new Category();
        $originalEnd = $category->getEndAt();

        $category->setEvent(null);

        self::assertNull($category->getEvent());
        self::assertSame($originalEnd, $category->getEndAt());
    }

    public function testIsActiveWhenNowIsBetweenStartAndEnd(): void
    {
        $category = new Category();
        $category->setStartAt(new \DateTimeImmutable('-1 hour'));
        $category->setEndAt(new \DateTimeImmutable('+1 hour'));

        self::assertTrue($category->isActive());
    }

    public function testIsActiveWhenNowIsBeforeStart(): void
    {
        $category = new Category();
        $category->setStartAt(new \DateTimeImmutable('+1 hour'));
        $category->setEndAt(new \DateTimeImmutable('+2 hours'));

        self::assertFalse($category->isActive());
    }

    public function testIsActiveWhenNowIsAfterEnd(): void
    {
        $category = new Category();
        $category->setStartAt(new \DateTimeImmutable('-2 hours'));
        $category->setEndAt(new \DateTimeImmutable('-1 hour'));

        self::assertFalse($category->isActive());
    }

    public function testGetCreatedAt(): void
    {
        $before = new \DateTimeImmutable();
        $category = new Category();
        $after = new \DateTimeImmutable();

        self::assertGreaterThanOrEqual($before, $category->getCreatedAt());
        self::assertLessThanOrEqual($after, $category->getCreatedAt());
    }

    public function testSetEventWithNullStartAt(): void
    {
        $event = new Event();

        $category = new Category();
        $originalEnd = $category->getEndAt();
        $category->setEvent($event);

        // Event has no startAt set, so endAt should not change
        self::assertNull($event->getStartAt());
        self::assertSame($originalEnd, $category->getEndAt());
    }
}
