<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\SysRol;
use App\Models\SysPermiso;
use App\Models\Perfil;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;

class RolController extends Controller
{
    /**
     * Listado de roles
     */
    public function index(Request $request)
    {
        // Query base
        $query = SysRol::withCount('perfiles');

        // Filtros
        if ($request->filled('buscar')) {
            $buscar = $request->buscar;
            $query->where(function ($q) use ($buscar) {
                $q->where('rol_nombre', 'like', "%{$buscar}%")
                  ->orWhere('rol_codigo', 'like', "%{$buscar}%")
                  ->orWhere('rol_descripcion', 'like', "%{$buscar}%");
            });
        }

        if ($request->filled('estado')) {
            $query->where('estado', $request->estado);
        }

        if ($request->filled('acceso')) {
            if ($request->acceso === 'web') {
                $query->where('acceso_web', 1);
            } elseif ($request->acceso === 'app') {
                $query->where('acceso_app', 1);
            }
        }

        // Ordenar
        $query->orderBy('rol_nombre');

        // Estadísticas
        $estadisticas = [
            'total' => SysRol::count(),
            'activos' => SysRol::where('estado', 1)->count(),
            'sistema' => SysRol::where('es_sistema', 1)->count(),
            'con_web' => SysRol::where('acceso_web', 1)->where('estado', 1)->count(),
            'con_app' => SysRol::where('acceso_app', 1)->where('estado', 1)->count(),
        ];

        // Paginar
        $roles = $query->paginate(15)->appends($request->query());

        return view('modules.roles.index', compact('roles', 'estadisticas'));
    }

    /**
     * Formulario para crear rol
     */
    public function create()
    {
        // Permisos agrupados por módulo
        $permisosAgrupados = SysPermiso::activos()
            ->orderBy('modulo')
            ->orderBy('permiso_nombre')
            ->get()
            ->groupBy('modulo');

        return view('modules.roles.create', compact('permisosAgrupados'));
    }

    /**
     * Guardar nuevo rol
     */
    public function store(Request $request)
    {
        $request->validate([
            'rol_nombre' => 'required|string|max:100',
            'rol_codigo' => 'required|string|max:50|unique:sys_roles,rol_codigo|alpha_dash:ascii',
            'rol_descripcion' => 'nullable|string|max:500',
            'acceso_web' => 'boolean',
            'acceso_app' => 'boolean',
            'permisos' => 'array',
            'permisos.*' => 'exists:sys_permisos,permiso_id',
        ]);

        DB::beginTransaction();
        try {
            // Crear rol
            $rol = SysRol::create([
                'rol_codigo' => Str::upper($request->rol_codigo),
                'rol_nombre' => $request->rol_nombre,
                'rol_descripcion' => $request->rol_descripcion,
                'acceso_web' => $request->boolean('acceso_web'),
                'acceso_app' => $request->boolean('acceso_app'),
                'es_sistema' => false,
                'estado' => 1,
                'usuario_crea' => auth()->id(),
                'fecha_crea' => now(),
            ]);

            // Asignar permisos
            if ($request->filled('permisos')) {
                $permisosData = [];
                foreach ($request->permisos as $permisoId) {
                    $permisosData[$permisoId] = [
                        'fecha_asignacion' => now(),
                        'usuario_asigna' => auth()->id(),
                    ];
                }
                $rol->permisos()->attach($permisosData);
            }

            DB::commit();

            return redirect()
                ->route('web.roles.index')
                ->with('success', 'Rol creado exitosamente.');

        } catch (\Exception $e) {
            DB::rollBack();
            return back()
                ->withInput()
                ->with('error', 'Error al crear el rol: ' . $e->getMessage());
        }
    }

    /**
     * Detalle del rol
     */
    public function show($id)
    {
        $rol = SysRol::with(['permisos', 'perfiles.usuarios'])
            ->withCount('perfiles')
            ->findOrFail($id);

        // Permisos agrupados
        $permisosAsignados = $rol->permisos()
            ->orderBy('modulo')
            ->orderBy('permiso_nombre')
            ->get()
            ->groupBy('modulo');

        // Usuarios con este rol (a través de perfiles)
        $usuariosConRol = DB::table('usuarios as u')
            ->join('perfil as p', 'u.per_id', '=', 'p.per_id')
            ->where('p.rol_id', $id)
            ->where('u.usu_estado', 1)
            ->select('u.usu_id', 'u.usu_nombre', 'u.usu_apellido', 'u.usu_email', 'p.per_nombre')
            ->orderBy('u.usu_nombre')
            ->limit(20)
            ->get();

        return view('modules.roles.show', compact('rol', 'permisosAsignados', 'usuariosConRol'));
    }

