import { REVIEW_SLOT_CONFIG } from './travelReimbursementReviewConstants.js'
import {
  formatConfidenceLabel,
  resolveExpenseTypeLabel
} from './travelReimbursementReviewDocuments.js'
import {
  buildReviewSlotMap,
  formatAmountDisplay,
  inferPresetSceneFromReview,
  parseAmountNumber,
  resolveExpenseTypeCode,
  resolveReviewExtraMissingLabels,
  resolveReviewMissingSlotCards,
  resolveReviewRecognizedSlotCards
} from './travelReimbursementReviewFormModel.js'

function resolvePresentationRiskBriefs(reviewPayload, riskBriefResolver = null) {
  if (typeof riskBriefResolver === 'function') {
    return riskBriefResolver(reviewPayload)
  }
  return Array.isArray(reviewPayload?.risk_briefs) ? reviewPayload.risk_briefs : []
}

export function buildClientTimeContext() {
  const now = new Date()
  const locale =
    typeof navigator !== 'undefined' && typeof navigator.language === 'string'
      ? navigator.language
      : 'zh-CN'

  return {
    client_now_iso: now.toISOString(),
    client_timezone_offset_minutes: now.getTimezoneOffset(),
    client_locale: locale
  }
}



export function formatDraftApplyTime(date = new Date()) {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hours = String(date.getHours()).padStart(2, '0')
  const minutes = String(date.getMinutes()).padStart(2, '0')
  return `${year}-${month}-${day} ${hours}:${minutes}`
}



export function formatDateInputValue(date = new Date()) {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  return `${year}-${month}-${day}`
}



export function buildDraftSavedPayload({
  draftPayload,
  reviewPayload,
  inlineState,
  linkedRequest,
  currentUser,
  riskItems = []
}) {
  const documents = Array.isArray(reviewPayload?.document_cards) ? reviewPayload.document_cards : []
  const missingItems = resolveReviewMissingSlotCards(reviewPayload)
  const typeCode = resolveExpenseTypeCode(inlineState?.expense_type)
  const amountNumber = parseAmountNumber(inlineState?.amount)
  const location = String(inlineState?.location || linkedRequest?.city || '').trim()
  const customerName = String(inlineState?.customer_name || '').trim()
  const typeLabel = String(inlineState?.expense_type || linkedRequest?.typeLabel || resolveExpenseTypeLabel(typeCode)).trim()
  const title =
    String(inlineState?.reason_value || '').trim()
    || String(inlineState?.scene_label || '').trim()
    || String(draftPayload?.title || '').trim()
    || `${typeLabel}报销草稿`
  const sceneLabel =
    String(inlineState?.scene_label || summarizeReviewScene(title, typeLabel, reviewPayload)).trim() || typeLabel
  const attachmentSummary = documents.length
    ? `${documents.length} 条识别票据 / ${documents.length} 份材料`
    : String(inlineState?.attachment_names || '').trim()
      ? '1 条识别票据 / 1 份材料'
      : '待上传票据'

  return {
    claimId: String(draftPayload?.claim_id || '').trim(),
    claimNo: String(draftPayload?.claim_no || '').trim(),
    status: String(draftPayload?.status || '').trim(),
    approvalStage: String(draftPayload?.approval_stage || '').trim(),
    person: String(currentUser?.name || '').trim() || '当前用户',
    dept: String(currentUser?.department || currentUser?.departmentName || '').trim() || '待补充部门',
    entity: String(linkedRequest?.entity || '').trim() || 'Northstar China Ltd.',
    typeCode,
    typeLabel,
    detailVariant: typeCode === 'travel' ? 'travel' : 'general',
    title,
    sceneLabel,
    sceneTarget: location || customerName || '待补充',
    location,
    relatedCustomer: customerName,
    occurredDisplay: String(inlineState?.occurred_date || '').trim() || '待补充',
    applyTime: formatDraftApplyTime(),
    amount: amountNumber === null ? 0 : amountNumber,
    secondaryStatusLabel: typeCode === 'travel' ? '行程状态' : '票据状态',
    secondaryStatusValue: documents.length ? '待继续完善' : '待上传票据',
    secondaryStatusTone: documents.length ? 'warning' : 'neutral',
    riskSummary: riskItems[0]?.summary || (missingItems.length ? '仍有识别字段待补充，请继续完善。' : 'AI 已生成草稿，可继续补充后提交。'),
    attachmentSummary,
    expenseTableSummary: documents.length
      ? `已关联 ${documents.length} 份票据，请继续在报销页补充和确认`
      : '当前尚未上传票据，请在报销页继续补充附件',
    note: String(draftPayload?.status || '').trim() === 'submitted'
      ? '该报销单已由 AI 工作台提交审批，可在个人报销页面持续跟踪进度。'
      : '该草稿由 AI 工作台根据当前识别结果生成，可在个人报销页面继续补充明细、票据与说明。'
  }
}


