function connectGame() {
    if (socket) {
        socket.close();
    }

    if (typeof pingInterval !== 'undefined' && pingInterval) {
        clearInterval(pingInterval);
    }

    const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
    const url = proto + "//" + location.host + "/ws";

    console.log("Verbinde zu:", url);
    socket = new WebSocket(url);

    socket.onopen = () => {
        console.log("🟢 WS Verbunden. Spiel startet.");

        // Alles zurücksetzen
        obstacleBuffer = [];
        platformBuffer = [];
        obstacles = [];
        platforms = [];
        currentLatencyMs = 0;

        isGameRunning = true;
        isGameOver = false;
        isLoaded = true;

        pingInterval = setInterval(sendPing, 1000);

        requestAnimationFrame(gameLoop);
    };

    socket.onmessage = (event) => {
        try {
            const msg = JSON.parse(event.data);

            if (msg.type === "pong") {
                const now = Date.now();
                const sentTime = msg.ts;


                const rtt = now - sentTime;


                const latency = rtt / 2;


                if (currentLatencyMs === 0) {
                    currentLatencyMs = latency;
                } else {

                    currentLatencyMs = (currentLatencyMs * 0.9) + (latency * 0.1);
                }

            }


            if (msg.type === "chunk") {


                const msPerTick = 1000 / 20;
                const latencyInTicks = Math.floor(currentLatencyMs / msPerTick);


                const targetTick = msg.serverTick + latencyInTicks;
                const drift = targetTick - currentTick;


                if (Math.abs(drift) > 2) {
                    currentTick = targetTick;
                }


                let sTick = msg.serverTick;
                let currentSpeedPerTick = 15.0 + (sTick / 1000.0) * 1.5;
                if (currentSpeedPerTick > 36) currentSpeedPerTick = 36;

                const speedPerMs = currentSpeedPerTick / msPerTick;


                let dynamicCorrection = (currentLatencyMs * speedPerMs) + 5;
                if (dynamicCorrection > 100) dynamicCorrection = 100; // Limit


                if (msg.obstacles) {
                    msg.obstacles.forEach(o => {
                        o.x -= dynamicCorrection;
                        o.prevX = o.x;
                        obstacleBuffer.push(o);
                    });
                }

                if (msg.platforms) {
                    msg.platforms.forEach(p => {
                        p.x -= dynamicCorrection;
                        p.prevX = p.x;
                        platformBuffer.push(p);
                    });
                }

                if (msg.score !== undefined) score = msg.score;

                if (msg.powerups) {
                    godModeLives = msg.powerups.godLives;
                    hasBat = msg.powerups.hasBat;
                    bootTicks = msg.powerups.bootTicks;
                }
            }

            if (msg.type === "init") {
                console.log("📩 INIT EMPFANGEN:", msg); // <--- DEBUG LOG

                if (msg.sessionId) {
                    sessionID = msg.sessionId; // Globale Variable setzen
                    console.log("🔑 Session ID gesetzt auf:", sessionID);
                } else {
                    console.error("❌ INIT FEHLER: Keine sessionId im Paket!", msg);
                }
            }

            if (msg.type === "dead") {
                console.log("💀 Server sagt: Game Over");

                if (msg.score) score = msg.score;

                // Verbindung sauber trennen
                socket.close();
                if (pingInterval) clearInterval(pingInterval);

                gameOver("Vom Server gestoppt");
            }

            if (msg.type === "debug_sync") {



                let clientSpeed = BASE_SPEED + (currentTick / 1000.0) * 1.5;
                if (clientSpeed > 36.0) clientSpeed = 36.0;

                let serverSpeed = msg.currentSpeed || 0;

                let diffSpeed = clientSpeed - serverSpeed;
                let speedIcon = Math.abs(diffSpeed) < 0.01 ? "✅" : "❌";

                console.group(`📊 SYNC REPORT (Tick: ${currentTick} vs Server: ${msg.serverTick})`);

                // --- DER NEUE SPEED CHECK ---
                console.log(`🚀 SPEED CHECK: ${speedIcon}`);
                console.log(`   Client: ${clientSpeed.toFixed(4)} px/tick (Basis: Tick ${currentTick})`);
                console.log(`   Server: ${serverSpeed.toFixed(4)} px/tick (Basis: Tick ${msg.serverTick})`);

                if (Math.abs(diffSpeed) > 0.01) {
                    console.warn(`⚠️ ACHTUNG: Geschwindigkeiten weichen ab! Diff: ${diffSpeed.toFixed(4)}`);
                    console.warn("Ursache: Client nutzt 'Score', Server nutzt 'Ticks'. Sind diese synchron?");
                }

                generateSyncTable("Obstacles", obstacles, msg.obstacles);


                generateSyncTable("Platforms", platforms, msg.platforms);

                console.groupEnd();
            }

        } catch (e) {
            console.error("Fehler beim Verarbeiten der Nachricht:", e);
        }
    };


    socket.onclose = () => {
        console.log("🔴 WS Verbindung getrennt.");
        if (pingInterval) clearInterval(pingInterval);
    };

    socket.onerror = (error) => {
        console.error("WS Fehler:", error);
    };
}


