<?php

namespace App\Tests\Doctor;

use App\Clinic\Entity\Clinic;
use App\Doctor\Entity\Doctor;
use App\Specialty\Entity\Specialty;
use App\Tests\ApiTestCase;

/**
 * The clinic doctor-list endpoint must hydrate each doctor's specialties in the
 * list query, not lazily per doctor. The query count must therefore be constant
 * regardless of how many doctors the clinic has.
 */
class ClinicDoctorListNPlusOneTest extends ApiTestCase
{
    private function makeClinicWithDoctors(int $doctorCount): Clinic
    {
        $clinic = new Clinic($this->createUser(['ROLE_CLINIC']));
        $this->em->persist($clinic);

        for ($i = 0; $i < $doctorCount; $i++) {
            $doctor = new Doctor($this->createUser(['ROLE_DOCTOR']), "دکتر $i");
            $slug = 'sp-' . bin2hex(random_bytes(6));
            $specialty = new Specialty('تخصص', $slug);
            $this->em->persist($specialty);
            $doctor->getSpecialties()->add($specialty);
            $this->em->persist($doctor);
            $clinic->getDoctors()->add($doctor);
        }
        $this->em->flush();

        return $clinic;
    }

    public function testQueryCountDoesNotGrowWithDoctorCount(): void
    {
        // Keep one kernel/container across both requests so the shared query
        // logger (doctrine.debug_data_holder) stays consistent.
        $this->client->disableReboot();

        $small = $this->makeClinicWithDoctors(2);
        $large = $this->makeClinicWithDoctors(6);

        $qSmall = $this->countQueries(fn () => $this->client->request(
            'GET', '/api/v1/clinic/doctor-list/' . $small->getUuid()
        ));
        $this->assertSame(200, $this->responseCode());

        $qLarge = $this->countQueries(fn () => $this->client->request(
            'GET', '/api/v1/clinic/doctor-list/' . $large->getUuid()
        ));
        $this->assertSame(200, $this->responseCode());

        // No N+1: 4 extra doctors must not add ~4 extra queries. A tiny slack
        // absorbs one-off warmup variance; the N+1 signal (≈ +doctorCount) is
        // far larger than the slack.
        $this->assertLessThanOrEqual($qSmall + 1, $qLarge, "N+1: query count grew from $qSmall to $qLarge with more doctors");

        // Correctness preserved: specialties are present in the payload.
        $body = json_decode($this->client->getResponse()->getContent(), true);
        $this->assertNotEmpty($body['data']['data'][0]['specialties']);
    }
}
