<?php

namespace App\Tests\Resource;

class ResourcePoolTest extends ResourceTestCase
{
    public function testPoolIsCreatedAndMembersAreReplacedWholesale(): void
    {
        [$user, , $address] = $this->clinicWithAddress();
        $type = $this->resourceType($address, 'laser', 'دستگاه لیزر');

        $one   = $this->createResource($user, $address, $type, ['name' => 'لیزر ۱']);
        $two   = $this->createResource($user, $address, $type, ['name' => 'لیزر ۲']);
        $three = $this->createResource($user, $address, $type, ['name' => 'لیزر ۳']);

        $pool = $this->authJson('POST', '/api/v1/resource-pools', $user, [
            'address_uuid' => $address->getUuid(),
            'type_uuid'    => $type->getUuid(),
            'name'         => 'لیزرهای آلکساندرایت',
        ]);
        self::assertSame(201, $this->responseCode(), json_encode($pool, JSON_UNESCAPED_UNICODE));
        self::assertSame([], $pool['data']['members'], 'استخر تازه هیچ عضوی ندارد و این معتبر است');

        $filled = $this->authJson('PUT', "/api/v1/resource-pool/{$pool['data']['uuid']}/members", $user, [
            'members' => [
                ['resource_uuid' => $one['data']['uuid'], 'priority' => 0],
                ['resource_uuid' => $two['data']['uuid'], 'priority' => 1],
                ['resource_uuid' => $three['data']['uuid'], 'priority' => 2],
            ],
        ]);

        self::assertSame(200, $this->responseCode());
        self::assertCount(3, $filled['data']['members']);
        self::assertSame($address->getUuid(), $filled['data']['address_uuid']);

        // جایگزینی کامل: عضوی که نیامده، برداشته می‌شود.
        $shrunk = $this->authJson('PUT', "/api/v1/resource-pool/{$pool['data']['uuid']}/members", $user, [
            'members' => [['resource_uuid' => $one['data']['uuid']]],
        ]);
        self::assertCount(1, $shrunk['data']['members']);
    }

    public function testMemberFromAnotherBranchIsRejected(): void
    {
        [$user, $clinic, $address] = $this->clinicWithAddress();
        $second = $this->extraAddress($clinic);
        $type   = $this->resourceType($address, 'laser', 'دستگاه لیزر');

        $elsewhere = $this->createResource($user, $second, $type, ['name' => 'لیزر شعبهٔ دو']);

        $pool = $this->authJson('POST', '/api/v1/resource-pools', $user, [
            'address_uuid' => $address->getUuid(),
            'type_uuid'    => $type->getUuid(),
            'name'         => 'استخر شعبهٔ یک',
        ]);

        $body = $this->authJson('PUT', "/api/v1/resource-pool/{$pool['data']['uuid']}/members", $user, [
            'members' => [['resource_uuid' => $elsewhere['data']['uuid']]],
        ]);

        self::assertSame(422, $this->responseCode());
        self::assertStringContainsString('یک شعبه', $body['errors'][0]['message']);
    }

