const KNOWLEDGE_JOB_TYPES = new Set([
  'knowledge_index_sync',
  'llm_wiki_sync',
  'llm_wiki_rule_formation',
  'finance_policy_knowledge_organize'
])

const STATUS_LABELS = {
  running: '运行中',
  succeeded: '已完成',
  failed: '失败',
  blocked: '待确认'
}

const STATUS_TONES = {
  running: 'warning',
  succeeded: 'success',
  failed: 'danger',
  blocked: 'muted'
}

const PHASE_LABELS = {
  queued: '排队中',
  indexing: '归纳中',
  completed: '已完成',
  failed: '失败',
  stale_failed: '超时失败'
}

export const AGENT_RUN_POLL_INTERVAL_MS = 5000
export const AGENT_RUN_HEARTBEAT_DELAY_MS = 60 * 1000
export const AGENT_RUN_HEARTBEAT_STUCK_MS = 5 * 60 * 1000

function toDate(value) {
  if (!value) {
    return null
  }

  const date = new Date(value)
  return Number.isNaN(date.getTime()) ? null : date
}

function resolveNowMs(now = Date.now()) {
  if (now instanceof Date) {
    return now.getTime()
  }

  const numeric = Number(now)
  return Number.isFinite(numeric) ? numeric : Date.now()
}

export function isKnowledgeIndexRun(run) {
  const jobType = String(run?.route_json?.job_type || '').trim()
  return KNOWLEDGE_JOB_TYPES.has(jobType)
}

export function getAgentRunPhase(run) {
  return String(run?.route_json?.phase || '').trim()
}

export function formatDurationShort(valueMs) {
  const numeric = Number(valueMs)
  if (!Number.isFinite(numeric) || numeric < 0) {
    return '—'
  }

  const totalSeconds = Math.max(0, Math.round(numeric / 1000))
  const hours = Math.floor(totalSeconds / 3600)
  const minutes = Math.floor((totalSeconds % 3600) / 60)
  const seconds = totalSeconds % 60

  if (hours > 0) {
    return `${hours}小时${minutes}分`
  }
  if (minutes > 0) {
    return seconds > 0 ? `${minutes}分${seconds}秒` : `${minutes}分`
  }
  return `${seconds}秒`
}

export function formatAgentRunElapsed(run, now = Date.now()) {
  const startedAt = toDate(run?.started_at)
  if (startedAt === null) {
    return '—'
  }

  const finishedAt = toDate(run?.finished_at)
  const endMs = finishedAt ? finishedAt.getTime() : resolveNowMs(now)
  return formatDurationShort(endMs - startedAt.getTime())
}

export function resolveAgentRunPhaseLabel(run) {
  const phase = getAgentRunPhase(run)
  return PHASE_LABELS[phase] || STATUS_LABELS[String(run?.status || '').trim()] || '未知'
}

export function resolveAgentRunHeartbeat(run, now = Date.now()) {
  const heartbeatAt = toDate(run?.route_json?.heartbeat_at)
  const startedAt = toDate(run?.started_at)
  const nowMs = resolveNowMs(now)
  const phase = getAgentRunPhase(run)
  const isRunning = String(run?.status || '').trim() === 'running'
  const heartbeatAgeMs = heartbeatAt ? Math.max(0, nowMs - heartbeatAt.getTime()) : null
  const startedAgeMs = startedAt ? Math.max(0, nowMs - startedAt.getTime()) : null

  if (heartbeatAt) {
    if (heartbeatAgeMs >= AGENT_RUN_HEARTBEAT_STUCK_MS) {
      return {
        at: heartbeatAt,
        ageMs: heartbeatAgeMs,
        text: `${formatDurationShort(heartbeatAgeMs)}前`,
        label: '疑似中断',
        tone: 'danger'
      }
    }
    if (heartbeatAgeMs >= AGENT_RUN_HEARTBEAT_DELAY_MS) {
      return {
        at: heartbeatAt,
        ageMs: heartbeatAgeMs,
        text: `${formatDurationShort(heartbeatAgeMs)}前`,
        label: '心跳延迟',
        tone: 'warning'
      }
    }
    return {
      at: heartbeatAt,
      ageMs: heartbeatAgeMs,
      text: `${formatDurationShort(heartbeatAgeMs)}前`,
      label: '心跳正常',
      tone: 'success'
    }
  }

  if (!isKnowledgeIndexRun(run) || !isRunning) {
    return {
      at: null,
      ageMs: null,
      text: '—',
      label: '无心跳',
      tone: 'muted'
    }
  }

  if (phase === 'queued') {
    return {
      at: null,
      ageMs: startedAgeMs,
      text: '尚未开始',
      label: '等待执行',
      tone: 'muted'
    }
  }

  if ((startedAgeMs || 0) >= AGENT_RUN_HEARTBEAT_DELAY_MS) {
    return {
      at: null,
      ageMs: startedAgeMs,
      text: '尚未收到',
      label: '无心跳',
      tone: 'warning'
    }
  }

  return {
    at: null,
    ageMs: startedAgeMs,
    text: '等待首个心跳',
    label: '等待心跳',
    tone: 'muted'
  }
}