    /**
     * Formulario de edición
     */
    public function edit($id)
    {
        $rol = SysRol::with('permisos')->findOrFail($id);

        // Verificar si es rol de sistema
        if ($rol->es_sistema) {
            return back()->with('warning', 'Los roles de sistema no pueden ser editados.');
        }

        // Permisos agrupados por módulo
        $permisosAgrupados = SysPermiso::activos()
            ->orderBy('modulo')
            ->orderBy('permiso_nombre')
            ->get()
            ->groupBy('modulo');

        // IDs de permisos asignados
        $permisosAsignados = $rol->permisos->pluck('permiso_id')->toArray();

        return view('modules.roles.edit', compact('rol', 'permisosAgrupados', 'permisosAsignados'));
    }

    /**
     * Actualizar rol
     */
    public function update(Request $request, $id)
    {
        $rol = SysRol::findOrFail($id);

        // Verificar si es rol de sistema
        if ($rol->es_sistema) {
            return back()->with('warning', 'Los roles de sistema no pueden ser editados.');
        }

        $request->validate([
            'rol_nombre' => 'required|string|max:100',
            'rol_codigo' => ['required', 'string', 'max:50', 'alpha_dash:ascii', Rule::unique('sys_roles', 'rol_codigo')->ignore($id, 'rol_id')],
            'rol_descripcion' => 'nullable|string|max:500',
            'acceso_web' => 'boolean',
            'acceso_app' => 'boolean',
            'estado' => 'required|in:0,1',
            'permisos' => 'array',
            'permisos.*' => 'exists:sys_permisos,permiso_id',
        ]);

        DB::beginTransaction();
        try {
            // Actualizar rol
            $rol->update([
                'rol_codigo' => Str::upper($request->rol_codigo),
                'rol_nombre' => $request->rol_nombre,
                'rol_descripcion' => $request->rol_descripcion,
                'acceso_web' => $request->boolean('acceso_web'),
                'acceso_app' => $request->boolean('acceso_app'),
                'estado' => $request->estado,
                'usuario_modifica' => auth()->id(),
                'fecha_modifica' => now(),
            ]);

            // Sincronizar permisos
            $permisosData = [];
            if ($request->filled('permisos')) {
                foreach ($request->permisos as $permisoId) {
                    $permisosData[$permisoId] = [
                        'fecha_asignacion' => now(),
                        'usuario_asigna' => auth()->id(),
                    ];
                }
            }
            $rol->permisos()->sync($permisosData);

            DB::commit();

            return redirect()
                ->route('web.roles.index')
                ->with('success', 'Rol actualizado exitosamente.');

        } catch (\Exception $e) {
            DB::rollBack();
            return back()
                ->withInput()
                ->with('error', 'Error al actualizar el rol: ' . $e->getMessage());
        }
    }

    /**
     * Duplicar rol
     */
    public function duplicar($id)
    {
        $rolOriginal = SysRol::with('permisos')->findOrFail($id);

        DB::beginTransaction();
        try {
            // Crear copia del rol
            $nuevoRol = SysRol::create([
                'rol_codigo' => $rolOriginal->rol_codigo . '_COPIA_' . time(),
                'rol_nombre' => $rolOriginal->rol_nombre . ' (Copia)',
                'rol_descripcion' => $rolOriginal->rol_descripcion,
                'acceso_web' => $rolOriginal->acceso_web,
                'acceso_app' => $rolOriginal->acceso_app,
                'es_sistema' => false,
                'estado' => 1,
                'usuario_crea' => auth()->id(),
                'fecha_crea' => now(),
            ]);

            // Copiar permisos
            $permisosData = [];
            foreach ($rolOriginal->permisos as $permiso) {
                $permisosData[$permiso->permiso_id] = [
                    'fecha_asignacion' => now(),
                    'usuario_asigna' => auth()->id(),
                ];
            }
            $nuevoRol->permisos()->attach($permisosData);

            DB::commit();

            return redirect()
                ->route('web.roles.edit', $nuevoRol->rol_id)
                ->with('success', 'Rol duplicado exitosamente. Modifique los datos según necesite.');

        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('error', 'Error al duplicar el rol: ' . $e->getMessage());
        }
    }

    /**
     * Toggle estado del rol
     */
    public function toggleEstado($id)
    {
        $rol = SysRol::findOrFail($id);

        if ($rol->es_sistema) {
            return back()->with('warning', 'Los roles de sistema no pueden ser desactivados.');
        }

        $nuevoEstado = $rol->estado == 1 ? 0 : 1;
        $rol->update([
            'estado' => $nuevoEstado,
            'usuario_modifica' => auth()->id(),
            'fecha_modifica' => now(),
        ]);

        $mensaje = $nuevoEstado == 1 ? 'Rol activado exitosamente.' : 'Rol desactivado exitosamente.';

        return back()->with('success', $mensaje);
    }
}
