<?php

namespace App\Http\Controllers\Api\V1\Identity;

use App\Domain\Identity\Models\Role;
use App\Domain\Identity\Services\RoleService;
use App\Http\Controllers\Controller;
use App\Http\Requests\Identity\CloneRoleRequest;
use App\Http\Requests\Identity\StoreRoleRequest;
use App\Http\Requests\Identity\UpdateRoleRequest;
use App\Http\Resources\RoleResource;
use App\Support\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class RoleController extends Controller
{
    public function __construct(private readonly RoleService $roles) {}

    public function index(Request $request): JsonResponse
    {
        $this->authorize('viewAny', Role::class);

        $roles = Role::query()
            ->withCount(['users', 'permissionScopes'])
            ->when($request->filled('search'), fn ($query) => $query->where(
                fn ($q) => $q->where('name', 'like', '%'.$request->string('search').'%')
                    ->orWhere('label', 'like', '%'.$request->string('search').'%')
            ))
            ->when($request->filled('is_active'), fn ($query) => $query->where('is_active', $request->boolean('is_active')))
            ->orderBy('level')
            ->orderBy('name')
            ->get();

        return ApiResponse::success(RoleResource::collection($roles));
    }

    public function show(Role $role): JsonResponse
    {
        $this->authorize('view', $role);

        $role->loadCount(['users', 'permissionScopes'])
            ->load('permissionScopes.permission:id,name');

        return ApiResponse::success(new RoleResource($role));
    }

    public function store(StoreRoleRequest $request): JsonResponse
    {
        $this->authorize('create', Role::class);

        $role = $this->roles->create($request->validated(), $request->grants());

        return ApiResponse::success(
            new RoleResource($role->load('permissionScopes.permission:id,name')),
            'Role created successfully.',
            status: 201,
        );
    }

    public function update(UpdateRoleRequest $request, Role $role): JsonResponse
    {
        $this->authorize('update', $role);

        if ($request->grants() !== null) {
            $this->authorize('assignPermissions', $role);
        }

        $role = $this->roles->update($role, $request->validated(), $request->grants());

        return ApiResponse::success(
            new RoleResource($role->fresh()->load('permissionScopes.permission:id,name')),
            'Role updated successfully.',
        );
    }

    public function clone(CloneRoleRequest $request, Role $role): JsonResponse
    {
        $this->authorize('create', Role::class);

        $clone = $this->roles->clone($role, $request->string('label')->toString(), $request->input('name'));

        return ApiResponse::success(
            new RoleResource($clone->load('permissionScopes.permission:id,name')),
            'Role cloned successfully.',
            status: 201,
        );
    }

    public function destroy(Role $role): JsonResponse
    {
        $this->authorize('delete', $role);

        $this->roles->delete($role);

        return ApiResponse::success(null, 'Role deleted successfully.');
    }
}
