import type {
  AppConfig,
  GatewayStatus,
  RuntimeCloudStatus,
  RuntimeStatus,
  WorkspaceSummary
} from "@qjclaw/shared-types";

export function isTransientLocalGatewayError(message?: string): boolean {
  if (!message) {
    return false;
  }

  const normalized = message.toLowerCase();
  return normalized.includes("gateway websocket is not open")
    || normalized.includes("gateway closed during connect (1006)")
    || normalized.includes("gateway connection closed (1006)")
    || normalized.includes("gateway closed during connect (1005)")
    || normalized.includes("gateway connection closed (1005)")
    || normalized.includes("gateway closed during connect (1000)")
    || normalized.includes("gateway connection closed (1000)")
    || normalized.includes("econnrefused")
    || normalized.includes("failed to connect to ws://127.0.0.1")
    || normalized.includes("failed to connect to ws://localhost")
    || normalized.includes("gateway readiness")
    || normalized.includes("gateway became ready")
    || normalized.includes("gateway closed during readiness probe")
    || normalized.includes("gateway closed before readiness probe completed")
    || normalized.includes("gateway closed before health probe completed")
    || normalized.includes("timed out while probing reusable gateway")
    || normalized.includes("timed out while waiting for reusable gateway")
    || normalized.includes("bundled runtime exited before gateway became ready");
}

export function isGatewayPolicyViolationError(message?: string): boolean {
  if (!message) {
    return false;
  }

  const normalized = message.toLowerCase();
  return normalized.includes("gateway connection closed (1008)")
    || normalized.includes("gateway closed during connect (1008)")
    || normalized.includes("policy violation");
}

export function isBundledRuntimeNameConflictError(message?: string): boolean {
  if (!message) {
    return false;
  }

  const normalized = message.toLowerCase();
  return normalized.includes("gateway name/hostname conflict detected")
    || normalized.includes("name conflict")
    || normalized.includes("hostname conflict")
    || normalized.includes("bonjour");
}

export function toStartupErrorMessage(message: string | undefined, fallback: string): string {
  if (isTransientLocalGatewayError(message)) {
    return "本地助手暂时没有准备好，请重试。";
  }

  if (isBundledRuntimeNameConflictError(message)) {
    return "内置运行时启动失败：检测到本机已有 OpenClaw 实例导致网关名称冲突，请先退出本地 OpenClaw 后重试。";
  }

  if (isGatewayPolicyViolationError(message)) {
    return "内置运行时网关连接被拒绝，如本机正在运行 OpenClaw，请先退出后重试；否则请重启应用。";
  }

  return message ?? fallback;
}

export function shouldRetryManagedRuntimeStartup(config: AppConfig, status: RuntimeStatus): boolean {
  if (config.runtimeMode === "external-gateway" || status.processState !== "error") {
    return false;
  }

  const bundledRuntimeSelected = status.selectedMode === "bundled-runtime" || status.activeMode === "bundled-runtime";
  if (!bundledRuntimeSelected) {
    return false;
  }

  const runtimeError = status.lastError ?? status.message;
  return isTransientLocalGatewayError(runtimeError)
    || isGatewayPolicyViolationError(runtimeError)
    || isBundledRuntimeNameConflictError(runtimeError);
}

export function shouldRetryBootstrapWarmup(input: {
  config: AppConfig;
  runtimeStatus: RuntimeStatus;
  gatewayStatus: GatewayStatus | null;
  isPackaged: boolean;
}): boolean {
  if (!input.isPackaged || input.config.runtimeMode === "external-gateway") {
    return false;
  }

  const bundledRuntimeSelected = input.runtimeStatus.selectedMode === "bundled-runtime"
    || input.runtimeStatus.activeMode === "bundled-runtime";
  if (!bundledRuntimeSelected) {
    return false;
  }

  const runtimeError = input.runtimeStatus.lastError ?? input.runtimeStatus.message;
  if (input.runtimeStatus.processState === "error" && (
    isTransientLocalGatewayError(runtimeError)
    || isGatewayPolicyViolationError(runtimeError)
    || isBundledRuntimeNameConflictError(runtimeError)
  )) {
    return true;
  }

  const gatewayError = input.gatewayStatus?.lastError ?? input.gatewayStatus?.message;
  return input.gatewayStatus?.state === "error" && (
    isTransientLocalGatewayError(gatewayError)
    || isGatewayPolicyViolationError(gatewayError)
    || isBundledRuntimeNameConflictError(gatewayError)
  );
}

export function requiresShellWarmupBeforeBinding(config: AppConfig): boolean {
  return !config.apiKeyConfigured
    && config.setupMode === "employee-key"
    && config.runtimeMode !== "external-gateway";
}

export function isWorkspaceShellReady(input: {
  config: AppConfig;
  runtimeStatus: RuntimeStatus;
  gatewayStatus: GatewayStatus | null;
}): boolean {
  const {
    config,
    runtimeStatus,
    gatewayStatus
  } = input;

  if (!requiresShellWarmupBeforeBinding(config)) {
    return true;
  }

  const runtimeReady = runtimeStatus.activeMode === "external-gateway"
    || runtimeStatus.processState === "running";
  if (!runtimeReady) {
    return false;
  }

  if (gatewayStatus?.state === "connected") {
    return true;
  }

  const gatewayError = gatewayStatus?.lastError ?? gatewayStatus?.message;
  return isTransientLocalGatewayError(gatewayError);
}

