import type { ChatMessage } from "../types/domain";
import { firstNonEmptyString, nonEmptyString, toneClass } from "../utils";

export type AgentStatusLabelTone = ReturnType<typeof toneClass>;

export interface AgentStatusLabel {
  label: string;
  tone: AgentStatusLabelTone;
  detail?: string;
}

const FALLBACK_FAILURE_LABELS: Record<string, string> = {
  timeout: "等待超时",
  provider: "Provider 不可用",
  runner_busy: "Runner 忙碌",
  session_blocked: "Session 受阻",
  canceled: "已取消",
  runner_blocked: "Runner 受阻",
  api_error: "API 错误",
  needs_config: "需要配置",
  capability_unavailable: "能力未开放",
  security_blocked: "安全阻断",
  fallback: "仍是 fallback",
  retryable: "可重试"
};

const STATUS_LABEL: Record<string, string> = {
  source: "SOURCE",
  sent: "已发送",
  running: "处理中",
  completed: "完成",
  failed: "失败",
  blocked: "阻塞",
  timeout: "超时",
  canceled: "已取消",
  unknown: "未知"
};

export function agentStatusLabel(message: ChatMessage): AgentStatusLabel {
  const status = String(message.status ?? "");
  if (status !== "failed") {
    return { label: STATUS_LABEL[status] ?? status, tone: toneClass(status) };
  }
  const errorCode = (message.error as { code?: string } | null | undefined)?.code;
  const errorMessage = (message.error as { message?: string } | null | undefined)?.message;
  const text: string = typeof message.text === "string" ? message.text : "";
  const category = classifyFailure(errorCode ?? undefined, errorMessage ?? undefined, text);
  return {
    label: FALLBACK_FAILURE_LABELS[category] ?? STATUS_LABEL.failed,
    tone: toneClass("failed"),
    detail: errorMessage ?? text
  } as AgentStatusLabel;
}

function classifyFailure(errorCode: string | undefined, errorMessage: string | undefined, text: string): string {
  if (errorCode === "codex_stdio_canceled") return "canceled";
  if (errorCode === "thread-resume-failed") return "retryable";
  if (errorCode === "codex_app_server_unavailable") return "provider";
  if (errorCode === "runner_busy") return "runner_busy";
  if (errorCode === "runner_blocked") return "runner_blocked";
  if (errorCode === "session_blocked") return "session_blocked";
  if (errorCode === "api_error" || errorCode === "codex_app_server_error") return "api_error";
  if (errorCode === "missing_config" || errorCode === "missing_env") return "needs_config";
  if (errorCode === "capability_unavailable" || errorCode === "capability_blocked") return "capability_unavailable";
  if (errorCode === "security_blocked" || errorCode === "secret_blocked") return "security_blocked";
  if (errorCode === "client_trace_idle_timeout" || errorCode === "client_timeout" || errorCode === "proxy_timeout" || errorCode === "cloud_api_proxy_timeout") return "timeout";
  if (errorCode === "code_agent_background_failed" || errorCode === "code_agent_session_evidence_missing") return "runner_blocked";
  if (typeof text === "string" && /(timeout|超时)/iu.test(text)) return "timeout";
  if (typeof text === "string" && /(provider|fallback|read-only)/iu.test(text)) return "fallback";
  if (errorMessage && /(timeout|超时)/iu.test(errorMessage)) return "timeout";
  if (errorMessage && /(provider|fallback|read-only)/iu.test(errorMessage)) return "fallback";
  return "retryable";
}

export function agentStatusTone(message: ChatMessage): AgentStatusLabelTone {
  return toneClass(message.status ?? "");
}

export function sourceTitle(result: { updatedAt?: string }): string {
  return `Code Agent 回复 ${formatBeijingTimeShort(result.updatedAt ?? new Date().toISOString())}`;
}

export function sourceFixtureTitle(result: { updatedAt?: string }): string {
  return `Code Agent SOURCE 回复 ${formatBeijingTimeShort(result.updatedAt ?? new Date().toISOString())}`;
}

export function textFallbackTitle(result: { updatedAt?: string }): string {
  return `Code Agent 文本 fallback 回复 ${formatBeijingTimeShort(result.updatedAt ?? new Date().toISOString())}`;
}

function formatBeijingTimeShort(iso: string): string {
  try {
    return new Date(iso).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" });
  } catch {
    return iso;
  }
}

export { nonEmptyString, firstNonEmptyString };