export function countReviewPendingItems(reviewPayload) {
  return resolveReviewMissingSlotCards(reviewPayload).length + resolveReviewExtraMissingLabels(reviewPayload).length
}



export function countReviewRiskItems(reviewPayload, riskBriefResolver = null) {
  return resolvePresentationRiskBriefs(reviewPayload, riskBriefResolver).length
}



export function buildReviewHeadline(reviewPayload) {
  if (countReviewPendingItems(reviewPayload)) {
    return '待补充信息'
  }
  if (reviewPayload?.can_proceed) {
    return '识别结果已整理完成'
  }
  return '识别结果摘要'
}



export function buildReviewSubline(reviewPayload) {
  const pendingCount = countReviewPendingItems(reviewPayload)

  if (pendingCount) {
    return `我已把 ${pendingCount} 项待补充内容整理成文字说明，请先核查。`
  }
  if (reviewPayload?.can_proceed) {
    return '当前关键信息已基本齐全，确认无误后可以继续下一步。'
  }
  return '已为您整理本轮识别结果，请核查当前识别摘要。'
}



export function buildReviewStateLabel(reviewPayload) {
  const pendingCount = countReviewPendingItems(reviewPayload)
  if (pendingCount) return `待补充 ${pendingCount} 项`
  if (reviewPayload?.can_proceed) return '可继续处理'
  return '已识别'
}



export function buildReviewStateTone(reviewPayload) {
  return reviewPayload?.can_proceed && !countReviewPendingItems(reviewPayload)
    ? 'ready'
    : 'pending'
}



export function buildReviewDisclosureTitle(reviewPayload) {
  const pendingCount = countReviewPendingItems(reviewPayload)
  if (pendingCount) {
    return `当前有 ${pendingCount} 项待补充，点击展开查看`
  }
  return '当前信息已齐全，可展开查看识别摘要'
}



export function buildReviewDisclosureHint(reviewPayload) {
  const pendingCount = countReviewPendingItems(reviewPayload)
  if (pendingCount) {
    return '展开后可查看待补充字段和处理建议'
  }
  return '展开后可查看本轮已识别的关键信息'
}



export function shouldOpenReviewDisclosure(reviewPayload) {
  return !countReviewPendingItems(reviewPayload)
}



export function buildReviewTodoSectionTitle(reviewPayload) {
  return countReviewPendingItems(reviewPayload) ? '待补充内容' : '已识别信息'
}



export function buildReviewTodoSectionMeta(reviewPayload) {
  const count = buildReviewTodoItems(reviewPayload).length
  if (countReviewPendingItems(reviewPayload)) {
    return count ? `${count} 项` : '待确认'
  }
  return count ? `${count} 项` : '已齐全'
}



export function buildReviewAlertLabel(slotKey, expenseTypeLabel = '') {
  if (slotKey === 'customer_name') {
    return expenseTypeLabel === '业务招待费' ? '业务招待费需补充关联客户' : '缺少关联客户'
  }
  if (slotKey === 'participants') return '缺少同行人员'
  if (slotKey === 'attachments') return '票据状态待补充'
  if (slotKey === 'amount') return '金额待确认'
  if (slotKey === 'time_range') return '发生时间待确认'
  if (slotKey === 'reason') return '场景 / 事由待补充'
  if (slotKey === 'expense_type') return '报销类型待确认'
  if (slotKey === 'location') return '业务地点待补充'
  if (slotKey === 'merchant_name') return '酒店/商户待补充'
  return '仍有信息待补充'
}