export function resolveAgentRunStatus(run, now = Date.now()) {
  const status = String(run?.status || '').trim()
  const phase = getAgentRunPhase(run)
  const heartbeat = resolveAgentRunHeartbeat(run, now)
  let label = STATUS_LABELS[status] || status || '未知'
  let tone = STATUS_TONES[status] || 'muted'
  let note = ''
  let isSuspicious = false

  if (status === 'failed' && phase === 'stale_failed') {
    return {
      label: '已超时',
      tone: 'danger',
      note: '系统已按长时间无心跳自动判定失败',
      phase,
      phaseLabel: resolveAgentRunPhaseLabel(run),
      heartbeat,
      isSuspicious: true
    }
  }

  if (status === 'running' && isKnowledgeIndexRun(run)) {
    if (phase === 'queued') {
      label = '排队中'
      tone = 'muted'
      note = '等待后台线程接管'
    } else if (phase === 'indexing') {
      if (heartbeat.at === null && heartbeat.label === '无心跳') {
        label = '无心跳'
        tone = 'warning'
        note = '已进入归纳流程，但还没有收到心跳'
        isSuspicious = true
      } else if (heartbeat.tone === 'danger') {
        label = '疑似卡住'
        tone = 'danger'
        note = `最后心跳在 ${heartbeat.text}`
        isSuspicious = true
      } else if (heartbeat.tone === 'warning') {
        label = '心跳延迟'
        tone = 'warning'
        note = `最后心跳在 ${heartbeat.text}`
        isSuspicious = true
      } else if (heartbeat.at === null) {
        label = '归纳启动中'
        tone = 'warning'
        note = '任务已启动，等待首个心跳'
      } else {
        label = '归纳中'
        tone = 'warning'
        note = `最后心跳在 ${heartbeat.text}`
      }
    }
  }

  if (!note && status === 'failed' && run?.error_message) {
    note = String(run.error_message).trim()
  }

  return {
    label,
    tone,
    note,
    phase,
    phaseLabel: resolveAgentRunPhaseLabel(run),
    heartbeat,
    isSuspicious
  }
}

export function formatAgentRunProgress(run) {
  const progress = run?.route_json?.progress || {}
  const percent = Number(progress.percent || 0)
  const completed = Number(progress.completed_documents || 0)
  const total = Number(progress.total_documents || 0)
  const failed = Number(progress.failed_documents || 0)
  const stage = String(progress.current_stage || '').trim()
  const stageLabelMap = {
    document_started: '文档启动',
    text_extracted: '文本已提取',
    candidate_chunks_selected: '已筛正文',
    extracting_candidates: '候选提炼中',
    candidate_extraction_completed: '候选提炼完成',
    document_completed: '文档完成',
    skipped: '跳过'
  }
  const stageLabel = stageLabelMap[stage] || stage

  if (total > 0) {
    const parts = [`${percent}%`, `${completed}/${total} 文档`]
    if (failed > 0) {
      parts.push(`失败 ${failed}`)
    }
    if (stageLabel) {
      parts.push(stageLabel)
    }
    return parts.join(' · ')
  }

  if (stageLabel) {
    return `${percent}% · ${stageLabel}`
  }

  return `${percent}%`
}
