<?php
/**
 * NEXUS IT - SesionRemotaController
 * Gestión de sesiones de soporte remoto (AnyDesk, MeshCentral, TeamViewer, Guacamole)
 * 
 * Schema: sesiones_remotas
 * id, ticket_id, tecnico_id, activo_id, proveedor(meshcentral/anydesk/teamviewer/guacamole),
 * session_id_externo, estado(iniciada/activa/finalizada/fallida), inicio_at, fin_at, notas
 */
class SesionRemotaController {

    /**
     * GET /sesiones-remotas — Listar sesiones (admin/tecnico)
     */
    public static function index(): void {
        $payload = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($payload);
        $db = getDB();

        $page = max(1, (int)($_GET['page'] ?? 1));
        $perPage = min(50, max(1, (int)($_GET['per_page'] ?? 20)));
        $offset = ($page - 1) * $perPage;

        $where = ["1=1"]; $params = [];
        if (!empty($_GET['estado'])) { $where[] = "sr.estado = ?"; $params[] = $_GET['estado']; }
        if (!empty($_GET['proveedor'])) { $where[] = "sr.proveedor = ?"; $params[] = $_GET['proveedor']; }
        if (!empty($_GET['tecnico_id'])) { $where[] = "sr.tecnico_id = ?"; $params[] = (int)$_GET['tecnico_id']; }
        if (!empty($_GET['activo_id'])) { $where[] = "sr.activo_id = ?"; $params[] = (int)$_GET['activo_id']; }

        // Non-admins only see their own sessions
        if ($payload['rol'] === 'tecnico') { $where[] = "sr.tecnico_id = ?"; $params[] = $payload['sub']; }

        $whereStr = implode(' AND ', $where);
        $countStmt = $db->prepare("SELECT COUNT(*) FROM sesiones_remotas sr WHERE $whereStr");
        $countStmt->execute($params);
        $total = (int)$countStmt->fetchColumn();

        $stmt = $db->prepare("
            SELECT sr.*, 
                u.nombre_completo as tecnico_nombre,
                a.codigo_activo, a.hostname, a.marca, a.modelo, a.direccion_ip,
                au.nombre_completo as usuario_equipo,
                t.numero_ticket, t.titulo as ticket_titulo
            FROM sesiones_remotas sr
            LEFT JOIN usuarios u ON sr.tecnico_id = u.id
            LEFT JOIN activos a ON sr.activo_id = a.id
            LEFT JOIN usuarios au ON a.usuario_asignado_id = au.id
            LEFT JOIN tickets t ON sr.ticket_id = t.id
            WHERE $whereStr 
            ORDER BY sr.inicio_at DESC 
            LIMIT $perPage OFFSET $offset
        ");
        $stmt->execute($params);
        Response::paginated($stmt->fetchAll(), $total, $page, $perPage);
    }

    /**
     * GET /sesiones-remotas/:id — Ver detalle sesión
     */
    public static function ver(int $id): void {
        $payload = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($payload);
        $db = getDB();

        $stmt = $db->prepare("
            SELECT sr.*, 
                u.nombre_completo as tecnico_nombre, u.email as tecnico_email,
                a.codigo_activo, a.hostname, a.marca, a.modelo, a.direccion_ip, a.sistema_operativo,
                au.nombre_completo as usuario_equipo, au.email as usuario_email,
                t.numero_ticket, t.titulo as ticket_titulo
            FROM sesiones_remotas sr
            LEFT JOIN usuarios u ON sr.tecnico_id = u.id
            LEFT JOIN activos a ON sr.activo_id = a.id
            LEFT JOIN usuarios au ON a.usuario_asignado_id = au.id
            LEFT JOIN tickets t ON sr.ticket_id = t.id
            WHERE sr.id = ?
        ");
        $stmt->execute([$id]);
        $sesion = $stmt->fetch();
        if (!$sesion) Response::notFound('Sesión no encontrada');
        Response::success($sesion);
    }

    /**
     * POST /sesiones-remotas — Iniciar nueva sesión remota
     */
    public static function iniciar(): void {
        $payload = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($payload);
        $body = Validator::getBody();
        $db = getDB();

        // Require at least an activo_id
        if (empty($body['activo_id'])) Response::error('activo_id es requerido');

        // Verify the asset exists and get its info
        $activo = $db->prepare("SELECT id, hostname, direccion_ip, codigo_activo FROM activos WHERE id = ?");
        $activo->execute([$body['activo_id']]);
        $activoData = $activo->fetch();
        if (!$activoData) Response::notFound('Activo no encontrado');

        $proveedor = $body['proveedor'] ?? 'anydesk';
        $validProveedores = ['meshcentral', 'anydesk', 'teamviewer', 'guacamole'];
        if (!in_array($proveedor, $validProveedores)) Response::error('Proveedor no válido: ' . implode(', ', $validProveedores));

        // Generate unique session ID
        $sessionId = strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 12));

        $stmt = $db->prepare("INSERT INTO sesiones_remotas (ticket_id, tecnico_id, activo_id, proveedor, session_id_externo, estado, inicio_at, notas) VALUES (?,?,?,?,?,?,NOW(),?)");
        $stmt->execute([
            $body['ticket_id'] ?? null,
            $payload['sub'],
            $body['activo_id'],
            $proveedor,
            $body['session_id_externo'] ?? $sessionId,
            'iniciada',
            $body['notas'] ?? null
        ]);
        $id = (int)$db->lastInsertId();

        // Log
        if (class_exists('AuditService')) AuditService::log('iniciar_sesion_remota', 'sesiones_remotas', $id, null, ['activo_id' => $body['activo_id'], 'proveedor' => $proveedor]);

        // Notify - create a notification for the asset's user
        try {
            $asignado = $db->prepare("SELECT usuario_asignado_id FROM activos WHERE id = ?");
            $asignado->execute([$body['activo_id']]);
            $asignadoData = $asignado->fetch();
            if ($asignadoData && $asignadoData['usuario_asignado_id']) {
                $db->prepare("INSERT INTO notificaciones (usuario_id, titulo, mensaje, tipo, url_accion, referencia_tipo, referencia_id) VALUES (?,?,?,?,?,?,?)")
                    ->execute([
                        $asignadoData['usuario_asignado_id'],
                        'Sesión remota iniciada',
                        "Un técnico ha iniciado una sesión de soporte remoto en tu equipo ({$activoData['hostname']})",
                        'sistema',
                        '/portal/mis-equipos.html',
                        'sesiones_remotas',
                        $id
                    ]);
            }
        } catch (\Exception $e) {}

        // Build connection info based on provider
        $conexionInfo = self::getConexionInfo($proveedor, $activoData, $body['session_id_externo'] ?? $sessionId);

        Response::created([
            'id' => $id,
            'session_id' => $body['session_id_externo'] ?? $sessionId,
            'proveedor' => $proveedor,
            'activo' => $activoData,
            'conexion' => $conexionInfo
        ], 'Sesión remota iniciada');
    }

