<?php

namespace Modules\Role\Http\Controllers;

use App\Http\Controllers\BaseCrudController;
use App\Services\ActivityLogger;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Modules\Role\Entities\Role;
use Modules\Role\Http\Requests\RoleRequest;
use Modules\Role\Repositories\Contracts\RoleRepositoryInterface;
use Modules\Role\Transformers\RoleResource;
use App\Models\Permission;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rule;

class RoleController extends BaseCrudController
{
    protected $modelClass = Role::class;

    protected $resourceClass = RoleResource::class;

    protected $requestClass = RoleRequest::class;

    protected $resourceName = 'role';

    protected $resourceNamePlural = 'roles';

    public function __construct(RoleRepositoryInterface $repository)
    {
        parent::__construct($repository);
    }

    /**
     * Prepare data for store method
     */
    protected function prepareStoreData(array $validated): array
    {
        return $validated;
    }

    /**
     * Prepare data for update method
     */
    protected function prepareUpdateData(array $validated, $role): array
    {
        return $validated;
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, string $id): JsonResponse
    {
        $this->authorize('update', $this->modelClass);

        try {
            $item = $this->repository->findById($id);

            if (! $item) {
                return $this->errorResponse($this->getNotFoundMessage(), 404);
            }

            $validated = $this->validateRequest($request);
            $data = $this->prepareUpdateData($validated, $item);

            // Use repository update method to handle permissions
            $updatedItem = $this->repository->update($id, $data);

            ActivityLogger::log("Updated {$this->resourceName}: {$this->getItemName($updatedItem)}", $updatedItem);

            return response()->json([
                'success' => true,
                'data' => new $this->resourceClass($updatedItem),
                'message' => $this->getSuccessMessage('update'),
            ]);

        } catch (Exception $e) {
            Log::error("Error updating {$this->resourceName}: ".$e->getMessage());

            return $this->errorResponse($this->getErrorMessage('update').': '.$e->getMessage(), 500);
        }
    }

    /**
     * Check dependencies before deletion
     */
    protected function checkDependencies($role): ?JsonResponse
    {
        // Check if role has users assigned
        if ($role->users()->count() > 0) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot delete role. It has users assigned to it.',
            ], 422);
        }

        return null;
    }

    /**
     * Get all permissions for role assignment
     */
    public function permissions(): JsonResponse
    {
        if (! Gate::any(['create', 'update'], $this->modelClass)) {
            abort(403);
        }

        $permissions = Permission::all();

        return response()->json([
            'success' => true,
            'data' => $permissions->map(function ($permission) {
                return [
                    'id' => $permission->id,
                    'name' => $permission->name,
                    'guard_name' => $permission->guard_name,
                    'route_name' => $permission->route_name,
                ];
            }),
        ]);
    }

    /**
     * Assign permissions to a role
     */
    public function assignPermissions(Request $request, string $id): JsonResponse
    {
        $this->authorize('update', $this->modelClass);

        $request->validate([
            'permissions' => 'required|array',
            'permissions.*' => ['required', 'uuid', Rule::exists('permissions', 'id')],
        ]);

        $role = $this->repository->find($id);
        $this->repository->syncPermissions($role, $request->permissions);

        return response()->json([
            'success' => true,
            'message' => 'Permissions assigned successfully.',
            'data' => new RoleResource($role->load('permissions')),
        ]);
    }

    /**
     * Get role with permissions
     */
    public function show(string $id): JsonResponse
    {
        $this->authorize('view', $this->modelClass);

        $role = $this->repository->find($id);
        
        return response()->json([
            'success' => true,
            'data' => new RoleResource($role->load('permissions')),
        ]);
    }

    /**
     * Get all roles with permissions
     */
    public function index(Request $request): JsonResponse
    {
        $this->authorize('viewAny', $this->modelClass);

        $search = $request->get('search', '');
        $roles = $this->repository->withPermissions($search);

        return response()->json([
            'success' => true,
            'data' => RoleResource::collection($roles),
        ]);
    }
}
