<?php

namespace App\Tests\Patient;

use App\Appointment\Entity\Appointment;
use App\Doctor\Entity\Doctor;
use App\Patient\Entity\PatientRecord;
use App\Tests\ApiTestCase;

/**
 * List Patient Appointments (تب نوبت‌ها): shape (incl. version), ordering,
 * empty boundary, and ownership scoping.
 */
class PatientAppointmentsTest extends ApiTestCase
{
    /** @return array{0: \App\Auth\Entity\User, 1: Doctor, 2: PatientRecord} */
    private function recordFor(): array
    {
        $owner  = $this->createUser(['ROLE_DOCTOR']);
        $doctor = new Doctor($owner, 'دکتر ژیلا فتحی');
        $this->em->persist($doctor);
        $this->em->flush();

        $patient = $this->createUser(['ROLE_USER']);
        $record  = new PatientRecord('doctor', $doctor->getId(), $patient, 'doctor', $doctor->getId());
        $this->em->persist($record);
        $this->em->flush();

        return [$owner, $doctor, $record];
    }

    private function appointment(Doctor $doctor, PatientRecord $record, int $slotStart): Appointment
    {
        $appt = $this->newAppointment($doctor, $record->getUser(), $slotStart, $slotStart + 1800);
        $this->em->persist($appt);
        $this->em->flush();

        return $appt;
    }

    public function testListReturnsShapeWithVersion(): void
    {
        [$owner, $doctor, $record] = $this->recordFor();
        $this->appointment($doctor, $record, 1_754_000_000);

        $list = $this->authJson('GET', '/api/v1/patient/' . $record->getUuid() . '/appointments', $owner);
        self::assertSame(200, $this->responseCode());
        self::assertCount(1, $list['data']);

        $row = $list['data'][0];
        foreach (['uuid', 'starts_at', 'ends_at', 'status', 'version', 'doctor_name'] as $key) {
            self::assertArrayHasKey($key, $row);
        }
        self::assertSame(1, $row['version']);
        self::assertSame('pending', $row['status']);
        self::assertSame('دکتر ژیلا فتحی', $row['doctor_name']);
        self::assertSame(1_754_000_000, $row['starts_at']);
    }

    public function testSortedByStartDescending(): void
    {
        [$owner, $doctor, $record] = $this->recordFor();
        $this->appointment($doctor, $record, 1_754_000_000);
        $this->appointment($doctor, $record, 1_755_000_000);

        $list = $this->authJson('GET', '/api/v1/patient/' . $record->getUuid() . '/appointments', $owner);
        self::assertCount(2, $list['data']);
        self::assertSame(1_755_000_000, $list['data'][0]['starts_at']);
        self::assertSame(1_754_000_000, $list['data'][1]['starts_at']);
    }

    public function testEmptyWhenNoAppointments(): void
    {
        [$owner, , $record] = $this->recordFor();

        $list = $this->authJson('GET', '/api/v1/patient/' . $record->getUuid() . '/appointments', $owner);
        self::assertSame(200, $this->responseCode());
        self::assertCount(0, $list['data']);
    }

    public function testNotFoundForUnknownRecord(): void
    {
        [$owner] = $this->recordFor();
        $this->authJson('GET', '/api/v1/patient/00000000-0000-0000-0000-000000000000/appointments', $owner);
        self::assertSame(404, $this->responseCode());
    }

    public function testOwnershipScoped(): void
    {
        [, $doctor, $record] = $this->recordFor();
        $this->appointment($doctor, $record, 1_754_000_000);

        [$other] = $this->recordFor();
        $this->authJson('GET', '/api/v1/patient/' . $record->getUuid() . '/appointments', $other);
        self::assertSame(404, $this->responseCode());
    }
}
