import { MESSAGE_TYPES, PORT_NAMES } from "../../shared/message-types.js";

const STREAM_KEEPALIVE_MS = 20000;

export async function getSettings() {
  return chrome.runtime.sendMessage({ type: MESSAGE_TYPES.GET_SETTINGS });
}

export async function saveSettings(payload) {
  return chrome.runtime.sendMessage({ type: MESSAGE_TYPES.SAVE_SETTINGS, payload });
}

export async function analyze(payload) {
  return chrome.runtime.sendMessage({ type: MESSAGE_TYPES.ANALYZE, payload });
}

export function analyzeStream(payload, handlers) {
  const port = chrome.runtime.connect({ name: PORT_NAMES.ANALYZE_STREAM });
  let finished = false;
  let keepaliveTimer = null;

  const cleanup = () => {
    if (finished) {
      return;
    }
    finished = true;
    if (keepaliveTimer) {
      window.clearInterval(keepaliveTimer);
      keepaliveTimer = null;
    }
    port.onMessage.removeListener(onMessage);
    port.onDisconnect.removeListener(onDisconnect);
    try {
      port.disconnect();
    } catch (error) {
      // Ignore disconnect errors from already-closed ports.
    }
  };

  const onMessage = (message) => {
    if (message?.type === MESSAGE_TYPES.ANALYZE_STREAM_DELTA) {
      handlers?.onDelta?.(message.delta || "");
      return;
    }
    if (message?.type === MESSAGE_TYPES.ANALYZE_STREAM_DONE) {
      handlers?.onDone?.(message.result || {});
      cleanup();
      return;
    }
    if (message?.type === MESSAGE_TYPES.ANALYZE_STREAM_ERROR) {
      handlers?.onError?.(message.error || "Unknown stream error");
      cleanup();
    }
  };

  const onDisconnect = () => {
    if (!finished) {
      handlers?.onError?.(chrome.runtime.lastError?.message || "流式连接已断开。");
      cleanup();
    }
  };

  port.onMessage.addListener(onMessage);
  port.onDisconnect.addListener(onDisconnect);
  port.postMessage({
    type: MESSAGE_TYPES.ANALYZE_STREAM_START,
    payload
  });
  keepaliveTimer = window.setInterval(() => {
    if (finished) {
      return;
    }
    try {
      port.postMessage({
        type: MESSAGE_TYPES.ANALYZE_STREAM_PING
      });
    } catch (error) {
      handlers?.onError?.(error instanceof Error ? error.message : String(error));
      cleanup();
    }
  }, STREAM_KEEPALIVE_MS);

  return cleanup;
}
