import { spawn, ChildProcess } from "child_process";
import { getConfig as loadConfig } from '../../shared/config';
const { values } = loadConfig();
const CLOUDFLARED_PATH = values.paths?.cloudflared || 'cloudflared';

let tunnelProcess: ChildProcess | null = null;
let exposedRooms = 0;
let publicUrl: string | null = null;
let tunnelPromise: Promise<string> | null = null;

export function openTunnel(): Promise<string> {
    if (tunnelProcess && publicUrl) {
        exposedRooms++;
        return Promise.resolve(publicUrl);
    }

    if (tunnelPromise) {
        return tunnelPromise;
    }

    tunnelPromise = new Promise((resolve, reject) => {
        const timeout = setTimeout(() => {
            cleanup();
            reject(new Error("Timeout esperando URL del túnel (30s)"));
        }, 30000);

        tunnelProcess = spawn(CLOUDFLARED_PATH, [
            "tunnel",
            "--url",
            "http://localhost:54322",
            "--no-autoupdate"
        ]);

        const cleanup = () => {
            clearTimeout(timeout);
            tunnelPromise = null;
        };

        let outputBuffer = "";

        const processOutput = (data: Buffer) => {
            const text = data.toString();
            outputBuffer += text;

            const match = outputBuffer.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/);
            if (match && !publicUrl) {
                publicUrl = match[0];
                exposedRooms = 1;
                cleanup();
                resolve(publicUrl);
            }
        };

        tunnelProcess.stdout?.on("data", (data) => {
            processOutput(data);
        });

        tunnelProcess.stderr?.on("data", (data) => {
            processOutput(data);
        });

        tunnelProcess.on("error", (error) => {
            console.error("[Cloudflared Process Error]", error);
            cleanup();
            tunnelProcess = null;
            reject(error);
        });

        tunnelProcess.on("exit", (code, signal) => {
            tunnelProcess = null;
            publicUrl = null;
            exposedRooms = 0;

            if (!publicUrl) {
                cleanup();
                reject(new Error(`Proceso cloudflared terminó antes de obtener URL (código: ${code})`));
            }
        });
    });

    return tunnelPromise;
}

export function closeTunnelIfUnused() {
    exposedRooms--;
    console.log(`[Tunnel Manager] Rooms expuestas: ${exposedRooms}`);

    if (exposedRooms <= 0 && tunnelProcess) {
        console.log("[Tunnel Manager] Cerrando túnel...");
        tunnelProcess.kill();
        tunnelProcess = null;
        publicUrl = null;
        exposedRooms = 0;
        tunnelPromise = null;
    }
}

export function getTunnelUrl(): string | null {
    return publicUrl;
}

export function forceTunnelClose() {
    if (tunnelProcess) {
        console.log("[Tunnel Manager] Forzando cierre del túnel...");
        tunnelProcess.kill();
        tunnelProcess = null;
        publicUrl = null;
        exposedRooms = 0;
        tunnelPromise = null;
    }
}