<?php

/**
 * Roles.php - Manejo de roles y permisos
 */

// Incluir modelos necesarios
require_once '../../modelos/Usuario.php';
require_once '../../modelos/Auth.php';

// Función para enviar respuesta JSON (si no está definida)
if (!function_exists('sendResponse')) {
    function sendResponse($success, $message = '', $data = null)
    {
        echo json_encode([
            "success" => $success,
            "message" => $message,
            "data" => $data
        ]);
        exit;
    }
}

// Función para validar token (si no está definida)
if (!function_exists('validateToken')) {
    function validateToken($conn, $authHeader)
    {
        error_log("Validando token en Roles.php...");

        if (empty($authHeader)) {
            error_log("Header Authorization vacío");
            return null;
        }

        $token = str_replace('Bearer ', '', $authHeader);

        // Usar el modelo Auth para verificar el JWT
        $auth = new Auth($conn);
        $userData = $auth->obtenerUsuarioDeToken($token);

        if ($userData) {
            error_log("Usuario validado: " . $userData['username']);
            return $userData;
        }

        return null;
    }
}

// Verificar autenticación
$authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (empty($authHeader)) {
    $authHeader = getallheaders()['Authorization'] ?? '';
}

// Validar token
$user = validateToken($conn, $authHeader);
if (!$user) {
    sendResponse(false, "No autorizado " . json_encode($authHeader) . " " . json_encode($user));
}

$usuario = new Usuario($conn);

// === OBTENER TODOS LOS ROLES ===
if ($tipo === 'getRoles') {
    error_log("=== OBTENIENDO ROLES ===");

    try {
        $query = "SELECT r.id, r.nombre, r.descripcion, r.activo, r.created_at, r.updated_at,
                         COUNT(ur.usuario_id) as usuarios_count
                  FROM roles r 
                  LEFT JOIN usuario_roles ur ON r.id = ur.rol_id 
                  WHERE r.id > 0 
                  GROUP BY r.id, r.nombre, r.descripcion, r.activo, r.created_at, r.updated_at
                  ORDER BY r.nombre";
        $stmt = $conn->prepare($query);
        $stmt->execute();

        $roles = $stmt->fetchAll(PDO::FETCH_ASSOC);
        sendResponse(true, "Roles obtenidos", $roles);
    } catch (Exception $e) {
        error_log("Error obteniendo roles: " . $e->getMessage());
        sendResponse(false, "Error al obtener roles");
    }
}

// === CREAR ROL ===
if ($tipo === 'createRol') {
    error_log("=== CREANDO ROL ===");

    // Verificar permisos
    if (!$usuario->verificarPermiso($user['sub'], 'configuracion', 'crear')) {
        sendResponse(false, "Sin permisos para crear roles");
    }

    $nombre = isset($datapost['nombre']) ? $datapost['nombre'] : '';
    $descripcion = isset($datapost['descripcion']) ? $datapost['descripcion'] : '';

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

    try {
        // Verificar si el rol ya existe
        $query = "SELECT COUNT(*) as count FROM roles WHERE nombre = :nombre";
        $stmt = $conn->prepare($query);
        $stmt->bindParam(':nombre', $nombre);
        $stmt->execute();
        $result = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($result['count'] > 0) {
            sendResponse(false, "El rol ya existe");
        }

        // Crear el rol
        $query = "INSERT INTO roles (nombre, descripcion) VALUES (:nombre, :descripcion)";
        $stmt = $conn->prepare($query);
        $stmt->bindParam(':nombre', $nombre);
        $stmt->bindParam(':descripcion', $descripcion);

        if ($stmt->execute()) {
            $rolId = $conn->lastInsertId();
            sendResponse(true, "Rol creado exitosamente", ['id' => $rolId]);
        } else {
            sendResponse(false, "Error al crear rol");
        }
    } catch (Exception $e) {
        error_log("Error creando rol: " . $e->getMessage());
        sendResponse(false, "Error al crear rol");
    }
}

// === ACTUALIZAR ROL ===
if ($tipo === 'updateRol') {
    error_log("=== ACTUALIZANDO ROL ===");

    $id = isset($datapost['id']) ? $datapost['id'] : null;

    if (!$id) {
        sendResponse(false, "ID de rol requerido");
    }

    // Verificar permisos
    if (!$usuario->verificarPermiso($user['sub'], 'configuracion', 'actualizar')) {
        sendResponse(false, "Sin permisos para actualizar roles");
    }

    try {
        $updateData = [];
        $allowedFields = ['nombre', 'descripcion', 'activo'];

        foreach ($allowedFields as $field) {
            if (isset($datapost[$field])) {
                $updateData[$field] = $datapost[$field];
            }
        }

        if (empty($updateData)) {
            sendResponse(false, "No hay datos para actualizar");
        }

        $setClause = [];
        foreach (array_keys($updateData) as $field) {
            $setClause[] = "$field = :$field";
        }

        $query = "UPDATE roles SET " . implode(', ', $setClause) . ", updated_at = CURRENT_TIMESTAMP WHERE id = :id";
        $stmt = $conn->prepare($query);

        foreach ($updateData as $field => $value) {
            $stmt->bindValue(":$field", $value);
        }
        $stmt->bindParam(':id', $id);

        if ($stmt->execute()) {
            sendResponse(true, "Rol actualizado exitosamente");
        } else {
            sendResponse(false, "Error al actualizar rol");
        }
    } catch (Exception $e) {
        error_log("Error actualizando rol: " . $e->getMessage());
        sendResponse(false, "Error al actualizar rol");
    }
}