export function buildReviewAlertChips(reviewPayload, riskBriefResolver = null) {
  const slotMap = buildReviewSlotMap(reviewPayload)
  const expenseTypeLabel = String(slotMap.expense_type?.value || '').trim()
  const chips = []

  for (const item of resolveReviewMissingSlotCards(reviewPayload).slice(0, 3)) {
    chips.push({
      key: item.key,
      label: buildReviewAlertLabel(item.key, expenseTypeLabel),
      tone: 'warning'
    })
  }

  if (chips.length < 3) {
    for (const label of resolveReviewExtraMissingLabels(reviewPayload)) {
      chips.push({
        key: label,
        label,
        tone: 'warning'
      })
      if (chips.length >= 3) break
    }
  }

  if (chips.length < 3) {
    for (const risk of resolvePresentationRiskBriefs(reviewPayload, riskBriefResolver)) {
      if (chips.some((item) => item.label === risk.title)) continue
      chips.push({
        key: risk.title,
        label: risk.title,
        tone: risk.level === 'high' ? 'danger' : 'warning'
      })
      if (chips.length >= 3) break
    }
  }

  if (!chips.length && reviewPayload?.can_proceed) {
    chips.push({
      key: 'ready',
      label: '当前识别信息已可继续处理',
      tone: 'success'
    })
  }

  return chips
}



export function buildReviewTodoItems(reviewPayload) {
  const missingItems = resolveReviewMissingSlotCards(reviewPayload)
  const extraMissingLabels = resolveReviewExtraMissingLabels(reviewPayload)
  if (missingItems.length || extraMissingLabels.length) {
    return [
      ...missingItems.map((item) => {
      const config = REVIEW_SLOT_CONFIG[item.key] || {}
      return {
        key: item.key,
        icon: config.icon || 'mdi mdi-form-select',
        title: config.title || item.label,
        hint: item.hint || config.hint || `请补充${item.label}`,
        status: config.status || '待补充',
        tone: 'warning'
      }
    }),
      ...extraMissingLabels.map((label, index) => ({
        key: `extra-missing-${index}-${label}`,
        icon: label.includes('酒店') || label.includes('住宿') ? 'mdi mdi-bed-outline' : 'mdi mdi-file-alert-outline',
        title: label,
        hint: label.includes('必须')
          ? '该票据属于当前差旅提交的必备材料，补齐后才能继续下一步。'
          : '可以继续补充该材料；如暂时没有，也可以按当前信息处理。',
        status: label.includes('必须') ? '必须补齐' : '可选补充',
        tone: 'warning'
      }))
    ]
  }

  return resolveReviewRecognizedSlotCards(reviewPayload)
    .filter((item) => String(item?.value || '').trim())
    .slice(0, 3)
    .map((item) => {
      const config = REVIEW_SLOT_CONFIG[item.key] || {}
      return {
        key: item.key,
        icon: config.icon || 'mdi mdi-check-circle-outline',
        title: config.title || item.label,
        hint: `已识别：${item.value}`,
        status: '已识别',
        tone: 'ready'
      }
    })
}



