<?php

namespace App\Resource\Controller;

use App\Auth\Entity\User;
use App\Resource\Entity\ResourceType;
use App\Resource\Repository\ClinicResourceRepository;
use App\Resource\Repository\ResourceTypeRepository;
use App\Resource\Service\ResourceContext;
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 ResourceTypeController extends BaseController
{
    use ResourcePermissionTrait;

    public function __construct(
        private readonly ResourceContext          $context,
        private readonly ResourceTypeRepository   $types,
        private readonly ClinicResourceRepository $resources,
        private readonly EntityManagerInterface   $em,
    ) {}

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

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

        $types  = $this->types->findForPair($entityType, $entityId);
        // یک کوئری گروهی، نه یکی per نوع.
        $counts = $this->resources->countByTypeIds(array_map(
            static fn (ResourceType $t): int => (int) $t->getId(),
            $types,
        ));

        return $this->success(array_map(
            static fn (ResourceType $t): array => $t->toArray($counts[(int) $t->getId()] ?? 0),
            $types,
        ));
    }

    #[Route('/api/v1/resource-types', name: 'resource_type_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)) {
            return $this->error(ErrorCodes::ERR_VALIDATION_001, 'بدنهٔ درخواست نامعتبر است', 422);
        }

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

        if (preg_match('/^[a-z0-9_]{1,40}$/', $code) !== 1) {
            return $this->error(ErrorCodes::ERR_VALIDATION_001, 'کد فقط حروف کوچک انگلیسی، عدد و زیرخط می‌پذیرد', 422, 'code');
        }

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

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

        if ($this->types->findByCode($entityType, $entityId, $code) !== null) {
            return $this->error(ErrorCodes::ERR_VALIDATION_001, 'نوع منبعی با این کد از قبل وجود دارد', 422, 'code');
        }

        $type = new ResourceType($entityType, $entityId, $code, $name);
        $this->em->persist($type);
        $this->em->flush();

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

    #[Route('/api/v1/resource-type/{uuid}', name: 'resource_type_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);
        }

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

        // `code` تغییر نمی‌کند حتی روی نوع غیرسیستمی: ResourceLinker و منابع موجود با
        // همان کد پیدا می‌شوند و عوض کردنش نگاشت را بی‌صدا می‌شکند.
        if (is_string($data['name'] ?? null) && trim($data['name']) !== '') {
            $type->setName(trim($data['name']));
        }

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

        $this->em->flush();

        return $this->success($type->toArray($this->resources->countForType($type)));
    }

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

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

        if ($type->isSystem()) {
            return $this->error(ErrorCodes::ERR_VALIDATION_001, 'نوع منبع سیستمی حذف نمی‌شود', 422);
        }

        $inUse = $this->resources->countForType($type);

        if ($inUse > 0) {
            return $this->error(
                ErrorCodes::ERR_VALIDATION_001,
                sprintf('این نوع روی %d منبع استفاده شده است', $inUse),
                422,
            );
        }

        $this->em->remove($type);
        $this->em->flush();

        return $this->success(null);
    }
}
