<?php

namespace App\Resource\Controller;

use App\Auth\Entity\User;
use App\Resource\Entity\Skill;
use App\Resource\Repository\ResourceSkillRepository;
use App\Resource\Repository\SkillRepository;
use App\Resource\Service\ResourceContext;
use App\Resource\Service\SkillAssignmentService;
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 SkillController extends BaseController
{
    use ResourcePermissionTrait;

    public function __construct(
        private readonly ResourceContext         $context,
        private readonly SkillRepository         $skills,
        private readonly ResourceSkillRepository $assignments,
        private readonly SkillAssignmentService  $service,
        private readonly EntityManagerInterface  $em,
    ) {}

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

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

        $skills = $this->skills->findForPair($entityType, $entityId);
        $counts = $this->assignments->countBySkillIds(array_map(
            static fn (Skill $s): int => (int) $s->getId(),
            $skills,
        ));

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

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

        $data = json_decode($request->getContent(), true);
        $name = is_array($data) && is_string($data['name'] ?? null) ? trim($data['name']) : '';

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

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

        $skill = new Skill($entityType, $entityId, $name);
        $this->em->persist($skill);
        $this->em->flush();

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

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

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

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

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

        $this->em->flush();

        return $this->success($skill->toArray($this->assignments->countForSkill($skill)));
    }

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

        $this->service->deleteSkill($this->context->skill($user, $uuid));

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