<?php

namespace App\Tests\Representation;

use App\Representation\Service\JalaliDateService;
use PHPUnit\Framework\TestCase;

/**
 * تبدیل شمسی ↔ میلادی.
 *
 * پیاده‌سازی دستیِ قبلی غلط بود و کسی متوجه نشده بود چون هیچ تستی نداشت:
 * `gregorianToJalali(2026, 7, 30)` مقدار `[3006, 7, 3]` می‌داد. این تست همان
 * نقطه‌هایی را قفل می‌کند که آن باگ را لو دادند.
 */
class JalaliDateServiceTest extends TestCase
{
    private JalaliDateService $service;

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

    /** نوروز لنگرِ همه‌چیز است: ۱ فروردین ۱۴۰۵ = ۲۱ مارس ۲۰۲۶. */
    public function testNowruzAnchor(): void
    {
        self::assertSame([2026, 3, 21], $this->service->jalaliToGregorian(1405, 1, 1));
        self::assertSame([1405, 1, 1], $this->service->gregorianToJalali(2026, 3, 21));
    }

    public function testRoundTripAcrossTheYear(): void
    {
        foreach ([[1405, 1, 1], [1405, 5, 8], [1405, 6, 31], [1405, 7, 1], [1405, 12, 29]] as [$jy, $jm, $jd]) {
            [$gy, $gm, $gd] = $this->service->jalaliToGregorian($jy, $jm, $jd);

            self::assertSame(
                [$jy, $jm, $jd],
                $this->service->gregorianToJalali($gy, $gm, $gd),
                sprintf('رفت‌وبرگشت %d/%d/%d', $jy, $jm, $jd),
            );
        }
    }

    /** مهر اول نیم‌سال دوم است و ماه‌هایش ۳۰ روزه — مرز ۶/۳۱ به ۷/۱. */
    public function testSixthMonthHasThirtyOneDaysAndSeventhStartsNextDay(): void
    {
        [$gy, $gm, $gd] = $this->service->jalaliToGregorian(1405, 6, 31);
        $end = (new \DateTimeImmutable(sprintf('%04d-%02d-%02d', $gy, $gm, $gd)))->modify('+1 day');

        self::assertSame(
            [1405, 7, 1],
            $this->service->gregorianToJalali(
                (int) $end->format('Y'),
                (int) $end->format('n'),
                (int) $end->format('j'),
            ),
        );
    }

    public function testJalaliYearOfAKnownTimestamp(): void
    {
        $timestamp = (new \DateTimeImmutable('2026-07-30 12:00:00', new \DateTimeZone('Asia/Tehran')))->getTimestamp();

        self::assertSame(1405, $this->service->jalaliYear($timestamp));
        self::assertSame(5, $this->service->jalaliMonth($timestamp));
    }

    /** بازهٔ سال باید نوروز تا آخر اسفند باشد، نه چیزی در قرن سی‌ویکم. */
    public function testYearRangeStartsAtNowruz(): void
    {
        [$start, $end] = $this->service->jalaliYearRange(1405);

        self::assertSame('2026-03-21', date('Y-m-d', $start));
        self::assertGreaterThan($start, $end);
        self::assertSame(1405, $this->service->jalaliYear($start));
    }
}
