import { useEffect, useRef } from "react";
import { Terminal } from "@xterm/xterm";
import { FitAddon } from "@xterm/addon-fit";
import "@xterm/xterm/css/xterm.css";

interface LiveTerminalProps {
    /** WebSocket URL for terminal I/O */
    wsUrl: string;
    /** Callback when terminal exits */
    onExit?: () => void;
    /** Callback when connected */
    onConnected?: () => void;
    /** Callback for errors */
    onError?: (error: string) => void;
}

export default function LiveTerminal({ wsUrl, onExit, onConnected, onError }: LiveTerminalProps) {
    const containerRef = useRef<HTMLDivElement>(null);
    const terminalRef = useRef<Terminal | null>(null);
    const fitAddonRef = useRef<FitAddon | null>(null);
    const wsRef = useRef<WebSocket | null>(null);

    // Initialize terminal and WebSocket
    useEffect(() => {
        if (!containerRef.current) return;

        const terminal = new Terminal({
            cursorBlink: true,
            fontFamily: "'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, monospace",
            fontSize: 14,
            lineHeight: 1.2,
            theme: {
                background: "#1a1a1a",
                foreground: "#d4d4d4",
                cursor: "#d4d4d4",
                black: "#1a1a1a",
                red: "#f87171",
                green: "#4ade80",
                yellow: "#facc15",
                blue: "#60a5fa",
                magenta: "#c084fc",
                cyan: "#22d3ee",
                white: "#d4d4d4",
                brightBlack: "#525252",
                brightRed: "#fca5a5",
                brightGreen: "#86efac",
                brightYellow: "#fde047",
                brightBlue: "#93c5fd",
                brightMagenta: "#d8b4fe",
                brightCyan: "#67e8f9",
                brightWhite: "#f5f5f5",
            },
        });

        const fitAddon = new FitAddon();
        terminal.loadAddon(fitAddon);
        terminal.open(containerRef.current);
        fitAddon.fit();

        terminalRef.current = terminal;
        fitAddonRef.current = fitAddon;

        // Connect WebSocket
        const ws = new WebSocket(wsUrl);
        wsRef.current = ws;

        ws.onopen = () => {
            onConnected?.();
            // Send initial size
            ws.send(
                JSON.stringify({
                    type: "resize",
                    cols: terminal.cols,
                    rows: terminal.rows,
                })
            );
        };

        ws.onmessage = (event) => {
            try {
                const msg = JSON.parse(event.data);
                if (msg.type === "output" && msg.data) {
                    const decoded = atob(msg.data);
                    terminal.write(decoded);
                } else if (msg.type === "exit") {
                    onExit?.();
                } else if (msg.type === "error") {
                    onError?.(msg.message);
                }
            } catch (e) {
                console.error("Failed to parse WebSocket message:", e);
            }
        };

        ws.onerror = () => {
            onError?.("WebSocket connection error");
        };

        ws.onclose = () => {
            onExit?.();
        };

        // Handle terminal input
        terminal.onData((data) => {
            if (ws.readyState === WebSocket.OPEN) {
                ws.send(
                    JSON.stringify({
                        type: "input",
                        data: btoa(data),
                    })
                );
            }
        });

        // Handle resize
        const resizeObserver = new ResizeObserver(() => {
            fitAddon.fit();
            if (ws.readyState === WebSocket.OPEN) {
                ws.send(
                    JSON.stringify({
                        type: "resize",
                        cols: terminal.cols,
                        rows: terminal.rows,
                    })
                );
            }
        });
        resizeObserver.observe(containerRef.current);

        // Focus terminal
        terminal.focus();

        return () => {
            resizeObserver.disconnect();
            ws.close();
            terminal.dispose();
            terminalRef.current = null;
            fitAddonRef.current = null;
            wsRef.current = null;
        };
    }, [wsUrl, onConnected, onExit, onError]);

    return (
        <div
            ref={containerRef}
            style={{
                width: "100%",
                height: "100%",
                backgroundColor: "#1a1a1a",
                borderRadius: "8px",
                overflow: "hidden",
            }}
        />
    );
}
