import {
  CATEGORY_CONFIDENCE_KEYWORDS,
  REVIEW_CATEGORY_PRESET_OPTIONS
} from './travelReimbursementReviewConstants.js'
import {
  buildReviewDocumentCorrectionLines,
  formatConfidenceLabel
} from './travelReimbursementReviewDocuments.js'
import {
  buildReviewSlotMap,
  cloneReviewEditFields,
  createEmptyInlineReviewState,
  formatAmountDisplay,
  mergeInlineReviewFields,
  resolveExpenseTypeCode,
  resolveReviewExtraMissingLabels
} from './travelReimbursementReviewFormModel.js'

export function buildReviewAttachmentStatus(reviewPayload) {
  const documents = Array.isArray(reviewPayload?.document_cards) ? reviewPayload.document_cards : []
  if (!documents.length) return '未上传'
  return documents.length === 1 ? '已上传 1 份' : `已上传 ${documents.length} 份`
}

export function shouldShowReviewFactCard(reviewPayload, slotKey, value = '') {
  const slotMap = buildReviewSlotMap(reviewPayload)
  const slot = slotMap[slotKey]
  return Boolean(String(value || slot?.normalized_value || slot?.value || '').trim()) || slot?.status === 'missing'
}

export function buildReviewEvidenceText(reviewPayload, inlineState = createEmptyInlineReviewState()) {
  const slotMap = buildReviewSlotMap(reviewPayload)
  const documents = Array.isArray(reviewPayload?.document_cards) ? reviewPayload.document_cards : []

  return [
    String(inlineState.reason_value || '').trim(),
    String(inlineState.scene_label || '').trim(),
    String(slotMap.reason?.value || slotMap.reason?.raw_value || '').trim(),
    ...documents.map((item) =>
      [item.scene_label, item.summary, item.filename, ...(Array.isArray(item.warnings) ? item.warnings : [])]
        .filter(Boolean)
        .join(' ')
    )
  ]
    .filter(Boolean)
    .join(' ')
    .toLowerCase()
}

export function resolveReviewCategoryTextScore(text, categoryCode) {
  const patterns = CATEGORY_CONFIDENCE_KEYWORDS[categoryCode]
  if (!patterns?.length || !text) {
    return 0
  }
  return patterns.some((pattern) => pattern.test(text))
    ? {
        travel: 0.84,
        hotel: 0.82,
        transport: 0.8,
        meal: 0.76,
        meeting: 0.78,
        entertainment: 0.88,
        office: 0.74,
        training: 0.77,
        communication: 0.7,
        welfare: 0.72
      }[categoryCode] || 0
    : 0
}

export function resolveReviewCategoryDocumentScore(reviewPayload, categoryCode) {
  const documents = Array.isArray(reviewPayload?.document_cards) ? reviewPayload.document_cards : []
  const matchedScores = documents
    .filter((item) => resolveExpenseTypeCode(item?.suggested_expense_type) === categoryCode)
    .map((item) => Number(item?.avg_score || 0))
    .filter((score) => Number.isFinite(score) && score > 0)

  if (!matchedScores.length) {
    return 0
  }

  return matchedScores.reduce((sum, score) => sum + score, 0) / matchedScores.length
}

export function resolveReviewCategoryConfidenceScore(reviewPayload, selectedLabel = '', inlineState = createEmptyInlineReviewState()) {
  const normalizedLabel = String(selectedLabel || '').trim()
  if (!normalizedLabel) {
    return 0
  }

  const selectedCode = resolveExpenseTypeCode(normalizedLabel)
  const slotMap = buildReviewSlotMap(reviewPayload)
  const expenseSlot = slotMap.expense_type
  const recognizedCode = resolveExpenseTypeCode(expenseSlot?.normalized_value || expenseSlot?.value || '')
  let score = 0

  if (recognizedCode === selectedCode) {
    score = Math.max(score, Number(expenseSlot?.confidence || 0))
  }

  score = Math.max(score, resolveReviewCategoryDocumentScore(reviewPayload, selectedCode))
  score = Math.max(score, resolveReviewCategoryTextScore(buildReviewEvidenceText(reviewPayload, inlineState), selectedCode))

  if (!score && normalizedLabel) {
    score = selectedCode === 'other' ? 0.52 : 0.58
  }

  return Math.max(0, Math.min(0.98, Number(score.toFixed(2))))
}

