import { useEffect, useRef, useCallback } from "react";
import { Terminal as XTerminal } from "@xterm/xterm";
import { FitAddon } from "@xterm/addon-fit";
import { WebLinksAddon } from "@xterm/addon-web-links";
import "@xterm/xterm/css/xterm.css";
import { Command } from "@tauri-apps/plugin-shell";
import { useStore } from "@/lib/store";

export function Terminal() {
  const termRef = useRef<HTMLDivElement>(null);
  const xtermRef = useRef<XTerminal | null>(null);
  const fitAddonRef = useRef<FitAddon | null>(null);
  const { workspacePath, settings } = useStore();
  const childRef = useRef<any>(null);
  const inputBufferRef = useRef("");

  const initTerminal = useCallback(async () => {
    if (!termRef.current || xtermRef.current) return;

    const xterm = new XTerminal({
      cursorBlink: true,
      fontSize: settings.fontSize - 1,
      fontFamily: settings.fontFamily,
      theme: {
        background: "#1e1e1e",
        foreground: "#cccccc",
        cursor: "#ffffff",
        selectionBackground: "#264f78",
        black: "#000000",
        red: "#cd3131",
        green: "#0dbc79",
        yellow: "#e5e510",
        blue: "#2472c8",
        magenta: "#bc3fbc",
        cyan: "#11a8cd",
        white: "#e5e5e5",
      },
      allowProposedApi: true,
    });

    const fitAddon = new FitAddon();
    xterm.loadAddon(fitAddon);
    xterm.loadAddon(new WebLinksAddon());

    xterm.open(termRef.current);
    fitAddon.fit();

    xtermRef.current = xterm;
    fitAddonRef.current = fitAddon;

    // Try to spawn a shell using Tauri shell plugin
    try {
      const shell = detectShell();
      const cmd = Command.create("exec-sh", ["-c", shell], {
        cwd: workspacePath ?? undefined,
      });

      cmd.on("close", () => {
        xterm.writeln("\r\n[Process exited]");
      });

      cmd.stdout.on("data", (data: string) => {
        xterm.write(data);
      });

      cmd.stderr.on("data", (data: string) => {
        xterm.write(data);
      });

      const child = await cmd.spawn();
      childRef.current = child;

      xterm.onData((data: string) => {
        child.write(data);
      });
    } catch (err) {
      xterm.writeln(`Terminal: Could not spawn shell. Error: ${err}`);
      xterm.writeln("Make sure shell permissions are configured in Tauri.");
      xterm.writeln("");

      // Fallback: simple command executor
      xterm.write("$ ");
      xterm.onData((data: string) => {
        if (data === "\r") {
          const cmd = inputBufferRef.current.trim();
          inputBufferRef.current = "";
          xterm.writeln("");
          if (cmd) {
            executeCommand(xterm, cmd);
          } else {
            xterm.write("$ ");
          }
        } else if (data === "\x7f") {
          // Backspace
          if (inputBufferRef.current.length > 0) {
            inputBufferRef.current = inputBufferRef.current.slice(0, -1);
            xterm.write("\b \b");
          }
        } else if (data >= " ") {
          inputBufferRef.current += data;
          xterm.write(data);
        }
      });
    }

    // Handle resize
    const resizeObserver = new ResizeObserver(() => {
      fitAddon.fit();
    });
    resizeObserver.observe(termRef.current);

    return () => {
      resizeObserver.disconnect();
    };
  }, [workspacePath, settings.fontSize, settings.fontFamily]);

  useEffect(() => {
    initTerminal();
    return () => {
      if (childRef.current) {
        childRef.current.kill().catch(() => {});
      }
      if (xtermRef.current) {
        xtermRef.current.dispose();
        xtermRef.current = null;
      }
    };
  }, [initTerminal]);

  // Refit on visibility change
  useEffect(() => {
    if (fitAddonRef.current) {
      setTimeout(() => fitAddonRef.current?.fit(), 50);
    }
  });

  return (
    <div className="h-full w-full bg-[#1e1e1e] overflow-hidden">
      <div ref={termRef} className="h-full w-full" />
    </div>
  );
}

function detectShell(): string {
  // Check common shells
  const shell = typeof navigator !== "undefined" ? "bash" : "bash";
  return shell;
}

async function executeCommand(xterm: XTerminal, cmd: string) {
  try {
    const command = Command.create("exec-sh", ["-c", cmd]);
    const output = await command.execute();
    if (output.stdout) xterm.write(output.stdout.replace(/\n/g, "\r\n"));
    if (output.stderr) xterm.write(output.stderr.replace(/\n/g, "\r\n"));
  } catch (err) {
    xterm.writeln(`Error: ${err}`);
  }
  xterm.write("$ ");
}