function buildSetupSummary(config: AppConfig): Pick<WorkspaceSummary, "chatReady" | "chatLaunchState" | "chatStatusMessage" | "startupPhase" | "startupMessage"> {
  const setupMessage = config.setupMode === "direct-provider"
    ? "请先完成厂商 API Key 配置。"
    : "请先绑定员工密钥。";
  return {
    chatReady: false,
    chatLaunchState: "unbound",
    chatStatusMessage: setupMessage,
    startupPhase: "idle",
    startupMessage: setupMessage
  };
}

function buildRuntimeStartingSummary(runtimeStatus: RuntimeStatus): Pick<WorkspaceSummary, "chatReady" | "chatLaunchState" | "chatStatusMessage" | "startupPhase" | "startupMessage"> {
  const message = runtimeStatus.message || "正在唤起本地助手，请稍候。";
  return {
    chatReady: false,
    chatLaunchState: "starting",
    chatStatusMessage: message,
    startupPhase: "starting-runtime",
    startupMessage: message
  };
}

function buildGatewayStartingSummary(gatewayStatus: GatewayStatus | null): Pick<WorkspaceSummary, "chatReady" | "chatLaunchState" | "chatStatusMessage" | "startupPhase" | "startupMessage"> {
  const message = gatewayStatus?.message ?? "正在连接聊天服务，请稍候。";
  return {
    chatReady: false,
    chatLaunchState: "starting",
    chatStatusMessage: message,
    startupPhase: "connecting-gateway",
    startupMessage: message
  };
}

function shouldWaitForRuntimeCloudStabilization(input: {
  config: AppConfig;
  runtimeStatus: RuntimeStatus;
  runtimeCloudStatus: RuntimeCloudStatus;
  warmupInFlight: boolean;
  runtimeCloudRefreshInFlight: boolean;
  runtimeCloudConfigSyncInFlight: boolean;
  isPackaged: boolean;
}): boolean {
  const {
    config,
    runtimeStatus,
    runtimeCloudStatus,
    warmupInFlight,
    runtimeCloudRefreshInFlight,
    runtimeCloudConfigSyncInFlight,
    isPackaged
  } = input;

  if (config.setupMode !== "employee-key" || config.runtimeMode === "external-gateway") {
    return false;
  }

  if (runtimeCloudStatus.state === "loading" || runtimeCloudStatus.state === "unconfigured") {
    return true;
  }

  if (runtimeCloudRefreshInFlight || runtimeCloudConfigSyncInFlight) {
    return runtimeStatus.processState === "running";
  }

  const packagedBundledRuntime = isPackaged;
  return packagedBundledRuntime
    && warmupInFlight
    && runtimeStatus.processState === "running"
    && runtimeCloudStatus.state === "ready";
}

