<?php

namespace App\Tests\Appointment;

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

/**
 * Clinic-workflow additions on Appointment: following_up/salon statuses,
 * service section/item + staff relations, deposit fields, reserve flag,
 * and rescheduleTo keeping active_slot_key consistent.
 */
class AppointmentWorkflowFieldsTest extends ApiTestCase
{
    private function makeDoctor(): Doctor
    {
        $doctor = new Doctor($this->createUser(['ROLE_DOCTOR']), 'دکتر تست');
        $this->em->persist($doctor);
        $this->em->flush();

        return $doctor;
    }

    private function newBooking(Doctor $doctor, int $start): Appointment
    {
        $a = $this->newAppointment($doctor, $this->createUser(), $start, $start + 1_800);
        $this->em->persist($a);
        $this->em->flush();

        return $a;
    }

    public function testDayOfWorkflowTransitions(): void
    {
        $a = $this->newBooking($this->makeDoctor(), time() + 86_400);

        $a->transitionTo(Appointment::STATUS_CONFIRMED);
        $a->transitionTo(Appointment::STATUS_FOLLOWING_UP);
        $a->transitionTo(Appointment::STATUS_SALON);
        $a->transitionTo(Appointment::STATUS_COMPLETED);
        $this->em->flush();

        self::assertSame(Appointment::STATUS_COMPLETED, $a->getStatus());
    }

    public function testPendingCannotJumpToSalon(): void
    {
        $a = $this->newBooking($this->makeDoctor(), time() + 86_400);

        $this->expectException(\LogicException::class);
        $a->transitionTo(Appointment::STATUS_SALON);
    }

    public function testWorkflowFieldsPersistAndSerialize(): void
    {
        $a = $this->newBooking($this->makeDoctor(), time() + 86_400);

        $a->setDepositRequired(true)
          ->setDepositAmountRials(5_000_000);
        $a->rescheduleTo($a->getSlotStart(), $a->getSlotEnd(), true);
        $this->em->flush();
        $this->em->clear();

        $reloaded = $this->em->getRepository(Appointment::class)->findOneBy(['uuid' => $a->getUuid()]);
        $arr      = $reloaded->toArray();

        self::assertTrue($arr['deposit_required']);
        self::assertSame(5_000_000, $arr['deposit_amount_rials']);
        self::assertTrue($arr['is_reserve']);
        self::assertNull($arr['service_section']);
        self::assertNull($arr['staff']);
    }

    public function testRescheduleFreesTheOldSlot(): void
    {
        $doctor = $this->makeDoctor();
        $start  = time() + 86_400;

        $first = $this->newBooking($doctor, $start);
        $first->rescheduleTo($start + 3_600, $start + 5_400);
        $this->em->flush();

        // old slot must be free again — a new live booking on it succeeds
        $second = $this->newBooking($doctor, $start);
        self::assertNotNull($second->getId());
    }
}
