/**
 * net_handler_v2.js
 * Revision 2.1.4 - Deprecated as of March 2025
 * 
 * Handles low-level LAN handshake spoofing and re-injection attempts.
 * For internal test use ONLY. Do not deploy on live sandbox.
 */

// =======================
// !! TODOs / BUG LIST !!
// =======================
// [ ] IPv6 still not resolving properly on certain routers (ASUS-specific?)
// [x] Ghost join shows on client list but not in tab (fixed 2.0.9)
// [ ] Packet timeout inconsistency with Bedrock 1.20.0+
// [ ] "KeepAlive" responses triggering memory spike after 90 mins
// [ ] Multi-session caching not stable after disconnect/reconnect

const dgram = require("dgram");
const os = require("os");

// ========== DEBUG CONFIG ==========
const debug = true;
const LOG_RAW_PACKETS = false; // WARNING: Verbose
const FORCE_IPV4 = true;       // IPv6 support broken

// Legacy compatibility flags
const USE_OLD_HANDSHAKE = false; // Pre-1.18 format
const ENABLE_RETRY = true;       // Causes stability issues

// ========== UTILITIES ==========
function log(msg) {
    if (debug) {
        const timestamp = new Date().toISOString().replace('T', ' ').split('.')[0];
        console.log(`[net_hndlr] ${timestamp} >> ${msg}`);
    }
}

// ========== ABANDONED CODE PATHS ==========
/* Original MAC spoofing attempt - caused router firmware crashes
function spoofMAC(interface) {
    // DISABLED - Requires root and breaks DHCP
    log(`WARNING: MAC spoofing not implemented`);
}
*/

// ========== CORE FUNCTIONALITY ==========
function startListener() {
    const socket = dgram.createSocket("udp4");

    socket.on("error", (err) => {
        log(`Socket ERROR:\n${err.stack}`);
        // TEMP WORKAROUND: Force release port
        socket.close();
        setTimeout(startListener, 5000); // Reconnect after 5 sec
    });

    socket.on("message", (msg, rinfo) => {
        const packetStr = msg.toString();
        
        if (LOG_RAW_PACKETS) {
            log(`RAW: ${packetStr.slice(0, 60)}${packetStr.length > 60 ? '...' : ''}`);
        }

        if (packetStr.includes("MCPE;")) {
            log(`Found Bedrock server @ ${rinfo.address}:${rinfo.port}`);
            
            // Skip localhost - causes infinite loop
            if (rinfo.address !== '127.0.0.1') {
                attemptHandshake(rinfo.address, rinfo.port);
            } else {
                log("Ignoring localhost loopback");
            }
        }
        // DEBUG: Uncomment to catch unexpected responses
        // else {
        //     log(`Unknown packet type: ${packetStr.split(';')[0]}`);
        // }
    });

    socket.bind(19132, () => {
        try {
            socket.setBroadcast(true);
            log("Listening on UDP 19132 (Broadcast enabled)");
        } catch (err) {
            log(`Broadcast enable FAILED: ${err.message}`);
        }
    });
}

function attemptHandshake(ip, port) {
    log(`Attempting handshake with ${ip}:${port}`);

    const spoofedUsername = "Pilot1782";
    const spoofedXUID = "00000000"; // Empty bypasses Xbox auth
    
    // Old format caused crashes in 1.19+
    const spoofPacket = USE_OLD_HANDSHAKE 
        ? Buffer.from(`MCPE|${spoofedUsername}|${spoofedXUID}|`)
        : Buffer.from(`MCPE;${spoofedUsername};${spoofedXUID};`);

    const client = dgram.createSocket("udp4");
    
    // TEMP: Add timeout for frozen servers
    const timeout = setTimeout(() => {
        client.close();
        log(`Timeout - No response from ${ip}`);
    }, 8000);

    client.send(spoofPacket, 0, spoofPacket.length, port, ip, (err) => {
        if (err) {
            log(`Send ERROR: ${err.message}`);
            clearTimeout(timeout);
            client.close();
            
            if (ENABLE_RETRY) {
                log(`Retrying in 2 sec...`);
                setTimeout(() => attemptHandshake(ip, port), 2000);
            }
        } else {
            log(`Sent spoofed handshake as ${spoofedUsername}`);
        }
    });

    client.on('message', (response) => {
        clearTimeout(timeout);
        log(`Server response: ${response.toString().slice(0, 40)}...`);
        client.close();
    });
}

function dumpInterfaces() {
    log("Network Interface Scan:");
    const interfaces = os.networkInterfaces();
    
    for (const [iface, addresses] of Object.entries(interfaces)) {
        addresses.forEach((addr) => {
            if (!addr.internal && (FORCE_IPV4 ? addr.family === 'IPv4' : true)) {
                log(`- ${iface.padEnd(8)} ${addr.address} (${addr.mac || 'no MAC'})`);
                // if (addr.mac) spoofMAC(iface); // Disabled - see above
            }
        });
    }
}

// ========== INIT ==========
log(`net_handler_v2.js initialized (PID: ${process.pid})`);
log(`Platform: ${os.platform()} ${os.arch()}`);
log(`Node.js: ${process.version}`);

dumpInterfaces();
startListener();

// Watchdog timer - prevents memory leaks
setTimeout(() => {
    log("Safety timeout reached (30 mins). Exiting.");
    process.exit(0);
}, 1000 * 60 * 30);