export function buildReviewCategoryOptions(reviewPayload, selectedLabel = '', inlineState = createEmptyInlineReviewState()) {
  const presetLabels = REVIEW_CATEGORY_PRESET_OPTIONS.filter((item) => !item.is_other).map((item) => item.label)
  return REVIEW_CATEGORY_PRESET_OPTIONS.map((item, index) => ({
    ...item,
    active: item.is_other ? Boolean(selectedLabel) && !presetLabels.includes(selectedLabel) : item.label === selectedLabel,
    confidenceLabel: item.is_other
      ? formatConfidenceLabel(resolveReviewCategoryConfidenceScore(reviewPayload, selectedLabel, inlineState))
      : formatConfidenceLabel(resolveReviewCategoryConfidenceScore(reviewPayload, item.label, inlineState)),
    caption: item.is_other
      ? selectedLabel && !presetLabels.includes(selectedLabel)
        ? `${selectedLabel} · ${formatConfidenceLabel(resolveReviewCategoryConfidenceScore(reviewPayload, selectedLabel, inlineState))}`
        : '点击选择更多类型'
      : `置信度 ${formatConfidenceLabel(resolveReviewCategoryConfidenceScore(reviewPayload, item.label, inlineState))}`,
    groupLabel: index === 0 ? '常用' : index < 5 ? '常用' : '更多'
  }))
}

export function buildReviewPanelConfidence(reviewPayload, inlineState = createEmptyInlineReviewState()) {
  return formatConfidenceLabel(
    resolveReviewCategoryConfidenceScore(reviewPayload, inlineState.expense_type, inlineState)
  )
}

export function resolveInlineReviewSlotValue(slotKey, inlineState = createEmptyInlineReviewState()) {
  const state = inlineState || createEmptyInlineReviewState()
  if (slotKey === 'expense_type') return String(state.expense_type || '').trim()
  if (slotKey === 'customer_name') return String(state.customer_name || '').trim()
  if (slotKey === 'time_range') return String(state.occurred_date || '').trim()
  if (slotKey === 'location') return String(state.location || '').trim()
  if (slotKey === 'merchant_name') return String(state.merchant_name || '').trim()
  if (slotKey === 'amount') return String(state.amount || '').trim()
  if (slotKey === 'reason') return String(state.reason_value || state.scene_label || '').trim()
  if (slotKey === 'participants') return String(state.participants || '').trim()
  if (slotKey === 'attachments') {
    return String(state.attachment_names || '').trim()
      || (Number(state.attachment_count || 0) > 0 ? `${Number(state.attachment_count)} 份附件` : '')
      || (Number(state.pending_attachment_count || 0) > 0 ? `${Number(state.pending_attachment_count)} 份待上传附件` : '')
  }
  return ''
}

export function buildLocallySyncedReviewActions(reviewPayload, canProceed) {
  const actions = Array.isArray(reviewPayload?.confirmation_actions)
    ? reviewPayload.confirmation_actions.map((item) => ({ ...item }))
    : []
  const actionTypes = new Set(actions.map((item) => String(item?.action_type || '').trim()))
  const associationPending = actionTypes.has('link_to_existing_draft') || actionTypes.has('create_new_claim_from_documents')

  if (!canProceed || associationPending) {
    return actions
  }

  const syncedActions = actions.filter((item) => String(item?.action_type || '').trim() !== 'next_step')
  if (!syncedActions.some((item) => String(item?.action_type || '').trim() === 'save_draft')) {
    syncedActions.push({
      label: '保存为草稿',
      action_type: 'save_draft',
      description: '先暂存当前已识别信息，稍后仍可继续补充或提交。',
      emphasis: 'secondary'
    })
  }

  return [
    ...syncedActions,
    {
      label: '继续下一步',
      action_type: 'next_step',
      description: '当前信息已齐全，进入 AI 预审、风险校验和审批路径确认。',
      emphasis: 'primary'
    }
  ]
}

