<?php

namespace App\Resource\Controller;

use App\Auth\Entity\User;
use App\Resource\Entity\ResourcePool;
use App\Resource\Repository\ResourcePoolRepository;
use App\Resource\Service\ResourceContext;
use App\Resource\Service\ResourcePoolService;
use App\Shared\Constant\ErrorCodes;
use App\Shared\Controller\BaseController;
use Doctrine\ORM\EntityManagerInterface;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
use Symfony\Component\Security\Http\Attribute\IsGranted;

#[OA\Tag(name: 'Resource')]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
class ResourcePoolController extends BaseController
{
    use ResourcePermissionTrait;

    public function __construct(
        private readonly ResourceContext        $context,
        private readonly ResourcePoolRepository $pools,
        private readonly ResourcePoolService    $service,
        private readonly EntityManagerInterface $em,
    ) {}

    #[Route('/api/v1/resource-pools', name: 'resource_pool_list', methods: ['GET'])]
    public function list(#[CurrentUser] User $user): JsonResponse
    {
        $this->denyUnlessGranted($user, 'view');

        [$entityType, $entityId] = $this->context->pair($user);

        return $this->success(array_map(
            static fn (ResourcePool $p): array => $p->toArray(),
            $this->pools->findForPair($entityType, $entityId),
        ));
    }

    #[Route('/api/v1/resource-pools', name: 'resource_pool_create', methods: ['POST'])]
    public function create(#[CurrentUser] User $user, Request $request): JsonResponse
    {
        $this->denyUnlessGranted($user, 'update');

        $data = json_decode($request->getContent(), true);

        if (!is_array($data) || !is_string($data['address_uuid'] ?? null)) {
            return $this->error(ErrorCodes::ERR_VALIDATION_002, 'فیلد address_uuid الزامی است', 422, 'address_uuid');
        }

        if (!is_string($data['type_uuid'] ?? null)) {
            return $this->error(ErrorCodes::ERR_VALIDATION_002, 'فیلد type_uuid الزامی است', 422, 'type_uuid');
        }

        $name = is_string($data['name'] ?? null) ? trim($data['name']) : '';

        if ($name === '') {
            return $this->error(ErrorCodes::ERR_VALIDATION_002, 'نام استخر الزامی است', 422, 'name');
        }

        $pool = new ResourcePool(
            $this->context->address($user, $data['address_uuid']),
            $this->context->type($user, $data['type_uuid']),
            $name,
        );

        $this->em->persist($pool);
        $this->em->flush();

        return $this->success($pool->toArray(), 201);
    }

    #[Route('/api/v1/resource-pool/{uuid}', name: 'resource_pool_show', methods: ['GET'])]
    public function show(#[CurrentUser] User $user, string $uuid): JsonResponse
    {
        $this->denyUnlessGranted($user, 'view');

        return $this->success($this->context->pool($user, $uuid)->toArray());
    }

    #[Route('/api/v1/resource-pool/{uuid}', name: 'resource_pool_update', methods: ['PATCH'])]
    public function update(#[CurrentUser] User $user, string $uuid, Request $request): JsonResponse
    {
        $this->denyUnlessGranted($user, 'update');

        $data = json_decode($request->getContent(), true);

        if (!is_array($data)) {
            return $this->error(ErrorCodes::ERR_VALIDATION_001, 'بدنهٔ درخواست نامعتبر است', 422);
        }

        $pool = $this->context->pool($user, $uuid);

        if (is_string($data['name'] ?? null) && trim($data['name']) !== '') {
            $pool->setName(trim($data['name']));
        }

        if (array_key_exists('active', $data)) {
            $pool->setActive((bool) $data['active']);
        }

        $this->em->flush();

        return $this->success($pool->toArray());
    }

    #[Route('/api/v1/resource-pool/{uuid}', name: 'resource_pool_delete', methods: ['DELETE'])]
    public function delete(#[CurrentUser] User $user, string $uuid): JsonResponse
    {
        $this->denyUnlessGranted($user, 'update');

        // اعضا فرزند aggregate اند و با CASCADE می‌روند؛ خودِ منابع دست‌نخورده می‌مانند.
        $this->em->remove($this->context->pool($user, $uuid));
        $this->em->flush();

        return $this->success(null);
    }

    #[Route('/api/v1/resource-pool/{uuid}/members', name: 'resource_pool_members_replace', methods: ['PUT'])]
    public function replaceMembers(#[CurrentUser] User $user, string $uuid, Request $request): JsonResponse
    {
        $this->denyUnlessGranted($user, 'update');

        $data = json_decode($request->getContent(), true);

        if (!is_array($data) || !is_array($data['members'] ?? null)) {
            return $this->error(ErrorCodes::ERR_VALIDATION_002, 'فیلد members الزامی است', 422, 'members');
        }

        $pool = $this->context->pool($user, $uuid);
        $this->service->replaceMembers($user, $pool, $data['members']);

        return $this->success($pool->toArray());
    }
}
