<?php

namespace App\Tests\Resource;

use App\Resource\Entity\ResourceException;

/**
 * تعداد کوئریِ محاسبهٔ ساعت آزاد نباید با تعداد روزها رشد کند.
 *
 * بدون این تست، اولین refactor می‌تواند یک کوئری داخل حلقهٔ روز بگذارد و پاسخِ
 * ۹۰ روزه بی‌صدا به صدها کوئری برسد — چیزی که فقط در تولید دیده می‌شود.
 */
class AvailabilityQueryCountTest extends ResourceTestCase
{
    private const TEHRAN = 'Asia/Tehran';

    private function midnight(string $expression): int
    {
        return (new \DateTimeImmutable($expression, new \DateTimeZone(self::TEHRAN)))
            ->setTime(0, 0)
            ->getTimestamp();
    }

    public function testQueryCountDoesNotGrowWithTheNumberOfDays(): void
    {
        // یک کرنل برای هر دو اندازه‌گیری، وگرنه reboot دادهٔ کوئری‌ها را می‌ریزد.
        $this->client->disableReboot();

        [$user, , $address] = $this->clinicWithAddress();
        $type    = $this->resourceType($address, 'operator', 'اپراتور');
        $created = $this->createResource($user, $address, $type, ['name' => 'اپراتور پرشیفت']);
        $uuid    = $created['data']['uuid'];

        $shifts = [];
        foreach (range(0, 6) as $day) {
            $shifts[$day] = [['start_minute' => 540, 'end_minute' => 1020]];
        }
        $this->authJson('PUT', "/api/v1/resource/$uuid/calendar", $user, ['days' => $shifts]);

        $this->authJson('PUT', "/api/v1/branch/{$address->getUuid()}/working-hours", $user, [
            'days' => array_fill_keys(range(0, 6), [['start_minute' => 480, 'end_minute' => 1200]]),
        ]);

        $start = $this->midnight('next saturday');

        $this->authJson('POST', "/api/v1/resource/$uuid/exception", $user, [
            'type'      => ResourceException::TYPE_LEAVE,
            'starts_at' => $start + 2 * 86400,
            'ends_at'   => $start + 3 * 86400,
        ]);

        $oneDay = $this->countQueries(fn () => $this->authJson(
            'GET',
            "/api/v1/resource/$uuid/availability?from=$start&to=$start",
            $user,
        ));
        self::assertSame(200, $this->responseCode());

        $ninetyDays = $this->countQueries(fn () => $this->authJson(
            'GET',
            sprintf('/api/v1/resource/%s/availability?from=%d&to=%d', $uuid, $start, $start + 89 * 86400),
            $user,
        ));
        self::assertSame(200, $this->responseCode());

        self::assertSame(
            $oneDay,
            $ninetyDays,
            "محاسبهٔ یک روز $oneDay کوئری می‌خواهد و ۹۰ روز $ninetyDays — یعنی کوئری داخل حلقهٔ روز رفته",
        );
    }
}
