<?php

namespace App\Tests\Doctor;

use App\Appointment\Entity\WeeklySchedule;
use App\Clinic\Entity\Clinic;
use App\Doctor\Entity\Doctor;
use App\Doctor\Entity\DoctorAddress;
use App\Tests\ApiTestCase;

/**
 * The public doctor payload must aggregate booking state across every weekly
 * schedule (personal + each clinic). A doctor whose personal schedule is empty
 * but who is bookable at a clinic used to be reported as «نوبت‌دهی غیرفعال».
 */
class DoctorBookingStateAggregationTest extends ApiTestCase
{
    /** پاسخ عمومی doctor به شکل {data:{data:{…}}} است. */
    private function doctorPayload(): array
    {
        $json = json_decode($this->client->getResponse()->getContent(), true) ?? [];

        return $json['data']['data'] ?? [];
    }

    private function week(array $session): array
    {
        $days = array_fill_keys(range(0, 6), ['sessions' => []]);
        $days[0] = ['sessions' => [$session]];

        return $days;
    }

    private function session(bool $active, int $locationId): array
    {
        return [
            'active'               => $active,
            'location_id'          => $locationId,
            'start_time'           => '09:00',
            'end_time'             => '13:00',
            'duration_per_patient' => 20,
        ];
    }

    /** @return array{doctor: Doctor, personal: WeeklySchedule, clinic: WeeklySchedule} */
    private function makeDoctorWithInactivePersonalAndClinic(): array
    {
        $doctor = new Doctor($this->createUser(['ROLE_USER', 'ROLE_DOCTOR']), 'دکتر تجمیع');
        $this->em->persist($doctor);

        $clinic = new Clinic($this->createUser(['ROLE_USER', 'ROLE_CLINIC']));
        $clinic->setName('کلینیک تجمیع');
        $clinic->getDoctors()->add($doctor);
        $this->em->persist($clinic);
        $this->em->flush();

        $personalAddress = DoctorAddress::forDoctor($doctor);
        $this->em->persist($personalAddress);
        $clinicAddress = DoctorAddress::forClinic($clinic->getId());
        $this->em->persist($clinicAddress);
        $this->em->flush();

        $personal = $this->newWeeklySchedule($doctor, $this->week($this->session(false, $personalAddress->getId())));
        $clinicSchedule = $this->newWeeklySchedule(
            $doctor,
            $this->week($this->session(true, $clinicAddress->getId())),
            $clinic
        );
        $this->em->persist($personal);
        $this->em->persist($clinicSchedule);
        $this->em->flush();

        return ['doctor' => $doctor, 'personal' => $personal, 'clinic' => $clinicSchedule];
    }

    public function testClinicScheduleKeepsDoctorBookableDespiteEmptyPersonalSchedule(): void
    {
        ['doctor' => $doctor] = $this->makeDoctorWithInactivePersonalAndClinic();

        $this->client->request('GET', '/api/v1/doctor/' . $doctor->getUuid());
        $data = $this->doctorPayload();

        $this->assertTrue($data['active']);
        $this->assertStringContainsString('شنبه', $data['free_turn']);
    }

    public function testAllSchedulesDisabledReportsBookingDisabled(): void
    {
        ['doctor' => $doctor, 'personal' => $personal, 'clinic' => $clinicSchedule]
            = $this->makeDoctorWithInactivePersonalAndClinic();

        $personal->setMeta(['online_booking_enabled' => false]);
        $clinicSchedule->setMeta(['online_booking_enabled' => false]);
        $this->em->flush();

        $this->client->request('GET', '/api/v1/doctor/' . $doctor->getUuid());
        $data = $this->doctorPayload();

        $this->assertFalse($data['active']);
        $this->assertSame('نوبت‌دهی آنلاین غیرفعال است', $data['free_turn']);
    }

    public function testDetailExposesRawIsActiveFlagForDeactivatedDoctor(): void
    {
        ['doctor' => $doctor] = $this->makeDoctorWithInactivePersonalAndClinic();

        // فلگ روشن (پیش‌فرض): is_active باید true باشد.
        $this->client->request('GET', '/api/v1/doctor/' . $doctor->getUuid());
        $this->assertTrue($this->doctorPayload()['is_active']);

        // ادمین پزشک را غیرفعال می‌کند → is_active=false (مبنای 404 در سایت عمومی).
        $doctor->setActiveDoctorAppointment(false);
        $this->em->flush();

        $this->client->request('GET', '/api/v1/doctor/' . $doctor->getUuid());
        $data = $this->doctorPayload();
        $this->assertFalse($data['is_active']);
        $this->assertFalse($data['active']);
    }

    public function testDisabledClinicScheduleDoesNotMaskActivePersonalSchedule(): void
    {
        ['doctor' => $doctor, 'personal' => $personal, 'clinic' => $clinicSchedule]
            = $this->makeDoctorWithInactivePersonalAndClinic();

        // برعکسِ سناریوی اول: شخصی فعال، کلینیکی خاموش — ترتیب ردیف‌ها نباید مهم باشد.
        $personal->setSetting($this->week($this->session(true, 0)));
        $clinicSchedule->setMeta(['online_booking_enabled' => false]);
        $this->em->flush();

        $this->client->request('GET', '/api/v1/doctor/' . $doctor->getUuid());
        $data = $this->doctorPayload();

        $this->assertTrue($data['active']);
        $this->assertStringContainsString('شنبه', $data['free_turn']);
    }
}