export function buildChatSummary(input: {
  config: AppConfig;
  runtimeStatus: RuntimeStatus;
  runtimeCloudStatus: RuntimeCloudStatus;
  gatewayStatus: GatewayStatus | null;
  warmupInFlight: boolean;
  runtimeCloudRefreshInFlight: boolean;
  runtimeCloudConfigSyncInFlight: boolean;
  isPackaged: boolean;
}): Pick<WorkspaceSummary, "chatReady" | "chatLaunchState" | "chatStatusMessage" | "startupPhase" | "startupMessage"> {
  const {
    config,
    runtimeStatus,
    runtimeCloudStatus,
    gatewayStatus,
    warmupInFlight,
    runtimeCloudRefreshInFlight,
    runtimeCloudConfigSyncInFlight,
    isPackaged
  } = input;

  const shellReady = isWorkspaceShellReady({
    config,
    runtimeStatus,
    gatewayStatus
  });
  const packagedBundledRuntime = isPackaged;
  const runtimeError = runtimeStatus.lastError ?? runtimeStatus.message;
  const gatewayError = gatewayStatus?.lastError ?? gatewayStatus?.message;

  if (!config.apiKeyConfigured && !shellReady) {
    if (
      warmupInFlight
      && packagedBundledRuntime
      && runtimeStatus.processState === "error"
      && isTransientLocalGatewayError(runtimeError)
    ) {
      return {
        chatReady: false,
        chatLaunchState: "starting",
        chatStatusMessage: "正在重新唤起本地助手，请稍候。",
        startupPhase: "starting-runtime",
        startupMessage: "正在重新唤起本地助手，请稍候。"
      };
    }

    if (
      warmupInFlight
      && packagedBundledRuntime
      && gatewayStatus?.state === "error"
      && (isTransientLocalGatewayError(gatewayError) || isGatewayPolicyViolationError(gatewayError) || isBundledRuntimeNameConflictError(gatewayError))
    ) {
      return {
        chatReady: false,
        chatLaunchState: "starting",
        chatStatusMessage: "正在重新连接聊天服务，请稍候。",
        startupPhase: "connecting-gateway",
        startupMessage: "正在重新连接聊天服务，请稍候。"
      };
    }

    if (runtimeStatus.processState === "error") {
      const runtimeErrorMessage = toStartupErrorMessage(runtimeError, "本地助手启动失败，请稍后重试。");
      return {
        chatReady: false,
        chatLaunchState: "error",
        chatStatusMessage: runtimeErrorMessage,
        startupPhase: "error",
        startupMessage: runtimeErrorMessage
      };
    }

    if (gatewayStatus?.state === "error") {
      const gatewayErrorMessage = toStartupErrorMessage(gatewayError, "聊天服务连接失败，请稍后重试。");
      return {
        chatReady: false,
        chatLaunchState: "error",
        chatStatusMessage: gatewayErrorMessage,
        startupPhase: "error",
        startupMessage: gatewayErrorMessage
      };
    }

    if (runtimeStatus.processState === "starting" || (runtimeStatus.selectedMode === "bundled-runtime" && runtimeStatus.processState !== "running")) {
      return buildRuntimeStartingSummary(runtimeStatus);
    }

    return buildGatewayStartingSummary(gatewayStatus);
  }

  if (!config.apiKeyConfigured) {
    return buildSetupSummary(config);
  }

  if (config.setupMode === "employee-key" && runtimeCloudStatus.state === "error") {
    const baseHostSuffix = runtimeCloudStatus.baseHost ? `（当前绑定环境：${runtimeCloudStatus.baseHost}）` : "";
    const runtimeCloudError = runtimeCloudStatus.lastError
      ? `${runtimeCloudStatus.lastError}${baseHostSuffix}`
      : `员工配置同步失败，请检查密钥或网络连接。${baseHostSuffix}`;
    return {
      chatReady: false,
      chatLaunchState: "error",
      chatStatusMessage: runtimeCloudError,
      startupPhase: "error",
      startupMessage: runtimeCloudError
    };
  }

  if (
    warmupInFlight
    && packagedBundledRuntime
    && runtimeStatus.processState === "error"
    && isTransientLocalGatewayError(runtimeError)
  ) {
    return {
      chatReady: false,
      chatLaunchState: "starting",
      chatStatusMessage: "正在重新唤起本地助手，请稍候。",
      startupPhase: "starting-runtime",
      startupMessage: "正在重新唤起本地助手，请稍候。"
    };
  }

  if (
    warmupInFlight
    && packagedBundledRuntime
    && gatewayStatus?.state === "error"
    && (isTransientLocalGatewayError(gatewayError) || isGatewayPolicyViolationError(gatewayError) || isBundledRuntimeNameConflictError(gatewayError))
  ) {
    return {
      chatReady: false,
      chatLaunchState: "starting",
      chatStatusMessage: "正在重新连接聊天服务，请稍候。",
      startupPhase: "connecting-gateway",
      startupMessage: "正在重新连接聊天服务，请稍候。"
    };
  }

  if (shouldWaitForRuntimeCloudStabilization({
    config,
    runtimeStatus,
    runtimeCloudStatus,
    warmupInFlight,
    runtimeCloudRefreshInFlight,
    runtimeCloudConfigSyncInFlight,
    isPackaged
  })) {
    return {
      chatReady: false,
      chatLaunchState: "starting",
      chatStatusMessage: "正在同步员工配置，请稍候。",
      startupPhase: "syncing-config",
      startupMessage: "正在同步员工配置，请稍候。"
    };
  }

  if (runtimeStatus.processState === "error") {
    const runtimeErrorMessage = toStartupErrorMessage(runtimeError, "本地助手启动失败，请稍后重试。");
    return {
      chatReady: false,
      chatLaunchState: "error",
      chatStatusMessage: runtimeErrorMessage,
      startupPhase: "error",
      startupMessage: runtimeErrorMessage
    };
  }

  if (gatewayStatus?.state === "error") {
    const gatewayErrorMessage = toStartupErrorMessage(gatewayError, "聊天服务连接失败，请稍后重试。");
    return {
      chatReady: false,
      chatLaunchState: "error",
      chatStatusMessage: gatewayErrorMessage,
      startupPhase: "error",
      startupMessage: gatewayErrorMessage
    };
  }

  const runtimeCanServeChat = runtimeStatus.activeMode === "external-gateway" || runtimeStatus.processState === "running";
  if (runtimeCanServeChat && gatewayStatus?.state === "connected") {
    return {
      chatReady: true,
      chatLaunchState: "ready",
      chatStatusMessage: "聊天服务已就绪。",
      startupPhase: "ready",
      startupMessage: "聊天服务已就绪。"
    };
  }

  if (runtimeStatus.processState === "starting" || (runtimeStatus.selectedMode === "bundled-runtime" && runtimeStatus.processState !== "running")) {
    return buildRuntimeStartingSummary(runtimeStatus);
  }

  return buildGatewayStartingSummary(gatewayStatus);
}