// 待补充字段提示：每个字段给 2~3 种说法轮换，避免每次同一句。
// 取值用 buildStableTemplateIndex 按字段签名稳定选取，保证同一字段在同一次会话里文案一致。
const REVIEW_PENDING_HINT_COPY = {
  expense_type: [
    '这笔费用先归个类，后续票据就按这个分类往下核。',
    '还差费用类型，定下来我才能匹配对应的标准和材料。'
  ],
  customer_name: [
    '客户单位的全称填一下，合规校验要用。',
    '还差客户单位名称，补上就行。'
  ],
  time_range: [
    '业务是哪天发生的？日期或时间范围都行。',
    '还差业务发生时间，补个准确日期。'
  ],
  location: [
    '这笔费用发生在哪儿？',
    '业务地点还空着，补一下。'
  ],
  merchant_name: [
    '住的是哪家酒店、或是在哪家商户消费的？',
    '还差酒店或商户名称。'
  ],
  amount: [
    '这笔费用多少钱？',
    '金额还没填，补上才能继续。'
  ],
  reason: [
    '这笔费用是为什么发生的？简单说两句背景。',
    '事由还空着，补一下方便审核。'
  ],
  participants: [
    '一起出差的还有谁？至少填 1 位。',
    '同行人员还没填，补 1 名以上。'
  ],
  attachments: [
    '对应的票据传一下，或者关联已有的也行。',
    '还差票据附件，上传或关联一张。'
  ]
}

function resolveReviewPendingHint(fieldKey, signature = '') {
  const candidates = REVIEW_PENDING_HINT_COPY[fieldKey]
  if (!Array.isArray(candidates) || !candidates.length) {
    return ''
  }
  const index = buildStableTemplateIndex(`${fieldKey}:${signature}`, candidates.length)
  return candidates[index]
}

function normalizeReviewFollowupSentence(text) {
  const normalized = String(text || '')
    .replace(/^已识别[：:]\s*/, '')
    .replace(/^建议补充\s*/, '请补充')
    .replace(/\s+/g, ' ')
    .trim()
  if (!normalized) return ''
  return /[。！？.!?]$/.test(normalized) ? normalized : `${normalized}。`
}

function buildReviewPlainFollowupItem(item, pendingMode) {
  const key = String(item?.key || '').trim()
  const label = String(item?.title || item?.label || '').trim() || '待核查信息'
  if (pendingMode) {
    const hintFromPool = resolveReviewPendingHint(key, `${key}:${label}`)
    const fallbackHint = String(item?.hint || '').trim() || `请补充${label}`
    return {
      key: key || label,
      label,
      text: normalizeReviewFollowupSentence(hintFromPool || fallbackHint)
    }
  }

  const value = normalizeReviewFollowupSentence(item?.hint || '')
  return {
    key: key || label,
    label,
    text: value || '已识别，请核查是否准确。'
  }
}

// 4 条结构差异较大的轮播：①先点状态 ②先给选择 ③先共情 ④先给行动。
// 数量收敛后由 buildStableTemplateIndex 自动落到新范围，行为不变。
const REVIEW_PENDING_SUMMARY_TEMPLATES = [
  ({ issueSummary }) => `还差 ${issueSummary}，下面都列出来了，补齐就能继续。急着走的话，点“草稿”先把当前进度存下来。`,
  ({ issueSummary }) => `别急，这单还剩 ${issueSummary}。您可以选择现在就按下面的提示补，也可以稍后再回来——点“草稿”随时暂存。`,
  ({ issueSummary }) => `这边识别下来，${issueSummary} 还没到位。先看一眼下面的内容对不对，确认好了再往下；中途想停就点“草稿”。`,
  ({ issueSummary }) => `差 ${issueSummary}，所以暂时还不能提交。照着下面几项补一下，补完就能进下一步；实在没空先存草稿也行。`
]

const REVIEW_SAVED_DRAFT_PENDING_SUMMARY_TEMPLATES = [
  ({ issueSummary }) => `草稿存好了，但还差 ${issueSummary}。后面传票时记得关联到这张草稿，补齐了再提交审批。`,
  ({ issueSummary }) => `这张草稿还留着 ${issueSummary} 没处理。您随时可以回来补，新增的附件我会归到这张草稿上，不会重复建单。`,
  ({ issueSummary }) => `进度保住了，不过 ${issueSummary} 还得补。建议把金额、票据这些先弄齐，再从草稿详情发起正式提交。`,
  ({ issueSummary }) => `草稿状态下还剩 ${issueSummary}。可以继续补字段和票据，补完了再提交；想先放着也没问题，草稿不会丢。`
]

