<?php

namespace App\Tests\Appointment;

use App\Appointment\Entity\Appointment;
use App\Appointment\Service\AppointmentExpiryService;
use App\Doctor\Entity\Doctor;
use App\Payment\Entity\Payment;
use App\Tests\ApiTestCase;

/**
 * Covers AppointmentExpiryService: stale pending bookings are expired and their
 * pending payments cancelled. Also guards the N+1 fix (batch payment fetch) by
 * exercising several appointments at once.
 */
class AppointmentExpiryServiceTest extends ApiTestCase
{
    public function testExpiresStaleAndCancelsPendingPayments(): void
    {
        $owner = $this->createUser(['ROLE_DOCTOR']);
        $doctor = new Doctor($owner, 'دکتر تست');
        $this->em->persist($doctor);

        $past = time() - 3600;
        $appointments = [];
        for ($i = 0; $i < 5; $i++) {
            $patient = $this->createUser(['ROLE_USER']);
            // distinct past slots — one live booking per (doctor, slot)
            $slotStart = $past - $i * 1000;
            $appt = new Appointment($doctor, $patient, $slotStart, $slotStart + 900);
            $this->em->persist($appt);

            $payment = new Payment($patient, 100_000, 'mellat', 'appointment');
            $payment->setAppointment($appt);
            $this->em->persist($payment);

            $appointments[] = [$appt, $payment];
        }
        $this->em->flush();

        $service = static::getContainer()->get(AppointmentExpiryService::class);
        $count = $service->expireStale();

        // At least our 5 — db_test is shared and may hold other stale pendings
        // from earlier tests/runs; the per-row checks below verify our own 5.
        $this->assertGreaterThanOrEqual(5, $count);

        $this->em->clear();
        foreach ($appointments as [$appt, $payment]) {
            $freshAppt = $this->em->getRepository(Appointment::class)->find($appt->getId());
            $freshPay  = $this->em->getRepository(Payment::class)->find($payment->getId());
            $this->assertSame(Appointment::STATUS_EXPIRED, $freshAppt->getStatus());
            $this->assertSame(Payment::STATUS_CANCELED, $freshPay->getStatus());
        }
    }
}
