import type { ConversationTraceItem, TraceTone } from "./useMessageTraces"

export type TraceStepKind = "setup" | "routing" | "tool" | "writing" | "complete" | "error"

export interface TraceDisplayLine {
  key: string
  time: string
  title: string
  detail?: string
  tone: TraceTone
  kind: TraceStepKind
}

const TRACE_TITLE_MAX_LENGTH = 34

export function formatTraceTime(value: string): string {
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) {
    return value
  }

  return date.toLocaleTimeString("zh-CN", { hour12: false })
}

function compactText(value: string | undefined): string | undefined {
  const text = value?.replace(/\s+/g, " ").trim()
  return text || undefined
}

function limitTraceTitle(value: string): string {
  if (value.length <= TRACE_TITLE_MAX_LENGTH) {
    return value
  }

  return `${value.slice(0, TRACE_TITLE_MAX_LENGTH - 1)}...`
}

function getTraceTitleCandidate(item: ConversationTraceItem): string | undefined {
  if (item.tone === "error") {
    return compactText(item.label)
  }

  return compactText(item.detail) ?? compactText(item.label)
}

export function getTraceStripTitle(
  items: ConversationTraceItem[],
  fallbackTitle: string,
  statusLabel?: string,
  statusDetail?: string
): string {
  const latestTraceTitle = items.length ? getTraceTitleCandidate(items[items.length - 1]) : undefined
  const title = latestTraceTitle ?? compactText(statusDetail) ?? compactText(statusLabel) ?? compactText(fallbackTitle)
  return title ? limitTraceTitle(title) : fallbackTitle
}

function classifyTraceItem(item: ConversationTraceItem): TraceStepKind {
  const stage = item.stage.toLowerCase()
  const value = `${item.stage} ${item.label}`.toLowerCase()
  if (item.tone === "error" || value.includes("error") || value.includes("failed") || value.includes("失败")) {
    return "error"
  }
  if (item.tone === "success" || value.includes("completed") || value.includes("ready") || value.includes("完成")) {
    return "complete"
  }
  if (stage.includes("route") || stage.includes("fallback")) {
    return "routing"
  }
  if (stage.includes("prepare") || stage.includes("request") || stage.includes("await")) {
    return "setup"
  }
  if (stage.includes("workspace") || stage.includes("runtime") || stage.includes("tool")) {
    return "tool"
  }
  if (value.includes("route") || value.includes("skill") || value.includes("fallback") || value.includes("项目") || value.includes("专家")) {
    return "routing"
  }
  if (value.includes("tool") || value.includes("workspace") || value.includes("runtime") || value.includes("local") || value.includes("本地")) {
    return "tool"
  }
  if (value.includes("started") || value.includes("model") || value.includes("reply") || value.includes("answer") || value.includes("回答")) {
    return "writing"
  }
  return "setup"
}

function getTraceStepTitle(item: ConversationTraceItem, kind: TraceStepKind): string {
  if (kind === "error") {
    return "遇到错误"
  }
  if (kind === "complete") {
    return "回答完成"
  }
  if (kind === "routing") {
    return "选择合适的处理方式"
  }
  if (kind === "tool") {
    return "准备执行环境"
  }
  if (kind === "writing") {
    return "整理回答内容"
  }
  if (item.stage === "request") {
    return "理解问题"
  }
  return "准备上下文"
}

function getTraceStepDetail(item: ConversationTraceItem, kind: TraceStepKind): string | undefined {
  const label = compactText(item.label)
  const detail = compactText(item.detail)
  if (kind === "error") {
    return detail ?? label
  }
  if (detail) {
    return detail
  }
  if (!label || label === getTraceStepTitle(item, kind)) {
    return undefined
  }
  return label
}

export function getTraceLineClassName(tone: TraceTone, kind?: TraceStepKind): string {
  return ["message-trace-line", tone, kind ? `trace-kind-${kind}` : ""].filter(Boolean).join(" ")
}

export function getTraceDisplayLines(items: ConversationTraceItem[]): TraceDisplayLine[] {
  const lines: TraceDisplayLine[] = []

  for (const item of items) {
    const kind = classifyTraceItem(item)
    const title = getTraceStepTitle(item, kind)
    const detail = getTraceStepDetail(item, kind)
    const previous = lines.at(-1)

    if (previous && previous.title === title && previous.detail === detail && previous.tone === item.tone && previous.kind === kind) {
      continue
    }

    lines.push({
      key: item.id,
      time: formatTraceTime(item.createdAt),
      title,
      detail,
      tone: item.tone,
      kind
    })
  }

  return lines
}
