"use client";
/* eslint-disable @typescript-eslint/no-explicit-any */

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

interface TerminalConsoleProps {
  sessionId: string;
  height?: string | number;
}

export default function TerminalConsole({ sessionId, height = "400px" }: TerminalConsoleProps) {
  const terminalRef = useRef<HTMLDivElement>(null);
  const xtermRef = useRef<Terminal | null>(null);
  const wsRef = useRef<WebSocket | null>(null);

  useEffect(() => {
    if (!terminalRef.current) return;

    let isDisposed = false;

    // Initialize xterm
    const term = new Terminal({
      cursorBlink: true,
      fontFamily: "var(--font-mono), monospace",
      fontSize: 13,
      lineHeight: 1.4,
      scrollback: 5000,
      theme: {
        background: "#05070a",
        foreground: "#c9d1d9",
        cursor: "#a855f7", // Purple matching primary theme
        black: "#000000",
        red: "#ff5555",
        green: "#50fa7b",
        yellow: "#f1fa8c",
        blue: "#bd93f9",
        magenta: "#ff79c6",
        cyan: "#8be9fd",
        white: "#ffffff",
      },
    });

    const fitAddon = new FitAddon();
    term.loadAddon(fitAddon);

    term.open(terminalRef.current);

    // Monkeypatch to prevent crash during unmount / disposal
    try {
      const core = (term as any)._core;
      if (core) {
        // 1. Patch viewport._innerRefresh
        const viewports = [
          core.viewport,
          core._viewport,
          (term as any).viewport,
          (term as any)._viewport
        ].filter(Boolean);

        for (const vp of viewports) {
          const originalInnerRefresh = vp._innerRefresh;
          if (originalInnerRefresh && !vp._innerRefresh.__patched) {
            const patchedFn = function(this: any, ...args: any[]) {
              try {
                return originalInnerRefresh.apply(this, args);
              } catch (err) {
                console.warn("Suppressed xterm viewport refresh error during unmount:", err);
              }
            };
            (patchedFn as any).__patched = true;
            vp._innerRefresh = patchedFn;
          }
        }

        // 2. Patch renderService.dimensions getter
        const renderServices = [
          core._renderService,
          core.renderService,
          (term as any)._renderService,
          (term as any).renderService
        ].filter(Boolean);

        for (const rs of renderServices) {
          if (rs && !rs.__dimensionsPatched) {
            rs.__dimensionsPatched = true;
            Object.defineProperty(rs, 'dimensions', {
              get() {
                try {
                  if (this._renderer && this._renderer.value) {
                    return this._renderer.value.dimensions;
                  }
                } catch {
                  // Ignore
                }
                // Return a safe dummy fallback object
                return {
                  device: {
                    cell: { width: 0, height: 0 },
                    canvas: { width: 0, height: 0 }
                  },
                  css: {
                    cell: { width: 0, height: 0 },
                    canvas: { width: 0, height: 0 }
                  }
                };
              },
              configurable: true
            });
          }
        }
      }
    } catch (e) {
      console.warn("Failed to apply xterm monkeypatch:", e);
    }
    
    // Fit the terminal to dimensions safely
    const fitTimeout = setTimeout(() => {
      if (isDisposed) return;
      try {
        if (terminalRef.current && terminalRef.current.clientWidth > 0 && terminalRef.current.clientHeight > 0) {
          fitAddon.fit();
        }
      } catch (e) {
        console.warn("Failed to fit terminal on mount", e);
      }
    }, 100);

    xtermRef.current = term;

    // Connect WebSocket client to gateway server on port 3001
    const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
    const wsUrl = `${protocol}//${window.location.hostname}:3001`;
    const ws = new WebSocket(wsUrl);
    wsRef.current = ws;

    ws.onopen = () => {
      if (isDisposed) return;
      term.write("\r\n\x1b[1;36m[System] Console bridge connected to gateway WebSocket...\x1b[0m\r\n");
      // Trigger session binding handshake
      ws.send(JSON.stringify({ type: "handshake", sessionId }));
    };

    ws.onmessage = (event) => {
      if (isDisposed) return;
      try {
        const msg = JSON.parse(event.data);
        if (msg.type === "handshake-ack") {
          term.clear();
          if (msg.history) {
            term.write(msg.history);
          }
        } else if (msg.type === "output") {
          term.write(msg.data);
        } else if (msg.type === "error") {
          term.write(`\r\n\x1b[1;31m[System Error] ${msg.message}\x1b[0m\r\n`);
        }
      } catch {
        // Fallback for raw stream chunks
        term.write(event.data);
      }
    };

    // User typing interaction: capture data and stream to WebSocket
    term.onData((data) => {
      if (isDisposed) return;
      if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({ type: "input", data }));
      }
    });

    // Resize listener using ResizeObserver
    const resizeObserver = new ResizeObserver(() => {
      if (isDisposed) return;
      try {
        if (
          terminalRef.current && 
          terminalRef.current.isConnected && 
          terminalRef.current.clientWidth > 0 && 
          terminalRef.current.clientHeight > 0
        ) {
          fitAddon.fit();
        }
      } catch {
        // Suppress layout errors
      }
    });
    resizeObserver.observe(terminalRef.current);

    return () => {
      isDisposed = true;
      clearTimeout(fitTimeout);
      resizeObserver.disconnect();
      ws.close();
      try {
        fitAddon.dispose();
        term.dispose();
      } catch (e) {
        console.warn("Error disposing terminal:", e);
      }
    };
  }, [sessionId]);

  return (
    <div 
      style={{ 
        width: "100%", 
        height: height, 
        backgroundColor: "#05070a", 
        border: "1px solid var(--border)",
        borderBottomLeftRadius: "12px",
        borderBottomRightRadius: "12px",
        overflow: "hidden"
      }}
    >
      <div 
        ref={terminalRef} 
        style={{ 
          width: "100%", 
          height: "100%",
          padding: "1rem"
        }} 
      />
    </div>
  );
}
