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

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

// Mirrors project.json roles.skillIds mapping — keep in sync when roles change.
interface SkillRoleEntry {
  name: string
  icon: string
  roleId: string
}

const SKILL_ROLE_MAP: Record<string, SkillRoleEntry> = {
  "xhs-strategist":   { name: "策划专家", icon: "lightbulb", roleId: "strategist" },
  "xhs-copywriter":   { name: "文案专家", icon: "pen", roleId: "copywriter" },
  "xhs-create-note":  { name: "文案专家", icon: "pen", roleId: "copywriter" },
  "xhs-pipeline":     { name: "文案专家", icon: "pen", roleId: "copywriter" },
  "xhs-publish-note": { name: "文案专家", icon: "pen", roleId: "copywriter" },
  "xhs-kol":          { name: "达人投放", icon: "users", roleId: "kol" },
  "xhs-community":    { name: "社区运营", icon: "chat", roleId: "community" },
  "xhs-analytics":    { name: "数据分析", icon: "chart", roleId: "analytics" },
  "xhs-research":     { name: "策划专家", icon: "lightbulb", roleId: "strategist" },
  "geo-diagnostician":   { name: "诊断师", icon: "search", roleId: "diagnostician" },
  "geo-strategist":      { name: "策略师", icon: "lightbulb", roleId: "strategist" },
  "geo-content-creator": { name: "内容师", icon: "pen", roleId: "content-creator" },
  "geo-tech-advisor":    { name: "技术顾问", icon: "settings", roleId: "tech-advisor" },
}

export function resolveRoleFromSkill(value: string): SkillRoleEntry | undefined {
  const lower = value.toLowerCase()
  for (const [skillId, role] of Object.entries(SKILL_ROLE_MAP)) {
    const sid = skillId.toLowerCase()
    const idx = lower.indexOf(sid)
    if (idx === -1) continue
    // Match skillId as a complete token — bounded by string edges, whitespace, or hyphens
    const beforeOk = idx === 0 || /[\s-]/.test(lower[idx - 1])
    const afterOk = idx + sid.length === lower.length || /[\s-]/.test(lower[idx + sid.length])
    if (beforeOk && afterOk) return role
  }
  return undefined
}

export interface ActiveRoleInfo {
  name: string
  icon: string
  roleId: string
  label: string
  detail?: string
}

export function getActiveRoleFromTraces(
  items: ConversationTraceItem[]
): ActiveRoleInfo | undefined {
  for (let i = items.length - 1; i >= 0; i--) {
    const role = resolveRoleFromSkill(items[i].stage)
    if (role) {
      return { ...role, label: items[i].label, detail: items[i].detail }
    }
  }
  return undefined
}

export function getActiveRoleIdFromMessages(
  messages: Array<{ role: string; id: string }>,
  traces: Record<string, { items: ConversationTraceItem[] }>
): string | undefined {
  for (let i = messages.length - 1; i >= 0; i--) {
    const message = messages[i]
    if (message.role !== "assistant") continue
    const trace = traces[message.id]
    if (!trace?.items?.length) continue
    const active = getActiveRoleFromTraces(trace.items)
    if (active) return active.roleId
  }
  return undefined
}

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

export function getLatestTraceLabel(items: ConversationTraceItem[]): string | undefined {
  const latest = items.at(-1)?.label?.replace(/\s+/g, " ").trim()
  return latest || undefined
}

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"
  }
  // Recognize skill stages (e.g. "geo-diagnostician", "xhs-strategist") as tool kind
  if (resolveRoleFromSkill(stage)) {
    return "tool"
  }
  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 getTraceStepDisplay(item: ConversationTraceItem, kind: TraceStepKind): { title: string; icon?: string } {
  if (kind === "error") {
    return { title: "遇到错误" }
  }
  if (kind === "complete") {
    return { title: "回答完成" }
  }
  if (kind === "routing") {
    return { title: "选择合适的处理方式" }
  }
  if (kind === "tool") {
    const role = resolveRoleFromSkill(`${item.stage} ${item.label}`)
    if (role) {
      return { title: `${role.name}正在工作`, icon: role.icon }
    }
    return { title: "准备执行环境" }
  }
  if (kind === "writing") {
    return { title: "整理回答内容" }
  }
  if (item.stage === "request") {
    return { title: "理解问题" }
  }
  return { title: "准备上下文" }
}

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 === getTraceStepDisplay(item, kind).title) {
    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 getTraceLineLabels(item: ConversationTraceItem): {
  time: string
  label: string
  detail?: string
} {
  return {
    time: formatTraceTime(item.createdAt),
    label: item.label,
    detail: item.detail
  }
}

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

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

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

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

  return lines
}
