<?php

namespace App\Tests\Resource;

class ResourceTypeTest extends ResourceTestCase
{
    public function testTypeIsCreatedAndListedWithUsageCount(): void
    {
        [$user, , $address] = $this->clinicWithAddress();

        $created = $this->authJson('POST', '/api/v1/resource-types', $user, [
            'code' => 'laser',
            'name' => 'دستگاه لیزر',
        ]);

        self::assertSame(201, $this->responseCode(), json_encode($created, JSON_UNESCAPED_UNICODE));
        self::assertFalse($created['data']['is_system']);
        self::assertSame(0, $created['data']['resources_count']);

        $this->createResource($user, $address, $this->typeEntity($created['data']['uuid']));

        $list = $this->authJson('GET', '/api/v1/resource-types', $user);
        self::assertSame(1, $list['data'][0]['resources_count']);
    }

    public function testDuplicateCodeInOneEnvironmentIsRejected(): void
    {
        [$user] = $this->clinicWithAddress();

        $this->authJson('POST', '/api/v1/resource-types', $user, ['code' => 'laser', 'name' => 'لیزر']);
        $body = $this->authJson('POST', '/api/v1/resource-types', $user, ['code' => 'laser', 'name' => 'لیزر دوم']);

        self::assertSame(422, $this->responseCode());
        self::assertSame('code', $body['errors'][0]['field']);
    }

    /** همان کد در محیط دیگر مجاز است — یکتایی per محیط است، نه سراسری. */
    public function testSameCodeInAnotherEnvironmentIsAllowed(): void
    {
        [$user] = $this->clinicWithAddress();
        $this->authJson('POST', '/api/v1/resource-types', $user, ['code' => 'laser', 'name' => 'لیزر']);

        [$otherUser] = $this->clinicWithAddress('شعبهٔ دیگر');
        $this->authJson('POST', '/api/v1/resource-types', $otherUser, ['code' => 'laser', 'name' => 'لیزر']);

        self::assertSame(201, $this->responseCode());
    }

    public function testInvalidCodeIsRejected(): void
    {
        [$user] = $this->clinicWithAddress();

        $body = $this->authJson('POST', '/api/v1/resource-types', $user, ['code' => 'Laser Device', 'name' => 'x']);

        self::assertSame(422, $this->responseCode());
        self::assertSame('code', $body['errors'][0]['field']);
    }

    public function testTypeInUseCannotBeDeleted(): void
    {
        [$user, , $address] = $this->clinicWithAddress();
        $created = $this->authJson('POST', '/api/v1/resource-types', $user, ['code' => 'laser', 'name' => 'لیزر']);
        $this->createResource($user, $address, $this->typeEntity($created['data']['uuid']));

        $body = $this->authJson('DELETE', "/api/v1/resource-type/{$created['data']['uuid']}", $user);

        self::assertSame(422, $this->responseCode());
        self::assertStringContainsString('1 منبع', $body['errors'][0]['message']);
    }

    public function testUnusedTypeIsDeleted(): void
    {
        [$user] = $this->clinicWithAddress();
        $created = $this->authJson('POST', '/api/v1/resource-types', $user, ['code' => 'laser', 'name' => 'لیزر']);

        $this->authJson('DELETE', "/api/v1/resource-type/{$created['data']['uuid']}", $user);

        self::assertSame(200, $this->responseCode());
    }

    /** نوع سیستمی هرگز حذف نمی‌شود: ResourceLinker با همان کد پل می‌زند. */
    public function testSystemTypeCannotBeDeletedEvenWhenUnused(): void
    {
        [$user, , $address] = $this->clinicWithAddress();

        $type = $this->resourceType($address, 'room', 'اتاق');
        $type->markSystem();
        $this->em->flush();

        $body = $this->authJson('DELETE', "/api/v1/resource-type/{$type->getUuid()}", $user);

        self::assertSame(422, $this->responseCode());
        self::assertStringContainsString('سیستمی', $body['errors'][0]['message']);
    }

    public function testForeignTypeIsNotFound(): void
    {
        [$user] = $this->clinicWithAddress();
        $created = $this->authJson('POST', '/api/v1/resource-types', $user, ['code' => 'laser', 'name' => 'لیزر']);

        [$otherUser] = $this->clinicWithAddress('شعبهٔ دیگر');

        $this->authJson('PATCH', "/api/v1/resource-type/{$created['data']['uuid']}", $otherUser, ['name' => 'x']);
        self::assertSame(404, $this->responseCode());
    }

    /** `code` عوض نمی‌شود: منابع موجود و ResourceLinker با همان کد پیدا می‌شوند. */
    public function testCodeIsImmutable(): void
    {
        [$user] = $this->clinicWithAddress();
        $created = $this->authJson('POST', '/api/v1/resource-types', $user, ['code' => 'laser', 'name' => 'لیزر']);

        $body = $this->authJson('PATCH', "/api/v1/resource-type/{$created['data']['uuid']}", $user, [
            'code' => 'something_else',
            'name' => 'نام تازه',
        ]);

        self::assertSame(200, $this->responseCode());
        self::assertSame('laser', $body['data']['code']);
        self::assertSame('نام تازه', $body['data']['name']);
    }

    private function typeEntity(string $uuid): \App\Resource\Entity\ResourceType
    {
        return $this->em->getRepository(\App\Resource\Entity\ResourceType::class)->findOneBy(['uuid' => $uuid]);
    }
}
