<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CmsBundle\Tests\Filter;

use Ferienpass\CmsBundle\Filter\WhenPresetResolver;
use PHPUnit\Framework\TestCase;

/**
 * The resolver maps the user-facing `Wann?` chip presets to a concrete date
 * window the existing date filters can apply. Tests pin down weekend edge
 * cases (Sat/Sun behave differently from Mon–Fri) and the month/week boundary.
 */
final class WhenPresetResolverTest extends TestCase
{
    public function testHeute(): void
    {
        $today = new \DateTimeImmutable('2026-05-20'); // Wed
        [$von, $bis] = WhenPresetResolver::resolve('heute', $today);

        self::assertSame('2026-05-20', $von->format('Y-m-d'));
        self::assertSame('2026-05-20', $bis->format('Y-m-d'));
    }

    public function testWochenendeFromMonday(): void
    {
        $today = new \DateTimeImmutable('2026-05-18'); // Mon
        [$von, $bis] = WhenPresetResolver::resolve('wochenende', $today);

        // Upcoming Saturday & Sunday of the same week.
        self::assertSame('2026-05-23', $von->format('Y-m-d'));
        self::assertSame('2026-05-24', $bis->format('Y-m-d'));
    }

    public function testWochenendeFromFriday(): void
    {
        $today = new \DateTimeImmutable('2026-05-22'); // Fri
        [$von, $bis] = WhenPresetResolver::resolve('wochenende', $today);

        self::assertSame('2026-05-23', $von->format('Y-m-d'));
        self::assertSame('2026-05-24', $bis->format('Y-m-d'));
    }

    public function testWochenendeFromSaturdayCoversTodayAndSunday(): void
    {
        $today = new \DateTimeImmutable('2026-05-23'); // Sat
        [$von, $bis] = WhenPresetResolver::resolve('wochenende', $today);

        // Don't strand the user on a Sat — include today.
        self::assertSame('2026-05-23', $von->format('Y-m-d'));
        self::assertSame('2026-05-24', $bis->format('Y-m-d'));
    }

    public function testWochenendeFromSundayCoversOnlyToday(): void
    {
        $today = new \DateTimeImmutable('2026-05-24'); // Sun
        [$von, $bis] = WhenPresetResolver::resolve('wochenende', $today);

        // From + to are both Sunday; the user gets results for today and
        // nothing past.
        self::assertSame('2026-05-24', $von->format('Y-m-d'));
        self::assertSame('2026-05-24', $bis->format('Y-m-d'));
    }

    public function testWocheFromWednesdayCoversTodayThroughSunday(): void
    {
        $today = new \DateTimeImmutable('2026-05-20'); // Wed
        [$von, $bis] = WhenPresetResolver::resolve('woche', $today);

        self::assertSame('2026-05-20', $von->format('Y-m-d'));
        self::assertSame('2026-05-24', $bis->format('Y-m-d'));
    }

    public function testWocheFromSundayCoversOnlyToday(): void
    {
        $today = new \DateTimeImmutable('2026-05-24'); // Sun
        [$von, $bis] = WhenPresetResolver::resolve('woche', $today);

        self::assertSame('2026-05-24', $von->format('Y-m-d'));
        self::assertSame('2026-05-24', $bis->format('Y-m-d'));
    }

    public function testMonatCoversTodayThroughLastDayOfMonth(): void
    {
        $today = new \DateTimeImmutable('2026-02-10'); // Feb 10
        [$von, $bis] = WhenPresetResolver::resolve('monat', $today);

        self::assertSame('2026-02-10', $von->format('Y-m-d'));
        self::assertSame('2026-02-28', $bis->format('Y-m-d'));
    }

    public function testMonatLeapYear(): void
    {
        $today = new \DateTimeImmutable('2024-02-10'); // 2024 is a leap year
        [$von, $bis] = WhenPresetResolver::resolve('monat', $today);

        self::assertSame('2024-02-29', $bis->format('Y-m-d'));
    }

    public function testUnknownPresetReturnsNulls(): void
    {
        [$von, $bis] = WhenPresetResolver::resolve('whatever', new \DateTimeImmutable('2026-05-20'));

        self::assertNull($von);
        self::assertNull($bis);
    }

    public function testCustomPresetIsNotResolvedHere(): void
    {
        // "eigen" is handled by the controller — the resolver isn't
        // called for it. Still, an unknown preset returns nulls.
        [$von, $bis] = WhenPresetResolver::resolve('eigen', new \DateTimeImmutable('2026-05-20'));

        self::assertNull($von);
        self::assertNull($bis);
    }
}
