<?php

namespace App\Tests\Clinic;

use App\Auth\Entity\UserActiveContext;
use App\Clinic\Entity\Clinic;
use App\Clinic\Entity\ClinicDoctorPermission;
use App\Doctor\Entity\Doctor;
use App\Tests\ApiTestCase;

/**
 * مجوزهای پزشکِ عضوِ کلینیک (ClinicDoctorPermission) باید مثل منشی در API enforce
 * شوند: منبعی که کلینیک به پزشکِ عضو نداده ۴۰۳؛ منبعِ داده‌شده ۲۰۰. پزشکِ مستقل
 * (بدون محیطِ کلینیک) هرگز محدود نمی‌شود.
 */
class ClinicDoctorPermissionEnforcementTest extends ApiTestCase
{
    /** @return array{0: \App\Auth\Entity\User, 1: ClinicDoctorPermission} */
    private function makeMemberDoctor(): array
    {
        $owner  = $this->createUser(['ROLE_CLINIC']);
        $clinic = new Clinic($owner);
        $this->em->persist($clinic);

        $doctorUser = $this->createUser(['ROLE_DOCTOR']);
        $doctor     = new Doctor($doctorUser, 'دکتر عضو');
        $this->em->persist($doctor);
        $clinic->getDoctors()->add($doctor);

        $perm = new ClinicDoctorPermission($clinic, $doctor);
        $this->em->persist($perm);
        // محیطِ فعالِ پزشک = کلینیک، تا memberClinicId او را به کلینیک ببرد.
        $this->em->persist(new UserActiveContext($doctorUser, $clinic->getUuid(), 'clinic'));

        return [$doctorUser, $perm];
    }

    public function testInventoryDeniedByDefault(): void
    {
        // DEFAULT_PERMISSIONS: inventory.* = false
        [$doctorUser] = $this->makeMemberDoctor();
        $this->em->flush();

        $this->authJson('GET', '/api/v1/inventory-items', $doctorUser);
        $this->assertSame(403, $this->responseCode());
    }

    public function testInventoryAllowedWhenGranted(): void
    {
        [$doctorUser, $perm] = $this->makeMemberDoctor();
        $perm->mergePermissions(['resources' => ['inventory' => ['view' => true]]]);
        $this->em->flush();

        $this->authJson('GET', '/api/v1/inventory-items', $doctorUser);
        $this->assertSame(200, $this->responseCode());
    }

    public function testStaffDeniedByDefault(): void
    {
        [$doctorUser] = $this->makeMemberDoctor();
        $this->em->flush();

        $this->authJson('GET', '/api/v1/staff', $doctorUser);
        $this->assertSame(403, $this->responseCode());
    }

    public function testStaffCreateDeniedButViewGranted(): void
    {
        [$doctorUser, $perm] = $this->makeMemberDoctor();
        $perm->mergePermissions(['resources' => ['staff' => ['view' => true, 'create' => false]]]);
        $this->em->flush();

        $this->authJson('GET', '/api/v1/staff', $doctorUser);
        $this->assertSame(200, $this->responseCode());

        $this->authJson('POST', '/api/v1/staff', $doctorUser, ['full_name' => 'خانم تست']);
        $this->assertSame(403, $this->responseCode());
    }

    public function testIndependentDoctorIsNotRestricted(): void
    {
        // پزشکِ مستقل: نه عضوِ کلینیک، نه محیطِ کلینیک → روی دادهٔ شخصیِ خودش آزاد.
        $doctorUser = $this->createUser(['ROLE_DOCTOR']);
        $this->em->persist(new Doctor($doctorUser, 'دکتر مستقل'));
        $this->em->flush();

        // inventory برای منابعِ ClinicDoctorPermission پیش‌فرض false است، اما این پزشک
        // اصلاً عضوِ کلینیک نیست، پس ClinicDoctorAccessChecker او را محدود نمی‌کند.
        $this->authJson('GET', '/api/v1/inventory-items', $doctorUser);
        $this->assertSame(200, $this->responseCode());
    }
}
