import { countClaimRisks, resolveArchiveRiskTone } from './archiveCenterListFilters.js'
import { isNewDocument } from './documentCenterNewState.js'
import { isArchivedDocumentRow } from './documentCenterRows.js'
import { sortDocumentRowsByLatestTime } from './documentCenterSort.js'
import {
  DOCUMENT_TYPE_ALL,
  DOCUMENT_TYPE_APPLICATION,
  DOCUMENT_TYPE_REIMBURSEMENT,
  resolveDocumentTypeLabel
} from '../constants/documentProtocol.js'
import {
  extractDateText,
  formatDocumentListTime,
  resolveDocumentSortTime,
  resolveDocumentStayTimeDisplay
} from './documentCenterTime.js'
import { normalizeRequestForUi } from './requestViewModel.js'

export {
  DOCUMENT_TYPE_ALL,
  DOCUMENT_TYPE_APPLICATION,
  DOCUMENT_TYPE_REIMBURSEMENT
}
export const SCENE_ALL = 'all'
export const DOCUMENT_SCOPE_ALL = '全部'
export const DOCUMENT_SCOPE_APPLICATION = '申请单'
export const DOCUMENT_SCOPE_REIMBURSEMENT = '报销单'
export const DOCUMENT_SCOPE_REVIEW = '审核单'
export const DOCUMENT_SCOPE_ARCHIVE = '归档'
export const scopeTabs = [
  DOCUMENT_SCOPE_ALL,
  DOCUMENT_SCOPE_APPLICATION,
  DOCUMENT_SCOPE_REIMBURSEMENT,
  DOCUMENT_SCOPE_REVIEW,
  DOCUMENT_SCOPE_ARCHIVE
]
export const DOCUMENT_LOADING_MIN_VISIBLE_MS = 720
export const DOCUMENT_CENTER_QUERY_KEYS = new Set([
  'dc_page',
  'dc_page_size',
  'dc_scope',
  'dc_status',
  'dc_doc_type',
  'dc_scene',
  'dc_q',
  'dc_start',
  'dc_end',
  'dc_review_page',
  'dc_review_page_size',
  'dc_review_q',
  'dc_review_risk',
  'dc_review_sla'
])
export const riskLevelTabs = ['全部', '高风险', '中风险', '低风险', '无风险']
export const RISK_TONE_META = {
  high: { label: '高风险', tone: 'high' },
  medium: { label: '中风险', tone: 'medium' },
  low: { label: '低风险', tone: 'low' },
  none: { label: '无风险', tone: 'none' }
}
export const FILTER_CONFIG_BY_SCOPE = {
  [DOCUMENT_SCOPE_ALL]: {
    searchPlaceholder: '搜索单号、事项、费用场景...',
    sceneFallbackLabel: '单据场景',
    dateLabel: '单据时间',
    statusTitle: '风险等级',
    statusTabs: riskLevelTabs,
    showDocumentType: true
  },
  [DOCUMENT_SCOPE_APPLICATION]: {
    searchPlaceholder: '搜索申请单号、申请事项、申请场景...',
    sceneFallbackLabel: '申请场景',
    dateLabel: '申请时间',
    statusTitle: '风险等级',
    statusTabs: riskLevelTabs,
    showDocumentType: false
  },
  [DOCUMENT_SCOPE_REIMBURSEMENT]: {
    searchPlaceholder: '搜索报销单号、报销事由、费用场景...',
    sceneFallbackLabel: '费用场景',
    dateLabel: '报销时间',
    statusTitle: '风险等级',
    statusTabs: riskLevelTabs,
    showDocumentType: false
  },
  [DOCUMENT_SCOPE_REVIEW]: {
    searchPlaceholder: '搜索审核单号、事项、当前环节...',
    sceneFallbackLabel: '审核场景',
    dateLabel: '审核时间',
    statusTitle: '风险等级',
    statusTabs: riskLevelTabs,
    showDocumentType: false
  },
  [DOCUMENT_SCOPE_ARCHIVE]: {
    searchPlaceholder: '搜索归档单号、事项、费用场景...',
    sceneFallbackLabel: '归档场景',
    dateLabel: '归档时间',
    statusTitle: '风险等级',
    statusTabs: riskLevelTabs,
    showDocumentType: false
  }
}
export const pageSizeOptions = [10, 20, 50].map((size) => ({ label: `${size} 条/页`, value: size }))
export const pageSizeValues = pageSizeOptions.map((item) => item.value)
export const documentTypeOptions = [
  { value: DOCUMENT_TYPE_ALL, label: '单据类型' },
  { value: DOCUMENT_TYPE_APPLICATION, label: '申请单' },
  { value: DOCUMENT_TYPE_REIMBURSEMENT, label: '报销单' }
]

export function routeQueryEquals(left, right) {
  const leftEntries = Object.entries(left || {}).map(([key, value]) => [
    key,
    Array.isArray(value) ? value.join(',') : String(value ?? '')
  ])
  const rightEntries = Object.entries(right || {}).map(([key, value]) => [
    key,
    Array.isArray(value) ? value.join(',') : String(value ?? '')
  ])
  if (leftEntries.length !== rightEntries.length) return false
  const rightMap = new Map(rightEntries)
  return leftEntries.every(([key, value]) => rightMap.get(key) === value)
}