function buildStableTemplateIndex(signature, total) {
  const source = String(signature || '')
  let hash = 0
  for (let index = 0; index < source.length; index += 1) {
    hash = ((hash << 5) - hash + source.charCodeAt(index)) >>> 0
  }
  return total ? hash % total : 0
}

function buildReviewPendingSummary(pendingCount, riskCount, signature = '', options = {}) {
  const issueParts = []
  if (pendingCount) {
    issueParts.push(`${pendingCount} 项信息待补充`)
  }
  if (riskCount) {
    issueParts.push(`${riskCount} 条风险提醒`)
  }
  const issueSummary = issueParts.length ? issueParts.join('、') : '一些细节还需要进一步确认'
  const templates = options.savedDraft
    ? REVIEW_SAVED_DRAFT_PENDING_SUMMARY_TEMPLATES
    : REVIEW_PENDING_SUMMARY_TEMPLATES
  const templateIndex = buildStableTemplateIndex(signature || issueSummary, templates.length)
  return templates[templateIndex]({ issueSummary })
}

export function buildReviewPlainFollowupCopy(reviewPayload, options = {}) {
  const savedDraft = Boolean(options?.savedDraft)
  const todoItems = buildReviewTodoItems(reviewPayload)
  const pendingCount = countReviewPendingItems(reviewPayload)
  const riskBriefs = resolvePresentationRiskBriefs(reviewPayload)
  const extraMissingCount = resolveReviewExtraMissingLabels(reviewPayload).length

  if (savedDraft) {
    const issueParts = []
    if (riskBriefs.length) {
      issueParts.push(`${riskBriefs.length} 条风险/异常提醒`)
    }
    if (pendingCount || extraMissingCount) {
      issueParts.push(`${pendingCount || extraMissingCount} 项待补充信息`)
    }
    return {
      lead: '后续处理：',
      tone: riskBriefs.length || pendingCount || extraMissingCount ? 'danger' : 'neutral',
      summary: issueParts.length
        ? `自动检测识别到 ${issueParts.join('、')}，请进入详情核对；如还有票据可继续上传。`
        : '自动检测暂未发现明确风险；如还有票据可继续上传。',
      items: [],
      notes: []
    }
  }

  if (pendingCount || extraMissingCount) {
    const summarySignature = [
      pendingCount || extraMissingCount,
      riskBriefs.length,
      ...todoItems.map((item) => `${item.key}:${item.title}:${item.status}`)
    ].join('|')
    return {
      lead: '补充信息：',
      tone: 'danger',
      summary: buildReviewPendingSummary(pendingCount || extraMissingCount, riskBriefs.length, summarySignature, {
        savedDraft
      }),
      items: todoItems.map((item) => buildReviewPlainFollowupItem(item, true)),
      notes: []
    }
  }

  return {
    lead: todoItems.length ? '我已整理出当前识别到的关键信息：' : '当前关键信息已基本整理完成。',
    tone: 'neutral',
    summary: '',
    items: todoItems.map((item) => buildReviewPlainFollowupItem(item, false)),
    notes: [
      reviewPayload?.can_proceed ? '确认无误后，可以继续下一步。' : '',
      riskBriefs.length ? `系统同时保留了 ${riskBriefs.length} 条风险提醒，请在提交前核查。` : ''
    ].filter(Boolean)
  }
}



export function resolveReviewPrimaryAction(reviewPayload) {
  return (
    (Array.isArray(reviewPayload?.confirmation_actions) ? reviewPayload.confirmation_actions : []).find(
      (item) => item.emphasis === 'primary' || ['save_draft', 'next_step'].includes(String(item?.action_type || ''))
    ) || null
  )
}



export function resolveReviewSaveDraftAction(reviewPayload) {
  return (
    (Array.isArray(reviewPayload?.confirmation_actions) ? reviewPayload.confirmation_actions : []).find(
      (item) => String(item?.action_type || '') === 'save_draft'
    ) || null
  )
}



export function resolveReviewFooterActions(reviewPayload) {
  return (Array.isArray(reviewPayload?.confirmation_actions) ? reviewPayload.confirmation_actions : []).filter((item) => {
    const actionType = String(item?.action_type || '').trim()
    return ['link_to_existing_draft', 'create_new_claim_from_documents'].includes(actionType)
  })
}



