<?php

declare(strict_types=1);

namespace App\Tests\Service\Leave;

use App\Service\Leave\LeaveBalanceComputationService;
use App\Service\Leave\SuspensionDaysCalculator;
use DateTimeImmutable;
use PHPUnit\Framework\TestCase;
use ReflectionClass;

/**
 * @internal
 */
final class LeaveBalanceComputationServiceTest extends TestCase
{
    public function testComputeAccruedDaysProratesPartialFirstMonth(): void
    {
        $service = $this->createServiceWithoutConstructor();
        $method  = new ReflectionClass(LeaveBalanceComputationService::class)->getMethod('computeAccruedDays');

        $result = $method->invoke(
            $service,
            25.0,
            25.0 / 12.0,
            new DateTimeImmutable('2025-06-10'),
            new DateTimeImmutable('2026-02-28')
        );

        self::assertEqualsWithDelta(18.125, $result, 0.0001);
    }

    public function testComputeAccruedDaysTotalMatchesAlainCase(): void
    {
        $service = $this->createServiceWithoutConstructor();
        $method  = new ReflectionClass(LeaveBalanceComputationService::class)->getMethod('computeAccruedDays');

        $days = $method->invoke(
            $service,
            25.0,
            25.0 / 12.0,
            new DateTimeImmutable('2025-06-10'),
            new DateTimeImmutable('2026-02-28')
        );
        $saturdays = $method->invoke(
            $service,
            5.0,
            5.0 / 12.0,
            new DateTimeImmutable('2025-06-10'),
            new DateTimeImmutable('2026-02-28')
        );

        self::assertEqualsWithDelta(21.75, $days + $saturdays, 0.0001);
    }

    public function testComputeAccruedDaysIncludesLastDayOfMonthDespiteTimeComponents(): void
    {
        $service = $this->createServiceWithoutConstructor();
        $method  = new ReflectionClass(LeaveBalanceComputationService::class)->getMethod('computeAccruedDays');

        $result = $method->invoke(
            $service,
            25.0,
            25.0 / 12.0,
            new DateTimeImmutable('2026-02-01 12:50:18'),
            new DateTimeImmutable('2026-02-28 00:00:00')
        );

        self::assertEqualsWithDelta(25.0 / 12.0, $result, 0.0001);
    }

    private function createServiceWithoutConstructor(): LeaveBalanceComputationService
    {
        $rc      = new ReflectionClass(LeaveBalanceComputationService::class);
        $service = $rc->newInstanceWithoutConstructor();

        $prop = $rc->getProperty('suspensionDaysCalculator');
        $prop->setValue($service, new SuspensionDaysCalculator());

        return $service;
    }
}
