import { computed, markRaw, nextTick, reactive, ref, watch } from "vue";
import { Terminal } from "@xterm/xterm";
import { FitAddon } from "@xterm/addon-fit";
import { getToken } from "../api";
import { useUI } from "./useUI";

const sessions = ref([]);
const activeId = ref("");
const terminalRefs = new Map();

const form = reactive({
  host: "",
  port: 22,
  username: "",
  authType: "password",
  password: "",
  privateKey: "",
  passphrase: "",
});
const formError = ref("");

const wsUrl = computed(() => {
  const token = getToken();
  const envUrl = import.meta.env.VITE_WS_URL;
  if (envUrl) return token ? `${envUrl}?token=${token}` : envUrl;
  if (typeof window === "undefined") {
    const base = "ws://localhost:8080/api/ws/ssh";
    return token ? `${base}?token=${token}` : base;
  }
  const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
  const base = `${protocol}//${window.location.host}/api/ws/ssh`;
  return token ? `${base}?token=${token}` : base;
});

function setTerminalRef(id, el) {
  if (el) terminalRefs.set(id, el);
  else terminalRefs.delete(id);
}

function statusLabel(status) {
  const map = {
    ready: "已连接",
    connecting: "连接中",
    connected: "已建立",
    closing: "关闭中",
    closed: "已关闭",
    error: "错误",
  };
  return map[status] ?? "准备中";
}

function resetForm() {
  Object.assign(form, {
    host: "", port: 22, username: "", authType: "password",
    password: "", privateKey: "", passphrase: "",
  });
  formError.value = "";
}

function connectWithSSH(item) {
  form.host = item.host || "";
  form.port = item.port || 22;
  form.username = item.username || "";
  if (item.privateKey) {
    form.authType = "key";
    form.privateKey = item.privateKey;
    form.passphrase = item.passphrase || "";
    form.password = "";
  } else {
    form.authType = "password";
    form.password = item.password || "";
    form.privateKey = "";
    form.passphrase = "";
  }
  createSession();
}

function createSession() {
  const { closeOverlay } = useUI();
  formError.value = "";
  if (!form.host || !form.username) { formError.value = "请填写主机与用户名。"; return; }
  if (form.authType === "password" && !form.password) { formError.value = "请选择密码认证时请输入密码。"; return; }
  if (form.authType === "key" && !form.privateKey) { formError.value = "请选择私钥认证时请输入私钥。"; return; }

  const id = crypto.randomUUID();
  const session = {
    id,
    title: `${form.username}@${form.host}:${form.port}`,
    status: "connecting",
    ws: null,
    term: null,
    fit: null,
  };
  sessions.value.push(session);
  activeId.value = id;

  const payload = {
    type: "connect",
    host: form.host, port: form.port, username: form.username,
    password: form.authType === "password" ? form.password : "",
    privateKey: form.authType === "key" ? form.privateKey : "",
    passphrase: form.authType === "key" ? form.passphrase : "",
  };
  nextTick(() => initSession(session, payload));
  closeOverlay();
}

function initSession(session, payload) {
  const container = terminalRefs.get(session.id);
  if (!container) return;

  const term = markRaw(
    new Terminal({
      fontFamily: `"JetBrains Mono", "Fira Code", ui-monospace, monospace`,
      fontSize: 14,
      lineHeight: 1.35,
      cursorBlink: true,
      cursorStyle: "block",
      scrollback: 8000,
      smoothScrollDuration: 100,
      theme: {
        background: "#000000",
        foreground: "#e6edf3",
        cursor: "#3fb950",
        cursorAccent: "#000000",
        selectionBackground: "rgba(63,185,80,0.25)",
        black: "#0d1117",   red: "#f85149",   green: "#3fb950",  yellow: "#d29922",
        blue: "#58a6ff",    magenta: "#bc8cff", cyan: "#39c5cf", white: "#b1bac4",
        brightBlack: "#484f58", brightRed: "#ff7b72", brightGreen: "#56d364",
        brightYellow: "#e3b341", brightBlue: "#79c0ff", brightMagenta: "#d2a8ff",
        brightCyan: "#56d4dd", brightWhite: "#cdd9e5",
      },
    })
  );

  const fitAddon = markRaw(new FitAddon());
  term.loadAddon(fitAddon);
  term.open(container);
  fitAddon.fit();
  term.focus();
  term.writeln("\x1b[90m[正在建立连接...]\x1b[0m");

  const ws = markRaw(new WebSocket(wsUrl.value));
  session.ws = ws;
  session.term = term;
  session.fit = fitAddon;

  const sendResize = () => {
    if (ws.readyState !== WebSocket.OPEN) return;
    ws.send(JSON.stringify({ type: "resize", cols: term.cols, rows: term.rows }));
  };

  ws.onopen = () => {
    session.status = "connected";
    ws.send(JSON.stringify({ ...payload, cols: term.cols, rows: term.rows }));
  };
  ws.onmessage = (event) => {
    let msg;
    try { msg = JSON.parse(event.data); } catch { term.write(event.data); return; }
    if (msg.type === "output" && msg.data) term.write(msg.data);
    else if (msg.type === "status") {
      session.status = msg.status || session.status;
      if (msg.message) term.writeln(`\r\x1b[90m[${msg.message}]\x1b[0m`);
    } else if (msg.type === "error") {
      session.status = "error";
      if (msg.message) term.writeln(`\r\x1b[31m[${msg.message}]\x1b[0m`);
    }
  };
  ws.onerror = () => { session.status = "error"; term.writeln("\r\n\x1b[31m[连接错误]\x1b[0m"); };
  ws.onclose = () => {
    if (session.status !== "closed") session.status = "closed";
    term.writeln("\r\n\x1b[90m[连接已关闭]\x1b[0m");
  };
  term.onData((data) => {
    if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: "input", data }));
  });
  term.onResize(() => sendResize());
  focusSession(session);
}

function focusSession(session) {
  if (!session?.term || !session?.fit) return;
  nextTick(() => {
    session.fit.fit();
    if (session.ws?.readyState === WebSocket.OPEN) {
      session.ws.send(JSON.stringify({ type: "resize", cols: session.term.cols, rows: session.term.rows }));
    }
    session.term.scrollToBottom();
    session.term.focus();
  });
}

function setActive(id) { activeId.value = id; }

function closeSession(id) {
  const index = sessions.value.findIndex((s) => s.id === id);
  if (index === -1) return;
  const session = sessions.value[index];
  if (session.ws?.readyState === WebSocket.OPEN) {
    session.ws.send(JSON.stringify({ type: "close" }));
    session.ws.close();
  }
  session.term?.dispose();
  sessions.value.splice(index, 1);
  if (activeId.value === id) activeId.value = sessions.value[0]?.id || "";
}

function handleWindowResize() {
  const session = sessions.value.find((s) => s.id === activeId.value);
  if (session) focusSession(session);
}

watch(activeId, (id) => {
  const session = sessions.value.find((s) => s.id === id);
  if (session) focusSession(session);
});

export function useSessions() {
  return {
    sessions, activeId, terminalRefs, form, formError, wsUrl,
    setTerminalRef, statusLabel, resetForm,
    connectWithSSH, createSession, initSession, focusSession,
    setActive, closeSession, handleWindowResize,
  };
}
