const STATUS_META = {
  identified: { label: '待评估', tone: 'info' },
  accepted: { label: '已接受', tone: 'primary' },
  in_progress: { label: '执行中', tone: 'warning' },
  realized: { label: '实际待确认', tone: 'warning' },
  verified: { label: '财务已确认', tone: 'success' },
  reversed: { label: '已冲回', tone: 'danger' },
  rejected: { label: '已拒绝', tone: 'danger' },
  expired: { label: '已到期', tone: 'muted' }
}

const ACTION_META = {
  accept: { label: '接受机会', tone: 'primary', kind: 'opportunity' },
  start: { label: '开始执行', tone: 'primary', kind: 'opportunity' },
  reject: { label: '拒绝', tone: 'danger', kind: 'opportunity' },
  expire: { label: '标记到期', tone: 'danger', kind: 'opportunity' },
  record_realization: { label: '登记实际结果', tone: 'warning', kind: 'evidence_required' },
  confirm: { label: '财务确认', tone: 'primary', kind: 'realization' },
  reverse: { label: '冲回', tone: 'danger', kind: 'realization' }
}

const DIMENSION_LABELS = {
  department: '部门',
  project: '项目',
  expense_type: '费用类型',
  supplier: '供应商',
  city: '城市',
  owner: '负责人',
  source: '来源'
}

const DATA_QUALITY_LABELS = {
  pendingConfirmationCount: '待财务确认',
  businessStateOnlyCount: '仅平台业务状态',
  pendingDedupeCount: '待 canonical 去重',
  missingFxCount: '汇率证据缺失',
  missingEvidenceCount: '证据缺失',
  actualOverEstimateCount: '实际超过预计'
}

const FILTER_KEYS = [
  'departmentId',
  'projectCode',
  'expenseType',
  'supplierId',
  'city',
  'ownerId',
  'sourceType',
  'valueKind',
  'status'
]

export function createEmptyValueFilters() {
  return Object.fromEntries(FILTER_KEYS.map((key) => [key, '']))
}

export function readValueFiltersFromQuery(query = {}) {
  const result = createEmptyValueFilters()
  FILTER_KEYS.forEach((key) => {
    const value = query[`value_${snakeCase(key)}`]
    result[key] = Array.isArray(value) ? String(value[0] || '') : String(value || '')
  })
  return result
}

export function writeValueFiltersToQuery(query = {}, filters = {}) {
  const result = { ...query }
  FILTER_KEYS.forEach((key) => {
    const queryKey = `value_${snakeCase(key)}`
    const value = String(filters[key] || '').trim()
    if (value) {
      result[queryKey] = value
    } else {
      delete result[queryKey]
    }
  })
  return result
}

export function resolveRangeWindow(activeRange, customRange = {}, nowValue = new Date()) {
  const now = new Date(nowValue)
  const end = new Date(now)
  const start = new Date(now)
  start.setHours(0, 0, 0, 0)

  if (activeRange === 'custom' && customRange.start && customRange.end) {
    const customStart = new Date(`${customRange.start}T00:00:00`)
    const customEnd = new Date(`${customRange.end}T23:59:59.999`)
    return {
      start: customStart.toISOString(),
      end: customEnd.toISOString()
    }
  }
  if (activeRange === '本周') {
    const day = start.getDay() || 7
    start.setDate(start.getDate() - day + 1)
  } else if (activeRange === '本月') {
    start.setDate(1)
  } else if (activeRange === '近10日') {
    start.setDate(start.getDate() - 9)
  }

  return { start: start.toISOString(), end: end.toISOString() }
}

export function classifyCfoDashboardState({ dashboard, error, loading, now = new Date() } = {}) {
  if (loading && !dashboard) return 'loading'
  if (error?.status === 403) return 'permission'
  if (error && !dashboard) return 'error'
  if (!dashboard) return 'empty'

  const source = dashboard.source || {}
  const opportunityCount = Number(source.opportunityCount || 0)
  const realizationCount = Number(source.realizationCount || 0)
  if (source.dataStatus === 'empty' && opportunityCount === 0 && realizationCount === 0) {
    return 'empty'
  }
  if (source.dataStatus === 'partial' || ((opportunityCount || realizationCount) && !source.freshnessAt)) {
    return 'partial'
  }
  if (isDashboardStale(dashboard, now)) return 'stale'
  return 'ready'
}

export function isDashboardStale(dashboard = {}, nowValue = new Date(), thresholdHours = 24) {
  const freshness = dashboard.source?.freshnessAt
  if (!freshness) return false
  const timestamp = new Date(freshness).getTime()
  const now = new Date(nowValue).getTime()
  return Number.isFinite(timestamp) && Number.isFinite(now) && now - timestamp > thresholdHours * 3_600_000
}