export function buildReviewRiskLevelCounts(reviewPayload) {
  return (Array.isArray(reviewPayload?.risk_briefs) ? reviewPayload.risk_briefs : []).reduce(
    (counts, item) => {
      const level = normalizeReviewRiskLevel(item?.level)
      if (level === 'high' || level === 'medium' || level === 'low') {
        counts[level] += 1
      }
      return counts
    },
    { low: 0, medium: 0, high: 0 }
  )
}



export function resolveReviewNextStepAction(reviewPayload) {
  return (
    (Array.isArray(reviewPayload?.confirmation_actions) ? reviewPayload.confirmation_actions : []).find(
      (item) => String(item?.action_type || '').trim() === 'next_step'
    ) || null
  )
}



export function buildReviewNextStepRichCopy(reviewPayload, { detailHref = '' } = {}) {
  const nextStepAction = resolveReviewNextStepAction(reviewPayload)
  if (!nextStepAction) {
    return ''
  }

  const counts = buildReviewRiskLevelCounts(reviewPayload)
  const riskSummary = `现存在 ${counts.low} 条低风险，${counts.medium} 条中风险，${counts.high} 条高风险，具体情况请看 [右侧](#review-risk-panel) 风险信息提示窗。`
  const lines = [`系统识别您的单据已经填写完所有已知信息，${riskSummary}`]

  if (reviewPayload?.can_proceed && counts.medium === 0 && counts.high === 0) {
    const editHref = String(detailHref || '').trim() || '#review-quick-edit'
    lines.push(
      `系统确认您可以 [继续下一步](#review-next-step) 进行单据的提交，如果您确认信息无误，请点击富文本按钮；如果您还需要继续修改信息，请点击 [快速修改单据信息](${editHref})。`
    )
  }
  return lines.join('\n\n')
}



export function buildReviewPrimaryButtonLabel(reviewPayload, draftPayload) {
  const action = resolveReviewPrimaryAction(reviewPayload)
  if (!action) return '确认'
  if (action.action_type === 'save_draft') {
    return draftPayload?.claim_no ? '保存为草稿' : '保存为草稿'
  }
  if (action.action_type === 'next_step') {
    return '继续下一步'
  }
  if (action.action_type === 'link_to_existing_draft') {
    return action.label || '关联到现有草稿'
  }
  if (action.action_type === 'create_new_claim_from_documents') {
    return action.label || '单独建立报销单'
  }
  return action.label || '确认'
}



export function buildReviewIntentText(reviewPayload) {
  const slotMap = buildReviewSlotMap(reviewPayload)
  const expenseType = String(slotMap.expense_type?.value || '').trim()
  if (expenseType) {
    return `报销一笔${expenseType}`
  }
  return '发起一笔报销'
}



export function buildReviewSceneValue(reviewPayload) {
  const slotMap = buildReviewSlotMap(reviewPayload)
  const reason = String(slotMap.reason?.raw_value || slotMap.reason?.value || '').trim()
  const expenseType = String(slotMap.expense_type?.value || slotMap.expense_type?.normalized_value || '').trim()
  return inferPresetSceneFromReview(reviewPayload, reason, expenseType)
}



export function buildMissingRiskLine(slotKey, expenseTypeLabel = '') {
  if (slotKey === 'customer_name') {
    return expenseTypeLabel === '业务招待费'
      ? '业务招待费需补充客户单位名称，以便进行合规校验。'
      : '当前仍缺少客户单位名称，建议补充后再提交。'
  }
  if (slotKey === 'participants') {
    return '缺少同行人员信息，建议补充至少 1 名。'
  }
  if (slotKey === 'attachments') {
    return '尚未上传票据附件，当前无法完成票据核对。'
  }
  if (slotKey === 'amount') {
    return '报销金额仍待确认，提交前需补齐金额信息。'
  }
  if (slotKey === 'time_range') {
    return '业务发生时间仍待确认，建议补充准确日期。'
  }
  if (slotKey === 'reason') {
    return '报销事由说明仍不完整，建议补充业务背景。'
  }
  return '当前仍有识别信息待补充，建议先核对后再处理。'
}