    public function testMemberOfAnotherTypeIsRejected(): void
    {
        [$user, , $address] = $this->clinicWithAddress();
        $laser = $this->resourceType($address, 'laser', 'دستگاه لیزر');
        $chair = $this->resourceType($address, 'chair', 'صندلی');

        $wrongType = $this->createResource($user, $address, $chair, ['name' => 'صندلی ۱']);

        $pool = $this->authJson('POST', '/api/v1/resource-pools', $user, [
            'address_uuid' => $address->getUuid(),
            'type_uuid'    => $laser->getUuid(),
            'name'         => 'استخر لیزر',
        ]);

        $body = $this->authJson('PUT', "/api/v1/resource-pool/{$pool['data']['uuid']}/members", $user, [
            'members' => [['resource_uuid' => $wrongType['data']['uuid']]],
        ]);

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

    /** عضو نامعتبر نباید اعضای درستِ قبلی را پاک کند. */
    public function testInvalidMemberLeavesTheStoredMembersUntouched(): void
    {
        [$user, $clinic, $address] = $this->clinicWithAddress();
        $second = $this->extraAddress($clinic);
        $type   = $this->resourceType($address, 'laser', 'دستگاه لیزر');

        $good      = $this->createResource($user, $address, $type, ['name' => 'لیزر خوب']);
        $elsewhere = $this->createResource($user, $second, $type, ['name' => 'لیزر شعبهٔ دو']);

        $pool = $this->authJson('POST', '/api/v1/resource-pools', $user, [
            'address_uuid' => $address->getUuid(),
            'type_uuid'    => $type->getUuid(),
            'name'         => 'استخر',
        ]);

        $this->authJson('PUT', "/api/v1/resource-pool/{$pool['data']['uuid']}/members", $user, [
            'members' => [['resource_uuid' => $good['data']['uuid']]],
        ]);

        $this->authJson('PUT', "/api/v1/resource-pool/{$pool['data']['uuid']}/members", $user, [
            'members' => [
                ['resource_uuid' => $good['data']['uuid']],
                ['resource_uuid' => $elsewhere['data']['uuid']],
            ],
        ]);
        self::assertSame(422, $this->responseCode());

        $read = $this->authJson('GET', "/api/v1/resource-pool/{$pool['data']['uuid']}", $user);
        self::assertCount(1, $read['data']['members']);
    }

    public function testForeignPoolIsNotFound(): void
    {
        [$user, , $address] = $this->clinicWithAddress();
        $pool = $this->authJson('POST', '/api/v1/resource-pools', $user, [
            'address_uuid' => $address->getUuid(),
            'type_uuid'    => $this->resourceType($address)->getUuid(),
            'name'         => 'استخر',
        ]);

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

        $this->authJson('GET', "/api/v1/resource-pool/{$pool['data']['uuid']}", $otherUser);
        self::assertSame(404, $this->responseCode());

        $this->authJson('PUT', "/api/v1/resource-pool/{$pool['data']['uuid']}/members", $otherUser, ['members' => []]);
        self::assertSame(404, $this->responseCode());
    }

    /** حذف استخر اعضا را می‌برد ولی خودِ منابع باید سرِ جایشان بمانند. */
    public function testDeletingAPoolKeepsItsResources(): void
    {
        [$user, , $address] = $this->clinicWithAddress();
        $type     = $this->resourceType($address, 'laser', 'لیزر');
        $resource = $this->createResource($user, $address, $type, ['name' => 'لیزر ۱']);

        $pool = $this->authJson('POST', '/api/v1/resource-pools', $user, [
            'address_uuid' => $address->getUuid(),
            'type_uuid'    => $type->getUuid(),
            'name'         => 'استخر',
        ]);
        $this->authJson('PUT', "/api/v1/resource-pool/{$pool['data']['uuid']}/members", $user, [
            'members' => [['resource_uuid' => $resource['data']['uuid']]],
        ]);

        $this->authJson('DELETE', "/api/v1/resource-pool/{$pool['data']['uuid']}", $user);
        self::assertSame(200, $this->responseCode());

        $this->authJson('GET', "/api/v1/resource/{$resource['data']['uuid']}", $user);
        self::assertSame(200, $this->responseCode(), 'منبع نباید با استخر حذف شود');
    }

    public function testDuplicateMemberIsRejected(): void
    {
        [$user, , $address] = $this->clinicWithAddress();
        $type     = $this->resourceType($address, 'laser', 'لیزر');
        $resource = $this->createResource($user, $address, $type, ['name' => 'لیزر ۱']);

        $pool = $this->authJson('POST', '/api/v1/resource-pools', $user, [
            'address_uuid' => $address->getUuid(),
            'type_uuid'    => $type->getUuid(),
            'name'         => 'استخر',
        ]);

        $this->authJson('PUT', "/api/v1/resource-pool/{$pool['data']['uuid']}/members", $user, [
            'members' => [
                ['resource_uuid' => $resource['data']['uuid']],
                ['resource_uuid' => $resource['data']['uuid']],
            ],
        ]);

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