export function buildDocumentRow(request, options = {}) {
  const normalized = normalizeRequestForUi(request)
  if (!normalized) {
    return null
  }

  const archived = Boolean(options.archived)
  const source = options.source || 'owned'
  const statusGroup = resolveStatusGroup(normalized, archived)
  const statusLabel = archived ? resolveArchivedStatusLabel(normalized) : resolveStatusLabel(normalized, statusGroup)
  const riskMeta = buildDocumentRiskMeta(normalized, options.currentUser)
  const documentNo = normalized.documentNo || normalized.id || normalized.claimId || '待生成'
  const claimId = normalized.claimId || normalized.id || documentNo
  const createdAtSource = normalized.createdAt || normalized.submittedAt || normalized.applyTime || normalized.updatedAt
  const updatedAtSource = normalized.updatedAt || normalized.submittedAt || normalized.createdAt || normalized.applyTime
  const createdSortTime = resolveDocumentSortTime(createdAtSource)
  const updatedSortTime = resolveDocumentSortTime(updatedAtSource)
  const documentTypeCode = normalized.documentTypeCode || DOCUMENT_TYPE_REIMBURSEMENT
  const documentTypeLabel =
    normalized.documentTypeLabel
    || resolveDocumentTypeLabel(documentTypeCode)
  const initiatorName = String(
    normalized.person
    || normalized.employeeName
    || normalized.profileName
    || normalized.applicant
    || request?.employee_name
    || request?.employeeName
    || request?.person
    || ''
  ).trim() || '待补充'

  return {
    ...normalized,
    rawRequest: request,
    documentKey: `${source}:${claimId || documentNo}`,
    documentTypeCode,
    documentTypeLabel,
    claimId,
    documentNo,
    initiatorName,
    node: archived ? resolveArchivedDocumentNode(normalized, documentTypeCode) : (normalized.node || normalized.workflowNode || '待提交'),
    statusGroup,
    statusLabel,
    statusTone: archived ? 'archived' : resolveStatusTone(normalized, statusGroup),
    riskTone: riskMeta.tone,
    riskLabel: riskMeta.label,
    riskCount: riskMeta.count,
    riskTags: riskMeta.tags,
    source,
    archived,
    createdAtDisplay: formatDocumentListTime(createdAtSource),
    stayTimeDisplay: resolveDocumentStayTimeDisplay(normalized),
    isNewDocument: archived
      ? false
      : isNewDocument({ ...normalized, source, claimId, documentNo }, options.viewedDocumentKeys || []),
    updatedAtDisplay: formatDocumentListTime(updatedAtSource),
    createdSortTime,
    updatedSortTime,
    sortTime: Math.max(createdSortTime, updatedSortTime)
  }
}

export function buildDocumentRiskMeta(row, currentUser = null) {
  const riskFlags = resolveDocumentRiskFlags(row)
  const riskSummary = row?.riskSummary || row?.risk
  // 列表风险标签按当前查看者可见性过滤，与详情页口径一致。
  const viewerOptions = currentUser ? { request: row || {}, currentUser } : null
  const count = countClaimRisks(riskFlags, riskSummary, viewerOptions)
  if (!count) {
    const meta = RISK_TONE_META.none
    return {
      ...meta,
      count: 0,
      tags: [{ ...meta }]
    }
  }

  const tone = resolveArchiveRiskTone(riskFlags, riskSummary, viewerOptions)
  const meta = RISK_TONE_META[tone] || RISK_TONE_META.medium
  return {
    ...meta,
    count,
    tags: [{ tone: meta.tone, label: `${meta.label} ${count}项` }]
  }
}

export function filterDocumentRows(rows, filters = {}) {
  const keyword = String(filters.keyword || '').trim().toLowerCase()
  return sortDocumentRowsByLatestTime((rows || []).filter((row) => {
    const matchesKeyword = !keyword || [
      row.documentNo,
      row.documentTypeLabel,
      row.typeLabel,
      row.initiatorName,
      row.reason,
      row.node,
      row.statusLabel,
      row.riskLabel
    ].filter(Boolean).join('').toLowerCase().includes(keyword)

    const matchesDocumentType =
      !filters.showDocumentTypeFilter
      || filters.activeDocumentType === DOCUMENT_TYPE_ALL
      || row.documentTypeCode === filters.activeDocumentType

    const matchesScene = filters.activeScene === SCENE_ALL || row.typeCode === filters.activeScene
    const matchesRiskLevel = matchesRiskLevelTab(row, filters.activeStatusTab, filters.activeScopeTab)
    const matchesDateRange = matchesAppliedDateRange(row, filters.appliedStart, filters.appliedEnd)

    return matchesKeyword && matchesDocumentType && matchesScene && matchesRiskLevel && matchesDateRange
  }))
}