    /**
     * PUT /sesiones-remotas/:id — Actualizar estado de sesión
     */
    public static function actualizar(int $id): void {
        $payload = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($payload);
        $body = Validator::getBody();
        $db = getDB();

        $fields = []; $params = [];
        if (!empty($body['estado'])) {
            $fields[] = "estado = ?"; $params[] = $body['estado'];
            if ($body['estado'] === 'finalizada' || $body['estado'] === 'fallida') {
                $fields[] = "fin_at = NOW()";
            }
            if ($body['estado'] === 'activa') {
                // Keep it as is
            }
        }
        if (isset($body['notas'])) { $fields[] = "notas = ?"; $params[] = $body['notas']; }
        if (!empty($body['session_id_externo'])) { $fields[] = "session_id_externo = ?"; $params[] = $body['session_id_externo']; }

        if (empty($fields)) Response::error('Nada que actualizar');
        $params[] = $id;
        $db->prepare("UPDATE sesiones_remotas SET " . implode(', ', $fields) . " WHERE id = ?")->execute($params);

        if (class_exists('AuditService')) AuditService::log('actualizar_sesion_remota', 'sesiones_remotas', $id, null, $body);
        Response::success(null, 'Sesión actualizada');
    }

    /**
     * GET /sesiones-remotas/stats — Session statistics
     */
    public static function stats(): void {
        $payload = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($payload);
        $db = getDB();

        $total = (int)$db->query("SELECT COUNT(*) FROM sesiones_remotas")->fetchColumn();
        $activas = (int)$db->query("SELECT COUNT(*) FROM sesiones_remotas WHERE estado IN ('iniciada','activa')")->fetchColumn();
        $hoy = (int)$db->query("SELECT COUNT(*) FROM sesiones_remotas WHERE DATE(inicio_at) = CURDATE()")->fetchColumn();

        // By provider
        $porProveedor = $db->query("SELECT proveedor, COUNT(*) as total FROM sesiones_remotas GROUP BY proveedor ORDER BY total DESC")->fetchAll();

        // Average duration (in minutes) of completed sessions
        $duracionPromedio = $db->query("SELECT ROUND(AVG(TIMESTAMPDIFF(MINUTE, inicio_at, fin_at)),1) as promedio FROM sesiones_remotas WHERE estado = 'finalizada' AND fin_at IS NOT NULL")->fetch();

        // Top technicians
        $topTecnicos = $db->query("SELECT u.nombre_completo, COUNT(*) as total FROM sesiones_remotas sr JOIN usuarios u ON sr.tecnico_id = u.id GROUP BY sr.tecnico_id ORDER BY total DESC LIMIT 5")->fetchAll();

        Response::success([
            'total' => $total,
            'activas' => $activas,
            'hoy' => $hoy,
            'por_proveedor' => $porProveedor,
            'duracion_promedio_min' => $duracionPromedio['promedio'] ?? 0,
            'top_tecnicos' => $topTecnicos
        ]);
    }