export function buildLocallySyncedReviewPayload(reviewPayload, inlineState = createEmptyInlineReviewState()) {
  if (!reviewPayload || typeof reviewPayload !== 'object') {
    return reviewPayload
  }

  const nextSlotCards = (Array.isArray(reviewPayload.slot_cards) ? reviewPayload.slot_cards : []).map((slot) => {
    const value = resolveInlineReviewSlotValue(slot.key, inlineState)
    const required = Boolean(slot.required)
    const filled = Boolean(value)
    return {
      ...slot,
      value: value || slot.value || '',
      normalized_value: value || slot.normalized_value || '',
      raw_value: value || slot.raw_value || '',
      source: filled ? 'user_form' : slot.source,
      source_label: filled ? '用户修改' : slot.source_label,
      confidence: filled ? Math.max(Number(slot.confidence || 0), 0.98) : Number(slot.confidence || 0),
      confirmed: filled || Boolean(slot.confirmed),
      status: required && !filled ? 'missing' : filled ? 'identified' : slot.status,
      hint: required && !filled ? slot.hint : ''
    }
  })
  const missingSlots = nextSlotCards
    .filter((slot) => slot.required && slot.status === 'missing')
    .map((slot) => slot.label || slot.key)
  const extraMissingSlots = resolveReviewExtraMissingLabels({
    ...reviewPayload,
    slot_cards: nextSlotCards
  })
  const allMissingSlots = [...missingSlots, ...extraMissingSlots]
  const canProceed = allMissingSlots.length === 0 && (Array.isArray(reviewPayload.claim_groups) ? reviewPayload.claim_groups.length > 0 : true)

  return {
    ...reviewPayload,
    can_proceed: canProceed,
    missing_slots: allMissingSlots,
    slot_cards: nextSlotCards,
    edit_fields: mergeInlineReviewFields(reviewPayload.edit_fields || [], inlineState),
    confirmation_actions: buildLocallySyncedReviewActions(reviewPayload, canProceed)
  }
}

export function normalizeInlineReviewComparableState(state) {
  const source = state && typeof state === 'object' ? state : {}
  return {
    occurred_date: String(source.occurred_date || '').trim(),
    amount: String(source.amount || '').trim(),
    transport_type: String(source.transport_type || '').trim(),
    scene_label: String(source.scene_label || '').trim(),
    reason_value: String(source.reason_value || '').trim(),
    customer_name: String(source.customer_name || '').trim(),
    location: String(source.location || '').trim(),
    merchant_name: String(source.merchant_name || '').trim(),
    participants: String(source.participants || '').trim(),
    attachment_names: String(source.attachment_names || '').trim(),
    pending_attachment_count: Math.max(0, Number(source.pending_attachment_count || 0)),
    expense_type: String(source.expense_type || '').trim()
  }
}

export function buildInlineReviewChangedLines(baseState, nextState, pendingFiles = []) {
  const base = normalizeInlineReviewComparableState(baseState)
  const next = normalizeInlineReviewComparableState(nextState)
  const lines = []

  if (base.occurred_date !== next.occurred_date) {
    lines.push(`发生时间 ${next.occurred_date || '待补充'}`)
  }
  if (base.amount !== next.amount) {
    lines.push(`金额 ${formatAmountDisplay(next.amount) || '待补充'}`)
  }
  if (base.transport_type !== next.transport_type) {
    lines.push(`交通类型 ${next.transport_type || '待确认'}`)
  }
  if (base.scene_label !== next.scene_label) {
    lines.push(`场景 ${next.scene_label || '待补充'}`)
  }
  if (base.customer_name !== next.customer_name) {
    lines.push(`关联客户 ${next.customer_name || '待补充'}`)
  }
  if (base.location !== next.location) {
    lines.push(`业务地点 ${next.location || '待补充'}`)
  }
  if (base.merchant_name !== next.merchant_name) {
    lines.push(`酒店/商户 ${next.merchant_name || '待补充'}`)
  }
  if (base.participants !== next.participants) {
    lines.push(`同行人员 ${next.participants || '待补充'}`)
  }
  if (base.expense_type !== next.expense_type) {
    lines.push(`报销分类 ${next.expense_type || '待补充'}`)
  }
  if (base.attachment_names !== next.attachment_names || pendingFiles.length) {
    lines.push(`票据 ${next.attachment_names || (pendingFiles.length ? `已选择 ${pendingFiles.length} 份附件` : '待上传')}`)
  }

  return lines
}