function sendPing() {
    if (socket && socket.readyState === WebSocket.OPEN) {
        socket.send(JSON.stringify({
            type: "ping",
            tick: Date.now() // Timestamp als Integer
        }));
    }
}

function sendInput(type, action) {
    if (socket && socket.readyState === WebSocket.OPEN) {
        socket.send(JSON.stringify({
            type: "input",
            input: action
        }));
    }
}

// Helper für die Tabelle
function generateSyncTable(label, clientList, serverList) {
    if (!serverList) serverList = [];

    console.log(`--- ${label} Analyse (Ping: ${Math.round(currentLatencyMs)}ms) ---`);

    const report = [];
    const matchedServerIndices = new Set();


    const msPerTick = 50;


    let debugSpeed = 15.0 + (score / 1000.0) * 1.5;
    if (debugSpeed > 36) debugSpeed = 36;

    const speedPerMs = debugSpeed / msPerTick;


    const latencyPx = currentLatencyMs * speedPerMs;


    clientList.forEach((cObj) => {
        let bestMatch = null;
        let bestDist = 9999;
        let bestSIdx = -1;


        const cID = cObj.def ? cObj.def.id : (cObj.id || "unknown");


        serverList.forEach((sObj, sIdx) => {
            if (matchedServerIndices.has(sIdx)) return;

            const sID = sObj.id || "unknown";

            const sPosCorrected = sObj.x - latencyPx;
            const dist = Math.abs(cObj.x - sPosCorrected);

            const isTypeMatch = (label === "Platforms") || (cID === sID);

            // Toleranter Suchradius (500px), falls Drift groß ist
            if (isTypeMatch && dist < bestDist && dist < 500) {
                bestDist = dist;
                bestMatch = sObj;
                bestSIdx = sIdx;
            }
        });

        // Datenzeile bauen
        let serverXRaw = "---";
        let serverXCorrected = "---";
        let diffReal = "---";
        let status = "👻 GHOST (Client only)";

        if (bestMatch) {
            matchedServerIndices.add(bestSIdx);

            serverXRaw = bestMatch.x;
            serverXCorrected = bestMatch.x - latencyPx;

            diffReal = cObj.x - serverXCorrected;

            const absDiff = Math.abs(diffReal);
            if (absDiff < 20) status = "✅ PERFECT";
            else if (absDiff < 60) status = "🆗 OK";
            else if (absDiff < 150) status = "⚠️ DRIFT";
            else status = "🔥 BROKEN";
        }

        report.push({
            "ID": cID,
            "Client X": Math.round(cObj.x),
            "Server X (Raw)": Math.round(serverXRaw),
            "Server X (Sim)": Math.round(serverXCorrected), // Wo es sein sollte
            "Diff (Real)": typeof diffReal === 'number' ? Math.round(diffReal) : "---",
            "Status": status
        });
    });

    serverList.forEach((sObj, sIdx) => {
        if (!matchedServerIndices.has(sIdx)) {
            const sPosCorrected = sObj.x - latencyPx;
            let status = "❌ MISSING";

            if (sPosCorrected > 850) status = "🔮 FUTURE (Buffer)"; // Noch rechts vom Screen
            if (sPosCorrected < -100) status = "🗑️ OLD (Server lag)"; // Schon links raus

            report.push({
                "ID": sObj.id || "?",
                "Client X": "---",
                "Server X (Raw)": Math.round(sObj.x),
                "Server X (Sim)": Math.round(sPosCorrected),
                "Diff (Real)": "---",
                "Status": status
            });
        }
    });

    report.sort((a, b) => {
        const valA = (typeof a["Client X"] === 'number') ? a["Client X"] : a["Server X (Sim)"];
        const valB = (typeof b["Client X"] === 'number') ? b["Client X"] : b["Server X (Sim)"];
        return valA - valB;
    });

    if (report.length > 0) console.table(report);
    else console.log("Leer.");
}

function sendPhysicsSync(y, vy) {
    if (socket && socket.readyState === WebSocket.OPEN) {
        socket.send(JSON.stringify({
            type: "sync",
            y: y,
            vy: vy,
            tick: currentTick
        }));
    }
}