export function buildReviewRiskSummary(reviewPayload, riskBriefResolver = null) {
  if (resolvePresentationRiskBriefs(reviewPayload, riskBriefResolver).length) {
    return '当前识别到了风险提示，点击任一风险点会在主对话中展开规则依据和整改建议。'
  }
  return '当前没有需要额外处理的结构化风险点。'
}



export function normalizeReviewRiskLevel(level) {
  const normalized = String(level || '').trim().toLowerCase()
  if (normalized === 'danger' || normalized === 'error' || normalized === 'critical') return 'high'
  if (normalized === 'warn' || normalized === 'warning' || normalized === 'medium') return 'medium'
  if (normalized === 'info' || normalized === 'notice') return 'info'
  if (normalized === 'low') return 'low'
  if (normalized === 'high') return normalized
  return 'low'
}



export function buildLocalReviewCompletionMessage(reviewPayload) {
  const missingSlots = Array.isArray(reviewPayload?.missing_slots) ? reviewPayload.missing_slots : []
  if (reviewPayload?.can_proceed && !missingSlots.length) {
    return '当前所有必填信息已处理完成，可以点击“继续下一步”进入 AI 预审。'
  }
  if (missingSlots.length) {
    return `当前还剩 ${missingSlots.length} 项待补充：${missingSlots.join('、')}。`
  }
  return '当前信息已保存，可以继续核对右侧状态。'
}



export function buildReviewRecognitionNotes(reviewPayload) {
  const recognized = resolveReviewRecognizedSlotCards(reviewPayload)
  const notes = []
  const timeSlot = recognized.find((item) => item.key === 'time_range')
  const sourceLabels = [...new Set(recognized.map((item) => String(item?.source_label || '').trim()).filter(Boolean))]

  if (timeSlot?.raw_value && timeSlot.raw_value !== timeSlot.value && timeSlot.value) {
    notes.push(`时间已按您的本地日期换算：${timeSlot.raw_value} -> ${timeSlot.value}`)
  }

  if (sourceLabels.length) {
    notes.push(`本轮主要依据：${sourceLabels.join('、')}`)
  }

  const documentCards = Array.isArray(reviewPayload?.document_cards) ? reviewPayload.document_cards : []
  if (documentCards.length) {
    notes.push(`已关联 ${documentCards.length} 份附件，逐张识别结果已整理在下方`)
  } else {
    notes.push('当前还没有上传票据，这一轮主要依据您的文字描述完成初步识别')
  }

  return notes
}



export function buildReviewMissingHint(reviewPayload) {
  if (!countReviewPendingItems(reviewPayload)) {
    return ''
  }
  if (reviewPayload?.can_proceed) {
    return '当前关键信息已经齐全，这里无需再补充。'
  }
  return '下面这些字段还需要您再确认或补齐，补完后我就能继续往下处理。'
}



export function buildReviewRiskHint(reviewPayload, riskBriefResolver = null) {
  const riskBriefs = resolvePresentationRiskBriefs(reviewPayload, riskBriefResolver)
  if (!riskBriefs.length) {
    return ''
  }
  return '这些是我根据当前单据信息、票据识别结果和规则口径给出的风险提示，提交前建议顺手核对一下。'
}



export function buildReviewActionHint(reviewPayload) {
  if (reviewPayload?.can_proceed) {
    return '如果识别无误，可以继续下一步；如果有偏差，请直接在右侧核对信息中修改。'
  }
  return '如果现在信息还不完整，可以先保存草稿；识别错了请直接在右侧核对信息中修改。'
}



export function buildReviewStatusTag(reviewPayload) {
  const missingCount = countReviewPendingItems(reviewPayload)
  if (reviewPayload?.can_proceed) {
    return '可继续处理'
  }
  if (missingCount > 0) {
    return `待补充 ${missingCount} 项`
  }
  return '待确认'
}
