<?php

namespace Maestro\Core\Http\Controllers;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Spatie\Permission\Models\Role;

class RoleSettingsController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        abort_unless($request->user()?->can('roles.view'), 403);

        $roles = Role::query()->where('guard_name', 'web')
            ->with('permissions:id,name')
            ->orderBy('name')
            ->get()
            ->map(fn (Role $role) => [
                'id' => $role->id,
                'name' => $role->name,
                'guard_name' => $role->guard_name,
                'permissions' => $role->permissions->pluck('name')->values()->all(),
            ]);

        return response()->json(['data' => $roles]);
    }

    public function store(Request $request): JsonResponse
    {
        abort_unless($request->user()?->can('roles.create'), 403);

        $validator = Validator::make($request->all(), [
            'name' => ['required', 'string', 'max:255', 'unique:roles,name'],
            'permissions' => ['nullable', 'array'],
            'permissions.*' => ['string', 'exists:permissions,name'],
        ]);

        if ($validator->fails()) {
            return response()->json([
                'message' => 'Validation failed.',
                'errors' => $validator->errors(),
            ], 422);
        }

        $role = Role::create([
            'name' => $request->input('name'),
            'guard_name' => 'web',
        ]);

        $permissions = $request->input('permissions', []);
        if ($permissions !== []) {
            $role->syncPermissions($permissions);
        }

        $role->load('permissions:id,name');

        return response()->json([
            'data' => [
                'id' => $role->id,
                'name' => $role->name,
                'permissions' => $role->permissions->pluck('name')->values()->all(),
            ],
        ], 201);
    }

    public function update(Request $request, Role $role): JsonResponse
    {
        abort_unless($request->user()?->can('roles.edit'), 403);

        abort_unless($role->guard_name === 'web', 404);

        $validator = Validator::make($request->all(), [
            'name' => ['sometimes', 'string', 'max:255', Rule::unique('roles', 'name')->ignore($role->id)],
            'permissions' => ['nullable', 'array'],
            'permissions.*' => ['string', 'exists:permissions,name'],
        ]);

        if ($validator->fails()) {
            return response()->json([
                'message' => 'Validation failed.',
                'errors' => $validator->errors(),
            ], 422);
        }

        if ($request->filled('name') && $request->input('name') !== $role->name) {
            abort_if($role->name === 'admin', 422, 'Renaming built-in roles is disabled.');
            $role->update(['name' => $request->input('name')]);
        }

        if ($request->has('permissions')) {
            abort_if($role->name === 'admin', 422, 'Permissions for admin are managed in seeds.');
            $role->syncPermissions($request->input('permissions', []));
        }

        $role->load('permissions:id,name');

        return response()->json([
            'data' => [
                'id' => $role->id,
                'name' => $role->name,
                'permissions' => $role->permissions->pluck('name')->values()->all(),
            ],
        ]);
    }

    public function destroy(Request $request, Role $role): JsonResponse
    {
        abort_unless($request->user()?->can('roles.delete'), 403);
        abort_unless($role->guard_name === 'web', 404);
        abort_if($role->name === 'admin', 422, 'Cannot delete admin role.');
        abort_if($role->users()->exists(), 422, 'Users still have this role.');

        $role->delete();

        return response()->json(['message' => 'Deleted.']);
    }
}