export function matchesRiskLevelTab(row, tab, activeScopeTab = DOCUMENT_SCOPE_ALL) {
  if (activeScopeTab !== DOCUMENT_SCOPE_ARCHIVE && isArchivedDocumentRow(row)) {
    return false
  }

  if (tab === '全部') return true
  if (tab === '高风险') return row.riskTone === 'high'
  if (tab === '中风险') return row.riskTone === 'medium'
  if (tab === '低风险') return row.riskTone === 'low'
  if (tab === '无风险') return row.riskTone === 'none'
  return true
}

export function matchesAppliedDateRange(row, start, end) {
  if (!start || !end) {
    return true
  }

  const date = extractDateText(row.updatedAt || row.submittedAt || row.createdAt || row.applyTime)
  return Boolean(date) && date >= start && date <= end
}

export function mergeDocumentRows(rows) {
  const rowMap = new Map()

  rows.filter(Boolean).forEach((row) => {
    const key = row.claimId || row.documentNo || row.documentKey
    const current = rowMap.get(key)
    if (!current || resolveSourcePriority(row) >= resolveSourcePriority(current)) {
      rowMap.set(key, row)
    }
  })

  return sortDocumentRowsByLatestTime(Array.from(rowMap.values()))
}

export function hasDocumentCenterActiveFilters(filters = {}) {
  return Boolean(
    String(filters.listKeyword || '').trim()
    || filters.activeStatusTab !== '全部'
    || (filters.showDocumentTypeFilter && filters.activeDocumentType !== DOCUMENT_TYPE_ALL)
    || filters.activeScene !== SCENE_ALL
    || filters.appliedStart
    || filters.appliedEnd
  )
}

export function buildDocumentCenterEmptyState(options = {}) {
  const filtered = Boolean(options.hasActiveFilters)
  const activeScopeTab = options.activeScopeTab || DOCUMENT_SCOPE_ALL
  if (
    activeScopeTab === DOCUMENT_SCOPE_APPLICATION
    || options.activeDocumentType === DOCUMENT_TYPE_APPLICATION
  ) {
    return {
      eyebrow: '申请单',
      title: '当前还没有申请单数据',
      desc: '费用申请功能接入后，差旅、会务、办公采购等前置申请会统一汇总到这里。',
      icon: 'mdi mdi-file-sign-outline',
      actionLabel: '',
      actionIcon: '',
      tone: 'theme',
      artLabel: 'APPLY',
      tips: ['申请、报销、审批与归档统一在此查看', '申请批准后可继续发起报销']
    }
  }

  return {
    eyebrow: filtered ? '筛选结果为空' : '单据中心',
    title: filtered ? '没有符合当前条件的单据' : `“${activeScopeTab}”里暂时没有单据`,
    desc: filtered
      ? '可以清空当前分类下的筛选条件后再看看。'
      : '当前视角暂无可展示单据，可以切换其他视角或发起一笔报销。',
    icon: filtered ? 'mdi mdi-magnify-scan' : 'mdi mdi-file-document-multiple-outline',
    actionLabel: '',
    actionIcon: '',
    tone: 'theme',
    artLabel: filtered ? 'FILTER' : 'DOCS',
    tips: ['单据中心已接入当前报销单据', '归档视角会同步已归档数据']
  }
}

function resolveArchivedDocumentNode(normalized, documentTypeCode) {
  if (documentTypeCode === DOCUMENT_TYPE_APPLICATION) {
    return '申请归档'
  }
  if (normalized.status === 'paid' || normalized.approvalStatus === '已付款') {
    return '已付款'
  }
  return normalized.node || normalized.workflowNode || '财务归档'
}

function resolveArchivedStatusLabel(normalized) {
  if (normalized.status === 'paid' || normalized.approvalStatus === '已付款' || normalized.node === '已付款') {
    return '已付款'
  }
  return '已归档'
}

function resolveStatusGroup(row, archived) {
  if (archived) return 'completed'
  if (row.approvalKey === 'draft') return 'draft'
  if (row.approvalKey === 'supplement' && row.status === 'returned') return 'pending_submit'
  if (row.approvalKey === 'supplement') return 'supplement'
  if (row.approvalKey === 'pending_payment') return 'pending_payment'
  if (row.approvalKey === 'in_progress') return 'in_progress'
  if (row.approvalKey === 'completed') return 'completed'
  return 'other'
}

function resolveStatusLabel(row, statusGroup) {
  if (statusGroup === 'pending_submit') return '待提交'
  if (statusGroup === 'pending_payment') return '待付款'
  return row.approval || row.approvalStatus || '处理中'
}

function resolveStatusTone(row, statusGroup) {
  if (statusGroup === 'pending_submit') return 'warning'
  return row.approvalTone || 'neutral'
}

function resolveDocumentRiskFlags(row) {
  if (Array.isArray(row?.riskFlags)) {
    return row.riskFlags
  }
  if (Array.isArray(row?.risk_flags_json)) {
    return row.risk_flags_json
  }
  return []
}

function resolveSourcePriority(row) {
  if (row.archived) return 3
  if (row.source === 'approval') return 2
  return 1
}