export function buildInlineReviewChangePhrases(baseState, nextState, pendingFiles = []) {
  const base = normalizeInlineReviewComparableState(baseState)
  const next = normalizeInlineReviewComparableState(nextState)
  const fieldConfigs = [
    { key: 'occurred_date', label: '发生时间', format: (value) => value || '待补充' },
    { key: 'amount', label: '金额', format: (value) => formatAmountDisplay(value) || '待补充' },
    { key: 'transport_type', label: '交通类型', format: (value) => value || '待确认' },
    { key: 'scene_label', label: '场景', format: (value) => value || '待补充' },
    { key: 'customer_name', label: '关联客户', format: (value) => value || '待补充' },
    { key: 'location', label: '业务地点', format: (value) => value || '待补充' },
    { key: 'merchant_name', label: '酒店/商户', format: (value) => value || '待补充' },
    { key: 'participants', label: '同行人员', format: (value) => value || '待补充' },
    { key: 'expense_type', label: '报销分类', format: (value) => value || '待补充' }
  ]

  const phrases = fieldConfigs.reduce((result, item) => {
    if (base[item.key] !== next[item.key]) {
      result.push(`${item.label}修改为 ${item.format(next[item.key])}`)
    }
    return result
  }, [])

  if (base.attachment_names !== next.attachment_names || pendingFiles.length) {
    phrases.push(`票据修改为 ${next.attachment_names || (pendingFiles.length ? `已选择 ${pendingFiles.length} 份附件` : '待上传')}`)
  }

  return phrases
}

export function buildLocalReviewSavedMessage(baseState, nextState, pendingFiles = [], baseDrafts = [], nextDrafts = []) {
  const phrases = buildInlineReviewChangePhrases(baseState, nextState, pendingFiles)
  const documentLines = buildReviewDocumentCorrectionLines(baseDrafts, nextDrafts)

  if (documentLines.length) {
    phrases.push(`${documentLines.length} 张票据识别信息更新为最新修改`)
  }

  if (!phrases.length) {
    return '右侧核对信息已保存。'
  }

  return `已将${phrases.join('，')}。`
}

export function buildInlineReviewUserText(baseState, nextState, pendingFiles = []) {
  const lines = buildInlineReviewChangedLines(baseState, nextState, pendingFiles)
  if (!lines.length) {
    return '我已校正核对信息，请按最新内容更新。'
  }
  return `我已校正核对信息：${lines.join('，')}。请按最新内容更新。`
}

export function buildReviewSubmitUserText(baseState, nextState, pendingFiles = [], baseDrafts = [], nextDrafts = []) {
  const inlineLines = buildInlineReviewChangedLines(baseState, nextState, pendingFiles)
  const documentLines = buildReviewDocumentCorrectionLines(baseDrafts, nextDrafts)

  if (!inlineLines.length && !documentLines.length) {
    return '我已校正核对信息，请按最新内容更新。'
  }

  const parts = []
  if (inlineLines.length) {
    parts.push(inlineLines.join('，'))
  }
  if (documentLines.length) {
    parts.push(`修正了 ${documentLines.length} 张票据识别信息`)
  }

  return `我已校正核对信息：${parts.join('；')}。请按最新内容更新。`
}
