<?php

/**
 * Módulo de Gestión de Roles y Permisos
 * Maneja todas las operaciones relacionadas con roles y permisos del sistema
 */

// Prevenir acceso directo
if (!defined('BASEPATH')) exit('No direct script access allowed');

switch ($tipo) {
    case 'getRoles':
        try {
            $query = "SELECT
                        r.id,
                        r.nombre,
                        r.descripcion,
                        r.nivel,
                        r.activo,
                        r.necesita_almacen,
                        r.fecha_creacion,
                        r.fecha_actualizacion,
                        COUNT(DISTINCT u.id) as usuarios_count,
                        COUNT(DISTINCT rp.permiso_id) as permisos_count,
                        GROUP_CONCAT(DISTINCT p.nombre) as permisos
                    FROM roles r
                    LEFT JOIN usuarios u ON r.id = u.rol_id AND u.activo = 1
                    LEFT JOIN rol_permisos rp ON r.id = rp.rol_id
                    LEFT JOIN permisos p ON rp.permiso_id = p.id AND p.activo = 1
                    GROUP BY r.id, r.nombre, r.descripcion, r.nivel, r.activo, r.necesita_almacen, r.fecha_creacion, r.fecha_actualizacion
                    ORDER BY r.nivel DESC, r.nombre ASC";

            $result = $conn->query($query);
            if (!$result) {
                sendResponse(false, "Error en consulta de roles: " . $conn->error);
                break;
            }

            $roles = [];
            while ($row = $result->fetch_assoc()) {
                $row['usuarios_count'] = (int)$row['usuarios_count'];
                $row['permisos_count'] = (int)$row['permisos_count'];
                $row['nivel'] = (int)$row['nivel'];
                $row['activo'] = (bool)$row['activo'];
                $row['necesita_almacen'] = (bool)$row['necesita_almacen'];
                $row['permisos'] = $row['permisos'] ? explode(',', $row['permisos']) : [];
                $roles[] = $row;
            }

            sendResponse(true, "Roles obtenidos correctamente", $roles);
        } catch (Exception $e) {
            error_log("Error al obtener roles: " . $e->getMessage());
            sendResponse(false, "Error al obtener roles");
        }
        break;

    case 'getRol':
        try {
            $role_id = isset($datapost['role_id']) ? intval($datapost['role_id']) : 0;

            if ($role_id <= 0) {
                sendResponse(false, "ID del rol requerido");
                break;
            }

            $query = "SELECT
                        r.id,
                        r.nombre,
                        r.descripcion,
                        r.nivel,
                        r.activo,
                        r.necesita_almacen,
                        r.fecha_creacion,
                        r.fecha_actualizacion,
                        COUNT(DISTINCT u.id) as usuarios_count
                    FROM roles r
                    LEFT JOIN usuarios u ON r.id = u.rol_id AND u.activo = 1
                    WHERE r.id = ?
                    GROUP BY r.id";

            $stmt = $conn->prepare($query);
            $stmt->bind_param("i", $role_id);
            $stmt->execute();
            $result = $stmt->get_result();
            $rol = $result->fetch_assoc();

            if (!$rol) {
                sendResponse(false, "Rol no encontrado");
                break;
            }

            // Obtener permisos del rol
            $query_permisos = "SELECT p.nombre
                            FROM rol_permisos rp
                            JOIN permisos p ON rp.permiso_id = p.id
                            WHERE rp.rol_id = ? AND p.activo = 1";
            $stmt_permisos = $conn->prepare($query_permisos);
            $stmt_permisos->bind_param("i", $role_id);
            $stmt_permisos->execute();
            $result_permisos = $stmt_permisos->get_result();

            $permisos = [];
            while ($row = $result_permisos->fetch_assoc()) {
                $permisos[] = $row['nombre'];
            }

            $rol['usuarios_count'] = (int)$rol['usuarios_count'];
            $rol['nivel'] = (int)$rol['nivel'];
            $rol['activo'] = (bool)$rol['activo'];
            $rol['permisos'] = $permisos;

            sendResponse(true, "Rol obtenido correctamente", $rol);
        } catch (Exception $e) {
            error_log("Error al obtener rol: " . $e->getMessage());
            sendResponse(false, "Error al obtener rol");
        }
        break;

    case 'crearRol':
        try {
            $nombre = isset($datapost['nombre']) ? trim($datapost['nombre']) : '';
            $descripcion = isset($datapost['descripcion']) ? trim($datapost['descripcion']) : '';
            $nivel = 1; // Valor por defecto
            $activo = isset($datapost['activo']) ? intval($datapost['activo']) : 1;
            $necesita_almacen = isset($datapost['necesita_almacen']) ? intval($datapost['necesita_almacen']) : 0;
            $permisos = isset($datapost['permisos']) ? $datapost['permisos'] : [];

            if (empty($nombre)) {
                sendResponse(false, "El nombre del rol es requerido");
                break;
            }

            // Validar que el nombre no exista
            $query_check = "SELECT id FROM roles WHERE nombre = ?";
            $stmt_check = $conn->prepare($query_check);
            $stmt_check->bind_param("s", $nombre);
            $stmt_check->execute();
            $result_check = $stmt_check->get_result();

            if ($result_check->fetch_assoc()) {
                sendResponse(false, "Ya existe un rol con ese nombre");
                break;
            }

            // Iniciar transacción
            $conn->begin_transaction();

            // Insertar rol
            $query = "INSERT INTO roles (nombre, descripcion, nivel, activo, necesita_almacen) VALUES (?, ?, ?, ?, ?)";
            $stmt = $conn->prepare($query);
            $stmt->bind_param("ssiii", $nombre, $descripcion, $nivel, $activo, $necesita_almacen);

            if (!$stmt->execute()) {
                $conn->rollback();
                sendResponse(false, "Error al crear rol");
                break;
            }

            $rol_id = $conn->insert_id;

            // Asignar permisos si se proporcionaron
            if (is_array($permisos) && !empty($permisos)) {
                foreach ($permisos as $permiso_nombre) {
                    // Obtener ID del permiso
                    $query_permiso = "SELECT id FROM permisos WHERE nombre = ? AND activo = 1";
                    $stmt_permiso = $conn->prepare($query_permiso);
                    $stmt_permiso->bind_param("s", $permiso_nombre);
                    $stmt_permiso->execute();
                    $result_permiso = $stmt_permiso->get_result();
                    $permiso_row = $result_permiso->fetch_assoc();

                    if ($permiso_row) {
                        $query_insert = "INSERT IGNORE INTO rol_permisos (rol_id, permiso_id) VALUES (?, ?)";
                        $stmt_insert = $conn->prepare($query_insert);
                        $stmt_insert->bind_param("ii", $rol_id, $permiso_row['id']);
                        $stmt_insert->execute();
                    }
                }
            }

            $conn->commit();
            sendResponse(true, "Rol creado correctamente", ['id' => $rol_id]);
        } catch (Exception $e) {
            $conn->rollback();
            error_log("Error al crear rol: " . $e->getMessage());
            sendResponse(false, "Error al crear rol");
        }
        break;

    case 'actualizarRol':
        try {
            $role_id = isset($datapost['role_id']) ? intval($datapost['role_id']) : 0;
            $nombre = isset($datapost['nombre']) ? trim($datapost['nombre']) : '';
            $descripcion = isset($datapost['descripcion']) ? trim($datapost['descripcion']) : '';
            $nivel = 1; // Valor por defecto
            $activo = isset($datapost['activo']) ? intval($datapost['activo']) : 1;
            $necesita_almacen = isset($datapost['necesita_almacen']) ? intval($datapost['necesita_almacen']) : 0;
            $permisos = isset($datapost['permisos']) ? $datapost['permisos'] : [];

            if ($role_id <= 0) {
                sendResponse(false, "ID del rol requerido");
                break;
            }

            // Verificar que el rol existe
            $query_check = "SELECT nombre FROM roles WHERE id = ?";
            $stmt_check = $conn->prepare($query_check);
            $stmt_check->bind_param("i", $role_id);
            $stmt_check->execute();
            $result_check = $stmt_check->get_result();
            $rol_existente = $result_check->fetch_assoc();

            if (!$rol_existente) {
                sendResponse(false, "Rol no encontrado");
                break;
            }

            // Validar nombre único si se está cambiando
            if (!empty($nombre) && $nombre !== $rol_existente['nombre']) {
                $query_nombre = "SELECT id FROM roles WHERE nombre = ? AND id != ?";
                $stmt_nombre = $conn->prepare($query_nombre);
                $stmt_nombre->bind_param("si", $nombre, $role_id);
                $stmt_nombre->execute();
                $result_nombre = $stmt_nombre->get_result();

                if ($result_nombre->fetch_assoc()) {
                    sendResponse(false, "Ya existe un rol con ese nombre");
                    break;
                }
            }

            // Iniciar transacción
            $conn->begin_transaction();

            // Actualizar rol
            $query = "UPDATE roles SET
                        nombre = ?,
                        descripcion = ?,
                        nivel = ?,
                        activo = ?,
                        necesita_almacen = ?,
                        fecha_actualizacion = CURRENT_TIMESTAMP
                    WHERE id = ?";

            $stmt = $conn->prepare($query);
            $nombre_final = !empty($nombre) ? $nombre : $rol_existente['nombre'];
            $stmt->bind_param("ssiiii", $nombre_final, $descripcion, $nivel, $activo, $necesita_almacen, $role_id);
            $stmt->execute();

            // Actualizar permisos si se proporcionaron
            if (is_array($permisos)) {
                // Eliminar permisos actuales
                $query_delete = "DELETE FROM rol_permisos WHERE rol_id = ?";
                $stmt_delete = $conn->prepare($query_delete);
                $stmt_delete->bind_param("i", $role_id);
                $stmt_delete->execute();

                // Asignar nuevos permisos
                foreach ($permisos as $permiso_nombre) {
                    // Obtener ID del permiso
                    $query_permiso = "SELECT id FROM permisos WHERE nombre = ? AND activo = 1";
                    $stmt_permiso = $conn->prepare($query_permiso);
                    $stmt_permiso->bind_param("s", $permiso_nombre);
                    $stmt_permiso->execute();
                    $result_permiso = $stmt_permiso->get_result();
                    $permiso_row = $result_permiso->fetch_assoc();

                    if ($permiso_row) {
                        $query_insert = "INSERT IGNORE INTO rol_permisos (rol_id, permiso_id) VALUES (?, ?)";
                        $stmt_insert = $conn->prepare($query_insert);
                        $stmt_insert->bind_param("ii", $role_id, $permiso_row['id']);
                        $stmt_insert->execute();
                    }
                }
            }

            $conn->commit();
            sendResponse(true, "Rol actualizado correctamente");
        } catch (Exception $e) {
            $conn->rollback();
            error_log("Error al actualizar rol: " . $e->getMessage());
            sendResponse(false, "Error al actualizar rol");
        }
        break;

    case 'eliminarRol':
        try {
            $role_id = isset($datapost['role_id']) ? intval($datapost['role_id']) : 0;

            if ($role_id <= 0) {
                sendResponse(false, "ID del rol requerido");
                break;
            }

            // Verificar que el rol no tenga usuarios asignados
            $query_usuarios = "SELECT COUNT(*) as total FROM usuarios WHERE rol_id = ? AND activo = 1";
            $stmt_usuarios = $conn->prepare($query_usuarios);
            $stmt_usuarios->bind_param("i", $role_id);
            $stmt_usuarios->execute();
            $result_usuarios = $stmt_usuarios->get_result();
            $usuarios_count = $result_usuarios->fetch_assoc()['total'];

            if ($usuarios_count > 0) {
                sendResponse(false, "No se puede eliminar el rol porque tiene usuarios asignados");
                break;
            }

            // Iniciar transacción
            $conn->begin_transaction();

            // Eliminar permisos del rol
            $query_permisos = "DELETE FROM rol_permisos WHERE rol_id = ?";
            $stmt_permisos = $conn->prepare($query_permisos);
            $stmt_permisos->bind_param("i", $role_id);
            $stmt_permisos->execute();

            // Eliminar rol
            $query = "DELETE FROM roles WHERE id = ?";
            $stmt = $conn->prepare($query);
            $stmt->bind_param("i", $role_id);
            $stmt->execute();

            if ($conn->affected_rows === 0) {
                $conn->rollback();
                sendResponse(false, "Rol no encontrado");
                break;
            }

            $conn->commit();
            sendResponse(true, "Rol eliminado correctamente");
        } catch (Exception $e) {
            $conn->rollback();
            error_log("Error al eliminar rol: " . $e->getMessage());
            sendResponse(false, "Error al eliminar rol");
        }
        break;

    case 'getPermisos':
        try {
            $query = "SELECT
                        id,
                        nombre,
                        descripcion,
                        modulo,
                        accion,
                        activo
                    FROM permisos
                    WHERE activo = 1
                    ORDER BY modulo ASC, accion ASC";

            $result = $conn->query($query);
            if (!$result) {
                sendResponse(false, "Error en consulta de permisos: " . $conn->error);
                break;
            }

            $permisos = [];
            while ($row = $result->fetch_assoc()) {
                $permisos[] = $row;
            }

            // Organizar por módulos
            $permisos_organizados = [];
            foreach ($permisos as $permiso) {
                $modulo = $permiso['modulo'];
                if (!isset($permisos_organizados[$modulo])) {
                    $permisos_organizados[$modulo] = [];
                }
                $permisos_organizados[$modulo][] = $permiso;
            }

            sendResponse(true, "Permisos obtenidos correctamente", $permisos_organizados);
        } catch (Exception $e) {
            error_log("Error al obtener permisos: " . $e->getMessage());
            sendResponse(false, "Error al obtener permisos");
        }
        break;

    default:
        sendResponse(false, "Operación no válida para roles");
        break;
}
