<?php

declare(strict_types=1);

namespace App\Tests\Unit\Administration\Application\Query\HasGradesInPeriod;

use App\Administration\Application\Port\GradeExistenceChecker;
use App\Administration\Application\Query\HasGradesInPeriod\HasGradesInPeriodHandler;
use App\Administration\Application\Query\HasGradesInPeriod\HasGradesInPeriodQuery;
use App\Administration\Domain\Model\SchoolClass\AcademicYearId;
use App\Shared\Domain\Tenant\TenantId;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

/**
 * Tests for HasGradesInPeriodHandler.
 *
 * Key invariants:
 * - Delegates to GradeExistenceChecker port
 * - Returns boolean indicating grade presence
 * - Correctly passes tenantId, academicYearId, and periodSequence
 */
final class HasGradesInPeriodHandlerTest extends TestCase
{
    private const string TENANT_ID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';
    private const string ACADEMIC_YEAR_ID = '550e8400-e29b-41d4-a716-446655440010';

    #[Test]
    public function returnsTrueWhenGradesExist(): void
    {
        $checker = $this->createMock(GradeExistenceChecker::class);
        $checker->expects(self::once())
            ->method('hasGradesInPeriod')
            ->with(
                self::callback(static fn (TenantId $t) => (string) $t === self::TENANT_ID),
                self::callback(static fn (AcademicYearId $a) => (string) $a === self::ACADEMIC_YEAR_ID),
                1,
            )
            ->willReturn(true);

        $handler = new HasGradesInPeriodHandler($checker);

        $query = new HasGradesInPeriodQuery(
            tenantId: self::TENANT_ID,
            academicYearId: self::ACADEMIC_YEAR_ID,
            periodSequence: 1,
        );

        $result = ($handler)($query);

        self::assertTrue($result);
    }

    #[Test]
    public function returnsFalseWhenNoGrades(): void
    {
        $checker = $this->createMock(GradeExistenceChecker::class);
        $checker->method('hasGradesInPeriod')->willReturn(false);

        $handler = new HasGradesInPeriodHandler($checker);

        $query = new HasGradesInPeriodQuery(
            tenantId: self::TENANT_ID,
            academicYearId: self::ACADEMIC_YEAR_ID,
            periodSequence: 2,
        );

        $result = ($handler)($query);

        self::assertFalse($result);
    }

    #[Test]
    public function passesCorrectPeriodSequence(): void
    {
        $checker = $this->createMock(GradeExistenceChecker::class);
        $checker->expects(self::once())
            ->method('hasGradesInPeriod')
            ->with(
                self::anything(),
                self::anything(),
                3,
            )
            ->willReturn(false);

        $handler = new HasGradesInPeriodHandler($checker);

        $query = new HasGradesInPeriodQuery(
            tenantId: self::TENANT_ID,
            academicYearId: self::ACADEMIC_YEAR_ID,
            periodSequence: 3,
        );

        ($handler)($query);
    }
}