// === ELIMINAR ROL ===
if ($tipo === 'deleteRol') {
    error_log("=== ELIMINANDO ROL ===");

    $id = isset($datapost['id']) ? $datapost['id'] : null;

    if (!$id) {
        sendResponse(false, "ID de rol requerido");
    }

    // Verificar permisos
    if (!$usuario->verificarPermiso($user['sub'], 'configuracion', 'eliminar')) {
        sendResponse(false, "Sin permisos para eliminar roles");
    }

    // No permitir eliminar roles del sistema
    if (in_array($id, [1, 2, 3, 4, 5])) { // IDs de roles del sistema
        sendResponse(false, "No se pueden eliminar roles del sistema");
    }

    try {
        // Verificar si hay usuarios con este rol
        $query = "SELECT COUNT(*) as count FROM usuario_roles WHERE rol_id = :rol_id";
        $stmt = $conn->prepare($query);
        $stmt->bindParam(':rol_id', $id);
        $stmt->execute();
        $result = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($result['count'] > 0) {
            sendResponse(false, "No se puede eliminar el rol porque tiene usuarios asignados");
        }

        // Soft delete
        $query = "UPDATE roles SET activo = 0, updated_at = CURRENT_TIMESTAMP WHERE id = :id";
        $stmt = $conn->prepare($query);
        $stmt->bindParam(':id', $id);

        if ($stmt->execute()) {
            sendResponse(true, "Rol eliminado exitosamente");
        } else {
            sendResponse(false, "Error al eliminar rol");
        }
    } catch (Exception $e) {
        error_log("Error eliminando rol: " . $e->getMessage());
        sendResponse(false, "Error al eliminar rol");
    }
}

// === OBTENER PERMISOS ===
if ($tipo === 'getPermisos') {
    error_log("=== OBTENIENDO PERMISOS ===");

    try {
        $query = "SELECT id, nombre, descripcion FROM permisos ORDER BY nombre";
        $stmt = $conn->prepare($query);
        $stmt->execute();

        $permisos = $stmt->fetchAll(PDO::FETCH_ASSOC);
        sendResponse(true, "Permisos obtenidos", $permisos);
    } catch (Exception $e) {
        error_log("Error obteniendo permisos: " . $e->getMessage());
        sendResponse(false, "Error al obtener permisos");
    }
}

// === ASIGNAR PERMISOS A ROL ===
if ($tipo === 'asignarPermisos') {
    error_log("=== ASIGNANDO PERMISOS A ROL ===");

    $rolId = isset($datapost['rol_id']) ? $datapost['rol_id'] : null;
    $moduloId = isset($datapost['modulo_id']) ? $datapost['modulo_id'] : null;
    $permisos = isset($datapost['permisos']) ? $datapost['permisos'] : [];

    if (!$rolId || !$moduloId) {
        sendResponse(false, "Rol y módulo requeridos");
    }

    // Verificar permisos
    if (!$usuario->verificarPermiso($user['sub'], 'configuracion', 'actualizar')) {
        sendResponse(false, "Sin permisos para asignar permisos");
    }

    try {
        // Primero eliminar permisos existentes para este rol y módulo
        $query = "DELETE FROM rol_modulo_permisos WHERE rol_id = :rol_id AND modulo_id = :modulo_id";
        $stmt = $conn->prepare($query);
        $stmt->bindParam(':rol_id', $rolId);
        $stmt->bindParam(':modulo_id', $moduloId);
        $stmt->execute();

        // Insertar nuevos permisos
        if (!empty($permisos)) {
            $query = "INSERT INTO rol_modulo_permisos (rol_id, modulo_id, permiso_id) VALUES (:rol_id, :modulo_id, :permiso_id)";
            $stmt = $conn->prepare($query);

            foreach ($permisos as $permisoId) {
                $stmt->bindParam(':rol_id', $rolId);
                $stmt->bindParam(':modulo_id', $moduloId);
                $stmt->bindParam(':permiso_id', $permisoId);
                $stmt->execute();
            }
        }

        sendResponse(true, "Permisos asignados exitosamente");
    } catch (Exception $e) {
        error_log("Error asignando permisos: " . $e->getMessage());
        sendResponse(false, "Error al asignar permisos");
    }
}

