<?php

declare(strict_types=1);

namespace App\Tests\Unit\Administration\Domain\Model\SchoolBranding;

use App\Administration\Domain\Model\SchoolBranding\BrandColor;
use App\Administration\Domain\Model\SchoolBranding\ContrastValidator;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

final class ContrastValidatorTest extends TestCase
{
    private ContrastValidator $validator;

    protected function setUp(): void
    {
        $this->validator = new ContrastValidator();
    }

    #[Test]
    public function blackOnWhitePassesWcagAA(): void
    {
        $result = $this->validator->validate(
            new BrandColor('#000000'),
            new BrandColor('#FFFFFF'),
        );

        self::assertGreaterThanOrEqual(4.5, $result->ratio);
        self::assertTrue($result->passesAA);
        self::assertTrue($result->passesAALarge);
        self::assertNull($result->suggestion);
    }

    #[Test]
    public function whiteOnBlackPassesWcagAA(): void
    {
        $result = $this->validator->validate(
            new BrandColor('#FFFFFF'),
            new BrandColor('#000000'),
        );

        self::assertGreaterThanOrEqual(4.5, $result->ratio);
        self::assertTrue($result->passesAA);
        self::assertTrue($result->passesAALarge);
    }

    #[Test]
    public function blackOnWhiteHasMaxContrast(): void
    {
        $result = $this->validator->validate(
            new BrandColor('#000000'),
            new BrandColor('#FFFFFF'),
        );

        self::assertEqualsWithDelta(21.0, $result->ratio, 0.1);
    }

    #[Test]
    public function sameColorHasMinContrast(): void
    {
        $result = $this->validator->validate(
            new BrandColor('#3B82F6'),
            new BrandColor('#3B82F6'),
        );

        self::assertEqualsWithDelta(1.0, $result->ratio, 0.01);
        self::assertFalse($result->passesAA);
        self::assertFalse($result->passesAALarge);
    }

    #[Test]
    public function lightGrayOnWhiteFailsWcagAA(): void
    {
        $result = $this->validator->validate(
            new BrandColor('#CCCCCC'),
            new BrandColor('#FFFFFF'),
        );

        self::assertLessThan(4.5, $result->ratio);
        self::assertFalse($result->passesAA);
    }

    #[Test]
    public function lightGrayOnWhitePassesAALarge(): void
    {
        $result = $this->validator->validate(
            new BrandColor('#767676'),
            new BrandColor('#FFFFFF'),
        );

        self::assertGreaterThanOrEqual(3.0, $result->ratio);
        self::assertTrue($result->passesAALarge);
    }

    #[Test]
    public function failingContrastSuggestsAlternative(): void
    {
        $result = $this->validator->validate(
            new BrandColor('#CCCCCC'),
            new BrandColor('#FFFFFF'),
        );

        self::assertFalse($result->passesAA);
        self::assertNotNull($result->suggestion);
    }

    #[Test]
    public function passingContrastDoesNotSuggestAlternative(): void
    {
        $result = $this->validator->validate(
            new BrandColor('#000000'),
            new BrandColor('#FFFFFF'),
        );

        self::assertTrue($result->passesAA);
        self::assertNull($result->suggestion);
    }

    #[Test]
    public function suggestedAlternativePassesWcagAA(): void
    {
        $result = $this->validator->validate(
            new BrandColor('#CCCCCC'),
            new BrandColor('#FFFFFF'),
        );

        self::assertNotNull($result->suggestion);

        $suggestionResult = $this->validator->validate(
            $result->suggestion,
            new BrandColor('#FFFFFF'),
        );

        self::assertTrue($suggestionResult->passesAA);
    }

    #[Test]
    public function blueOnWhiteCalculatesCorrectRatio(): void
    {
        $result = $this->validator->validate(
            new BrandColor('#3B82F6'),
            new BrandColor('#FFFFFF'),
        );

        self::assertGreaterThan(1.0, $result->ratio);
        self::assertLessThan(21.0, $result->ratio);
    }
}
