<?php

declare(strict_types=1);

namespace App\Tests\Unit\Scolarite\Domain\Model\Schedule;

use App\Scolarite\Domain\Exception\CreneauHoraireInvalideException;
use App\Scolarite\Domain\Model\Schedule\TimeSlot;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

final class TimeSlotTest extends TestCase
{
    #[Test]
    public function createsValidTimeSlot(): void
    {
        $timeSlot = new TimeSlot('08:00', '09:00');

        self::assertSame('08:00', $timeSlot->startTime);
        self::assertSame('09:00', $timeSlot->endTime);
    }

    #[Test]
    public function throwsWhenEndTimeBeforeStartTime(): void
    {
        $this->expectException(CreneauHoraireInvalideException::class);

        new TimeSlot('10:00', '09:00');
    }

    #[Test]
    public function throwsWhenEndTimeEqualsStartTime(): void
    {
        $this->expectException(CreneauHoraireInvalideException::class);

        new TimeSlot('08:00', '08:00');
    }

    #[Test]
    public function throwsWhenDurationLessThanFiveMinutes(): void
    {
        $this->expectException(CreneauHoraireInvalideException::class);

        new TimeSlot('08:00', '08:04');
    }

    #[Test]
    public function acceptsFiveMinuteDuration(): void
    {
        $timeSlot = new TimeSlot('08:00', '08:05');

        self::assertSame('08:00', $timeSlot->startTime);
        self::assertSame('08:05', $timeSlot->endTime);
    }

    #[Test]
    public function overlapsReturnsTrueWhenTimesOverlap(): void
    {
        $slot1 = new TimeSlot('08:00', '09:00');
        $slot2 = new TimeSlot('08:30', '09:30');

        self::assertTrue($slot1->overlaps($slot2));
        self::assertTrue($slot2->overlaps($slot1));
    }

    #[Test]
    public function overlapsReturnsFalseWhenTimesDoNotOverlap(): void
    {
        $slot1 = new TimeSlot('08:00', '09:00');
        $slot2 = new TimeSlot('09:00', '10:00');

        self::assertFalse($slot1->overlaps($slot2));
        self::assertFalse($slot2->overlaps($slot1));
    }

    #[Test]
    public function overlapsReturnsTrueWhenOneContainsOther(): void
    {
        $slot1 = new TimeSlot('08:00', '12:00');
        $slot2 = new TimeSlot('09:00', '10:00');

        self::assertTrue($slot1->overlaps($slot2));
        self::assertTrue($slot2->overlaps($slot1));
    }

    #[Test]
    public function overlapsReturnsFalseWhenAdjacent(): void
    {
        $slot1 = new TimeSlot('08:00', '09:00');
        $slot2 = new TimeSlot('09:00', '10:00');

        self::assertFalse($slot1->overlaps($slot2));
    }

    #[Test]
    public function equalsReturnsTrueForSameTimes(): void
    {
        $slot1 = new TimeSlot('08:00', '09:00');
        $slot2 = new TimeSlot('08:00', '09:00');

        self::assertTrue($slot1->equals($slot2));
    }

    #[Test]
    public function equalsReturnsFalseForDifferentTimes(): void
    {
        $slot1 = new TimeSlot('08:00', '09:00');
        $slot2 = new TimeSlot('08:00', '10:00');

        self::assertFalse($slot1->equals($slot2));
    }

    #[Test]
    public function durationInMinutesReturnsCorrectValue(): void
    {
        $timeSlot = new TimeSlot('08:00', '09:30');

        self::assertSame(90, $timeSlot->durationInMinutes());
    }
}