    /**
     * Build connection info for different providers
     */
    private static function getConexionInfo(string $proveedor, array $activo, string $sessionId): array {
        $ip = $activo['direccion_ip'] ?? '';
        $hostname = $activo['hostname'] ?? '';

        switch ($proveedor) {
            case 'anydesk':
                return [
                    'tipo' => 'anydesk',
                    'instrucciones' => "Abrir AnyDesk e ingresar el ID del equipo remoto",
                    'url_protocolo' => "anydesk:$sessionId",
                    'app_url' => 'https://anydesk.com/en/downloads'
                ];
            case 'teamviewer':
                return [
                    'tipo' => 'teamviewer',
                    'instrucciones' => "Abrir TeamViewer e ingresar el ID del equipo",
                    'url_protocolo' => "teamviewer10://control?device=$sessionId",
                    'app_url' => 'https://www.teamviewer.com/es/descarga/'
                ];
            case 'meshcentral':
                // MeshCentral uses web-based access
                $meshUrl = 'https://mesh.evolucionamos.com'; // Configurable
                return [
                    'tipo' => 'meshcentral',
                    'instrucciones' => "Conectar via MeshCentral web console",
                    'url' => "$meshUrl/#/device/$sessionId",
                    'app_url' => $meshUrl
                ];
            case 'guacamole':
                $guacUrl = 'https://guac.evolucionamos.com';
                return [
                    'tipo' => 'guacamole',
                    'instrucciones' => "Conectar via Apache Guacamole (RDP/VNC/SSH)",
                    'url' => "$guacUrl/#/client/$sessionId",
                    'protocolos' => ['rdp', 'vnc', 'ssh']
                ];
            default:
                return ['tipo' => $proveedor, 'session_id' => $sessionId];
        }
    }
}