export function buildValueKpis(dashboard = {}) {
  const source = dashboard.source || {}
  const cash = dashboard.kpis?.verifiedCash || {}
  const labor = dashboard.kpis?.releasableLabor || {}
  const safe = dashboard.kpis?.safeStraightThrough || {}
  const valueKindFilter = String(dashboard.filters?.valueKind || '')
  const hasLedgerRows = Number(source.opportunityCount || 0) + Number(source.realizationCount || 0) > 0
  const cashValues = Array.isArray(cash.values) ? cash.values : []
  const zeroCashLabel = resolveZeroCashLabel(dashboard)
  const cashExcluded = valueKindFilter === 'labor'
  const laborExcluded = valueKindFilter === 'cash'

  return [
    {
      key: 'verified_cash',
      label: cash.label || '财务确认净现金节省',
      displayValue: cashExcluded ? '未纳入筛选' : (cashValues.length ? formatMoneyValues(cashValues) : (hasLedgerRows ? zeroCashLabel : '暂无数据')),
      statusLabel: cashExcluded ? '筛选排除' : (cashValues.length ? '已核验' : (hasLedgerRows ? '真实零值' : '无台账数据')),
      state: cashExcluded ? 'unavailable' : (cashValues.length ? 'available' : (hasLedgerRows ? 'zero' : 'empty')),
      detail: cashExcluded
        ? '当前筛选仅查看工时价值，现金 KPI 未参与本次查询。'
        : cashValues.length
        ? `${Number(cash.confirmedRealizationCount || 0)} 笔独立财务确认`
        : (hasLedgerRows ? '当前周期尚无可计入主指标的确认结果' : '当前筛选范围暂无节省机会'),
      definition: cash.definition || ''
    },
    {
      key: 'labor',
      label: labor.label || '财务确认可释放工时价值',
      displayValue: laborExcluded ? '未纳入筛选' : '待采集',
      statusLabel: laborExcluded ? '筛选排除' : (labor.status === 'unavailable' ? '基线缺失' : '采集中'),
      state: laborExcluded ? 'unavailable' : 'baseline-missing',
      detail: laborExcluded ? '当前筛选仅查看现金节省，工时价值未参与本次查询。' : (labor.reason || '缺少经过客户确认的工时基线。'),
      requiredInputs: laborExcluded ? [] : (Array.isArray(labor.requiredInputs) ? labor.requiredInputs : [])
    },
    {
      key: 'straight_through',
      label: safe.label || '安全智能直通率',
      displayValue: '待采集',
      statusLabel: '审计样本不足',
      state: 'baseline-missing',
      detail: safe.reason || '缺少 eligibility 与事后审计结果。',
      requiredInputs: Array.isArray(safe.requiredInputs) ? safe.requiredInputs : []
    }
  ]
}

export function buildFunnelRows(dashboard = {}) {
  const stages = Array.isArray(dashboard.funnel?.stages) ? dashboard.funnel.stages : []
  const maxCount = Math.max(...stages.map((stage) => Number(stage.count || 0)), 1)
  return stages.map((stage) => ({
    ...stage,
    count: Number(stage.count || 0),
    valueLabel: formatMoneyValues(stage.values),
    width: `${Math.max((Number(stage.count || 0) / maxCount) * 100, stage.count ? 8 : 0)}%`
  }))
}

export function buildTrendSeries(dashboard = {}, currency = '') {
  const points = Array.isArray(dashboard.trend) ? dashboard.trend : []
  const currencies = [...new Set(points.map((item) => String(item.currency || '')).filter(Boolean))]
  const selectedCurrency = currencies.includes(currency) ? currency : (currencies[0] || '')
  const rows = points
    .filter((item) => !selectedCurrency || item.currency === selectedCurrency)
    .map((item) => ({
      period: item.period || '',
      currency: item.currency || '',
      verifiedNet: Number(item.verifiedNet || 0),
      actualPending: Number(item.actualPending || 0),
      reversal: Number(item.reversal || 0)
    }))
  return { currencies, selectedCurrency, rows }
}

export function buildBreakdownGroups(dashboard = {}) {
  return (Array.isArray(dashboard.breakdowns) ? dashboard.breakdowns : []).map((group) => {
    const items = Array.isArray(group.items) ? group.items : []
    const normalized = items.flatMap((item) => splitBreakdownItemByCurrency(item))
    const maxByCurrency = normalized.reduce((result, item) => {
      result[item.currency] = Math.max(result[item.currency] || 0, item.verifiedMagnitude)
      return result
    }, {})
    normalized.sort((left, right) => (
      left.currency.localeCompare(right.currency)
      || right.verifiedMagnitude - left.verifiedMagnitude
      || left.dimensionName.localeCompare(right.dimensionName, 'zh-CN')
    ))
    return {
      ...group,
      label: DIMENSION_LABELS[group.dimension] || group.dimension,
      items: normalized.map((item) => ({
        ...item,
        width: `${Math.max((item.verifiedMagnitude / Math.max(maxByCurrency[item.currency] || 0, 1)) * 100, item.verifiedMagnitude ? 6 : 0)}%`
      }))
    }
  })
}