// === OBTENER MÓDULOS ===
if ($tipo === 'getModulos') {
    error_log("=== OBTENIENDO MÓDULOS ===");

    try {
        $query = "SELECT id, nombre, descripcion, icono, ruta, orden, activo FROM modulos WHERE activo = 1 ORDER BY orden, nombre";
        $stmt = $conn->prepare($query);
        $stmt->execute();

        $modulos = $stmt->fetchAll(PDO::FETCH_ASSOC);
        sendResponse(true, "Módulos obtenidos", $modulos);
    } catch (Exception $e) {
        error_log("Error obteniendo módulos: " . $e->getMessage());
        sendResponse(false, "Error al obtener módulos");
    }
}

// === OBTENER MATRIZ DE PERMISOS ===
if ($tipo === 'getPermissionsMatrix') {
    error_log("=== OBTENIENDO MATRIZ DE PERMISOS ===");

    try {
        // Obtener todos los permisos asignados a roles
        $query = "SELECT rmp.rol_id, rmp.modulo_id, rmp.permiso_id
                  FROM rol_modulo_permisos rmp
                  INNER JOIN roles r ON rmp.rol_id = r.id
                  INNER JOIN modulos m ON rmp.modulo_id = m.id
                  INNER JOIN permisos p ON rmp.permiso_id = p.id
                  WHERE r.activo = 1 AND m.activo = 1";

        $stmt = $conn->prepare($query);
        $stmt->execute();

        $permissions = $stmt->fetchAll(PDO::FETCH_ASSOC);

        // Estructurar la matriz de permisos
        $matrix = [];
        foreach ($permissions as $permission) {
            $roleKey = "role_" . $permission['rol_id'];
            $moduleKey = "module_" . $permission['modulo_id'];
            $permissionKey = "permission_" . $permission['permiso_id'];

            if (!isset($matrix[$roleKey])) {
                $matrix[$roleKey] = [];
            }
            if (!isset($matrix[$roleKey][$moduleKey])) {
                $matrix[$roleKey][$moduleKey] = [];
            }

            $matrix[$roleKey][$moduleKey][$permissionKey] = true;
        }

        sendResponse(true, "Matriz de permisos obtenida", $matrix);
    } catch (Exception $e) {
        error_log("Error obteniendo matriz de permisos: " . $e->getMessage());
        sendResponse(false, "Error al obtener matriz de permisos");
    }
}

// === GUARDAR MATRIZ DE PERMISOS ===
if ($tipo === 'savePermissionsMatrix') {
    error_log("=== GUARDANDO MATRIZ DE PERMISOS ===");

    $permissions = isset($datapost['permissions']) ? $datapost['permissions'] : [];

    if (empty($permissions)) {
        sendResponse(false, "No se proporcionaron permisos para guardar");
    }

    // Verificar permisos
    if (!$usuario->verificarPermiso($user['sub'], 'configuracion', 'actualizar')) {
        sendResponse(false, "Sin permisos para actualizar permisos");
    }

    try {
        $conn->beginTransaction();

        // Para cada rol-módulo, actualizar permisos
        foreach ($permissions as $roleId => $modules) {
            foreach ($modules as $moduleId => $rolePermissions) {
                // Eliminar permisos existentes para este rol-módulo
                $deleteQuery = "DELETE FROM rol_modulo_permisos WHERE rol_id = :rol_id AND modulo_id = :modulo_id";
                $deleteStmt = $conn->prepare($deleteQuery);
                $deleteStmt->bindParam(':rol_id', $roleId);
                $deleteStmt->bindParam(':modulo_id', $moduleId);
                $deleteStmt->execute();

                // Insertar nuevos permisos
                if (!empty($rolePermissions)) {
                    $insertQuery = "INSERT INTO rol_modulo_permisos (rol_id, modulo_id, permiso_id) VALUES (:rol_id, :modulo_id, :permiso_id)";
                    $insertStmt = $conn->prepare($insertQuery);

                    foreach ($rolePermissions as $permissionId) {
                        $insertStmt->bindParam(':rol_id', $roleId);
                        $insertStmt->bindParam(':modulo_id', $moduleId);
                        $insertStmt->bindParam(':permiso_id', $permissionId);
                        $insertStmt->execute();
                    }
                }
            }
        }

        $conn->commit();
        sendResponse(true, "Matriz de permisos guardada exitosamente");
    } catch (Exception $e) {
        $conn->rollback();
        error_log("Error guardando matriz de permisos: " . $e->getMessage());
        sendResponse(false, "Error al guardar matriz de permisos");
    }
}
