<?php

declare(strict_types=1);

namespace App\Tests\Unit\Scolarite\Application\Port;

use App\Scolarite\Application\Port\HomeworkRulesCheckResult;
use App\Scolarite\Application\Port\RuleWarning;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

final class HomeworkRulesCheckResultTest extends TestCase
{
    #[Test]
    public function okReturnsValidNonBlockingResult(): void
    {
        $result = HomeworkRulesCheckResult::ok();

        self::assertTrue($result->estValide());
        self::assertFalse($result->estAvertissement());
        self::assertFalse($result->estBloquant());
        self::assertEmpty($result->warnings);
        self::assertEmpty($result->suggestedDates);
        self::assertFalse($result->bloquant);
    }

    #[Test]
    public function estBloquantReturnsTrueWhenBloquantWithWarnings(): void
    {
        $result = new HomeworkRulesCheckResult(
            warnings: [$this->uneWarning()],
            bloquant: true,
        );

        self::assertTrue($result->estBloquant());
        self::assertFalse($result->estAvertissement());
        self::assertFalse($result->estValide());
    }

    #[Test]
    public function estAvertissementReturnsTrueWhenNonBloquantWithWarnings(): void
    {
        $result = new HomeworkRulesCheckResult(
            warnings: [$this->uneWarning()],
            bloquant: false,
        );

        self::assertTrue($result->estAvertissement());
        self::assertFalse($result->estBloquant());
        self::assertFalse($result->estValide());
    }

    #[Test]
    public function estValideReturnsFalseWhenBloquantWithoutWarnings(): void
    {
        $result = new HomeworkRulesCheckResult(
            warnings: [],
            bloquant: true,
        );

        self::assertTrue($result->estValide());
        self::assertFalse($result->estBloquant());
        self::assertFalse($result->estAvertissement());
    }

    #[Test]
    public function suggestedDatesAreStoredAndAccessible(): void
    {
        $dates = ['2026-03-25', '2026-03-26', '2026-03-27'];

        $result = new HomeworkRulesCheckResult(
            warnings: [$this->uneWarning()],
            bloquant: true,
            suggestedDates: $dates,
        );

        self::assertSame($dates, $result->suggestedDates);
    }

    #[Test]
    public function messagesReturnsWarningMessages(): void
    {
        $result = new HomeworkRulesCheckResult(
            warnings: [
                new RuleWarning('minimum_delay', 'Au moins 3 jours.', ['days' => 3]),
                new RuleWarning('no_monday_after', 'Pas après vendredi 12h.', []),
            ],
            bloquant: false,
        );

        self::assertSame([
            'Au moins 3 jours.',
            'Pas après vendredi 12h.',
        ], $result->messages());
    }

    #[Test]
    public function ruleTypesReturnsWarningRuleTypes(): void
    {
        $result = new HomeworkRulesCheckResult(
            warnings: [
                new RuleWarning('minimum_delay', 'msg1', []),
                new RuleWarning('no_monday_after', 'msg2', []),
            ],
            bloquant: false,
        );

        self::assertSame(['minimum_delay', 'no_monday_after'], $result->ruleTypes());
    }

    #[Test]
    public function toArrayReturnsStructuredWarnings(): void
    {
        $result = new HomeworkRulesCheckResult(
            warnings: [
                new RuleWarning('minimum_delay', 'Au moins 3 jours.', ['days' => 3]),
            ],
            bloquant: true,
        );

        $expected = [
            [
                'ruleType' => 'minimum_delay',
                'message' => 'Au moins 3 jours.',
                'params' => ['days' => 3],
            ],
        ];

        self::assertSame($expected, $result->toArray());
    }

    private function uneWarning(): RuleWarning
    {
        return new RuleWarning(
            ruleType: 'minimum_delay',
            message: 'Le devoir doit être créé au moins 3 jours avant.',
            params: ['days' => 3],
        );
    }
}