export function buildGuardrailRows(dashboard = {}) {
  return (Array.isArray(dashboard.guardrails) ? dashboard.guardrails : []).map((item) => ({
    ...item,
    countLabel: item.count === null || item.count === undefined ? '不可用' : `${Number(item.count)} 项`,
    valueLabel: formatMoneyValues(item.values),
    rateLabel: item.rate === null || item.rate === undefined ? '' : formatPercent(item.rate),
    statusLabel: item.status === 'ok' ? '正常' : (item.status === 'attention' ? '需关注' : '待接入')
  }))
}

export function buildDataQualityRows(dashboard = {}) {
  const quality = dashboard.dataQuality || {}
  return Object.entries(DATA_QUALITY_LABELS).map(([key, label]) => {
    const available = Object.hasOwn(quality, key)
    const count = available ? Number(quality[key] || 0) : null
    return {
      key,
      label,
      count,
      displayValue: available ? String(count) : '—',
      tone: available ? (count > 0 ? 'attention' : 'ok') : 'unavailable'
    }
  })
}

export function buildOpportunityRows(payload = {}) {
  return (Array.isArray(payload.items) ? payload.items : []).map((item) => ({
    ...item,
    statusMeta: STATUS_META[item.status] || { label: item.status || '未知', tone: 'muted' },
    estimatedLabel: formatMoney(item.estimatedNet, item.reportingCurrency || item.currency),
    rangeLabel: `${formatMoney(item.estimatedLow, item.reportingCurrency || item.currency)} ~ ${formatMoney(item.estimatedHigh, item.reportingCurrency || item.currency)}`,
    dueLabel: formatDateTime(item.dueAt),
    updatedLabel: formatDateTime(item.updatedAt),
    confidenceLabel: formatPercent(item.confidence),
    ownerLabel: item.ownerName || item.ownerId || '未分配'
  }))
}

export function resolveActionMeta(action) {
  return ACTION_META[action] || { label: action || '执行动作', tone: 'primary', kind: 'opportunity' }
}

export function createRequestId(prefix = 'value') {
  if (globalThis.crypto?.randomUUID) {
    return `${prefix}-${globalThis.crypto.randomUUID()}`
  }
  return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 12)}`
}

export function formatMoneyValues(values = []) {
  const rows = Array.isArray(values) ? values : []
  if (!rows.length) return '—'
  return rows.map((item) => formatMoney(item.amount, item.currency)).join(' / ')
}

export function formatMoney(amount, currency = 'CNY') {
  const number = Number(amount || 0)
  const normalizedCurrency = String(currency || 'CNY').toUpperCase()
  try {
    return new Intl.NumberFormat('zh-CN', {
      style: 'currency',
      currency: normalizedCurrency,
      minimumFractionDigits: 0,
      maximumFractionDigits: 2
    }).format(number)
  } catch {
    return `${normalizedCurrency} ${number.toLocaleString('zh-CN', { maximumFractionDigits: 2 })}`
  }
}

export function formatPercent(value) {
  const number = Number(value)
  if (!Number.isFinite(number)) return '—'
  return `${(number * 100).toLocaleString('zh-CN', { maximumFractionDigits: 1 })}%`
}

export function formatDateTime(value) {
  if (!value) return '—'
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return String(value)
  return date.toLocaleString('zh-CN', {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    hour12: false
  })
}

function splitBreakdownItemByCurrency(item = {}) {
  const verifiedValues = Array.isArray(item.verifiedValues) ? item.verifiedValues : []
  const estimatedValues = Array.isArray(item.estimatedValues) ? item.estimatedValues : []
  const currencies = [...new Set(
    [...verifiedValues, ...estimatedValues].map((value) => String(value.currency || '')).filter(Boolean)
  )]
  const rows = currencies.length ? currencies : ['']
  return rows.map((currency) => {
    const verified = verifiedValues.find((value) => value.currency === currency)
    const estimated = estimatedValues.find((value) => value.currency === currency)
    const verifiedAmount = Number(verified?.amount || 0)
    return {
      ...item,
      rowKey: `${item.dimensionId || item.dimensionName}:${currency || 'no-currency'}`,
      currency,
      verifiedLabel: currency ? formatMoney(verifiedAmount, currency) : '—',
      estimatedLabel: currency ? formatMoney(estimated?.amount || 0, currency) : '—',
      verifiedMagnitude: Math.abs(verifiedAmount)
    }
  })
}

function resolveZeroCashLabel(dashboard = {}) {
  const currencies = new Set()
  const stages = Array.isArray(dashboard.funnel?.stages) ? dashboard.funnel.stages : []
  stages.forEach((stage) => {
    const values = Array.isArray(stage.values) ? stage.values : []
    values.forEach((item) => {
      if (item.currency) currencies.add(String(item.currency))
    })
  })
  if (!currencies.size) return '0（无确认币种）'
  return [...currencies].map((currency) => formatMoney(0, currency)).join(' / ')
}

function snakeCase(value) {
  return String(value || '').replace(/[A-Z]/gu, (letter) => `_${letter.toLowerCase()}`)
}
