<?php

namespace App\Tests\Insurance;

use App\ClinicService\Entity\ServiceItem;
use App\ClinicService\Entity\ServiceSection;
use App\Doctor\Entity\Doctor;
use App\Insurance\Entity\TenantInsurance;
use App\Tests\ApiTestCase;

/**
 * The «این خدمت شامل بیمه می‌شود» switch was removed from the service form, so
 * ServiceItem::insuranceCovered is no longer set by hand. Saving a coverage row
 * is now the single source of truth and must keep the flag in sync — session
 * pricing (CreateStep) reads it.
 */
class ServiceCoverageSyncsItemFlagTest extends ApiTestCase
{
    /** @return array{0: \App\Auth\Entity\User, 1: TenantInsurance, 2: ServiceItem} */
    private function makeDoctorContractAndItem(): array
    {
        $owner  = $this->createUser(['ROLE_DOCTOR']);
        $doctor = new Doctor($owner, 'دکتر تست همگام‌سازی');
        $this->em->persist($doctor);
        $this->em->flush();

        $contract = new TenantInsurance(TenantInsurance::TYPE_DOCTOR, $doctor->getId(), 1);
        $section  = new ServiceSection(TenantInsurance::TYPE_DOCTOR, $doctor->getId(), 'بخش');
        $this->em->persist($contract);
        $this->em->persist($section);
        $this->em->flush();

        $item = new ServiceItem($section, 'سرم ۵۰۰cc');
        $this->em->persist($item);
        $this->em->flush();

        return [$owner, $contract, $item];
    }

    /** EntityManager بین requestها clear می‌شود، پس پرچم باید دوباره از DB خوانده شود. */
    private function isInsured(string $uuid): bool
    {
        return $this->em->getRepository(ServiceItem::class)
            ->findOneBy(['uuid' => $uuid])
            ->isInsuranceCovered();
    }

    private function putCoverage(
        \App\Auth\Entity\User $owner,
        TenantInsurance $contract,
        ServiceItem $item,
        bool $covered,
    ): void {
        $this->authJson(
            'PUT',
            '/api/v1/billing/tenant-insurances/' . $contract->getUuid() . '/service-coverage',
            $owner,
            ['service_item_uuid' => $item->getUuid(), 'covered' => $covered, 'coverage_percent' => 70],
        );
    }

    public function testSavingCoveredCoverageMarksItemAsInsured(): void
    {
        [$owner, $contract, $item] = $this->makeDoctorContractAndItem();
        $this->assertFalse($item->isInsuranceCovered(), 'یک خدمت تازه نباید تحت پوشش باشد');

        $this->putCoverage($owner, $contract, $item, true);

        $this->assertSame(200, $this->responseCode());
        $this->assertTrue($this->isInsured($item->getUuid()));
    }

    public function testRemovingTheOnlyCoverageClearsTheFlag(): void
    {
        [$owner, $contract, $item] = $this->makeDoctorContractAndItem();
        $uuid = $item->getUuid();

        $this->putCoverage($owner, $contract, $item, true);
        $this->assertTrue($this->isInsured($uuid));

        $this->putCoverage($owner, $contract, $item, false);

        $this->assertSame(200, $this->responseCode());
        $this->assertFalse($this->isInsured($uuid));
    }

    public function testFlagStaysSetWhileAnotherContractStillCoversTheItem(): void
    {
        [$owner, $first, $item] = $this->makeDoctorContractAndItem();
        $uuid = $item->getUuid();

        $second = new TenantInsurance(TenantInsurance::TYPE_DOCTOR, $first->getEntityId(), 2);
        $this->em->persist($second);
        $this->em->flush();

        $this->putCoverage($owner, $first, $item, true);
        $this->putCoverage($owner, $second, $item, true);

        $this->putCoverage($owner, $first, $item, false);

        $this->assertTrue($this->isInsured($uuid), 'قرارداد دوم هنوز پوشش دارد');
    }

    public function testUnknownServiceItemIsRejected(): void
    {
        [$owner, $contract] = $this->makeDoctorContractAndItem();

        $this->authJson(
            'PUT',
            '/api/v1/billing/tenant-insurances/' . $contract->getUuid() . '/service-coverage',
            $owner,
            ['service_item_uuid' => 'no-such-uuid', 'covered' => true],
        );

        $this->assertSame(422, $this->responseCode());
    }
}
