import test from 'node:test'
import assert from 'node:assert/strict'

import {
  buildAiAttachmentAssociationActions,
  buildAiAttachmentAssociationMessage,
  buildAiAttachmentAssociationResultMessage,
  resolveAiAttachmentAssociationMatch
} from '../src/utils/aiAttachmentAssociationModel.js'
import { renderAiConversationHtml } from '../src/utils/aiConversationHtmlRenderer.js'

function findAction(actions, actionType) {
  return actions.find((action) => action.action_type === actionType)
}

test('根据票据日期和行程自动匹配最可能关联的报销单', () => {
  const claims = [
    {
      id: 'claim-wuhan-shanghai',
      claim_no: 'BX-20260220-001',
      expense_type: 'travel',
      status: 'draft',
      reason: '辅助国网仿生产服务器部署，武汉往返上海',
      location: '上海',
      occurred_at: '2026-02-20'
    },
    {
      id: 'claim-nanjing',
      claim_no: 'BX-20260301-002',
      expense_type: 'travel',
      status: 'draft',
      reason: '南京客户拜访',
      location: '南京',
      occurred_at: '2026-03-01'
    }
  ]
  const ocrDocuments = [
    {
      filename: '2月20 武汉-上海.pdf',
      summary: '武汉至上海高铁票',
      document_fields: [
        { key: 'date', label: '日期', value: '2026-02-20' },
        { key: 'route', label: '行程', value: '武汉-上海' }
      ]
    },
    {
      filename: '2月23 上海-武汉.pdf',
      summary: '上海至武汉高铁票',
      document_fields: [
        { key: 'date', label: '日期', value: '2026-02-23' },
        { key: 'route', label: '行程', value: '上海-武汉' }
      ]
    }
  ]

  const match = resolveAiAttachmentAssociationMatch(claims, ocrDocuments)

  assert.equal(match.highConfidence, true)
  assert.equal(match.best.record.claimId, 'claim-wuhan-shanghai')
  assert.match(match.best.reasons.join('、'), /日期/)
  assert.match(match.best.reasons.join('、'), /地点|行程/)

  const message = buildAiAttachmentAssociationMessage({
    match,
    fileNames: ocrDocuments.map((item) => item.filename),
    ocrDocuments
  })
  assert.match(message, /BX-20260220-001/)
  assert.match(message, /确认是否自动归集/)
  assert.match(message, /ai-trusted-html:start/)
  assert.ok(message.indexOf('票据识别结果') < message.indexOf('可能关联单据'))

  const html = renderAiConversationHtml(message)
  assert.match(html, /ai-ocr-recognition-card/)
  assert.match(html, /ai-attachment-association-card/)
  assert.match(html, /可能关联单据/)
  assert.doesNotMatch(html, /26429165800002785705/)

  const actions = buildAiAttachmentAssociationActions(match, 'assoc-1', { includeOcrDetails: true })
  assert.equal(actions[0].action_type, 'show_ai_attachment_ocr_details')
  assert.equal(findAction(actions, 'confirm_ai_attachment_association').payload.association_id, 'assoc-1')
  assert.ok(findAction(actions, 'open_application_detail'))
})

test('自动归集消息展示票面 OCR 关键字段', () => {
  const match = resolveAiAttachmentAssociationMatch([
    {
      id: 'claim-wuhan-shanghai',
      claim_no: 'BX-20260220-001',
      expense_type: 'travel',
      status: 'draft',
      reason: '辅助国网仿生产服务器部署，武汉往返上海',
      location: '上海',
      occurred_at: '2026-02-20'
    }
  ], [
    {
      filename: '2月20 武汉-上海.pdf',
      summary: '电子发票（铁路电子客票） 武汉-上海 票价 354元',
      document_fields: [
        { key: 'amount', label: '金额', value: '354元' },
        { key: 'departed_at', label: '列车出发时间', value: '2026-02-20 07:55' },
        { key: 'route', label: '行程', value: '武汉-上海' }
      ]
    }
  ])

  const message = buildAiAttachmentAssociationMessage({
    match,
    fileNames: ['2月20 武汉-上海.pdf'],
    ocrDocuments: [
      {
        filename: '2月20 武汉-上海.pdf',
        summary: '电子发票（铁路电子客票） 武汉-上海 票价 354元',
        document_fields: [
          { key: 'amount', label: '金额', value: '354元' },
          { key: 'departed_at', label: '列车出发时间', value: '2026-02-20 07:55' },
          { key: 'route', label: '行程', value: '武汉-上海' }
        ]
      }
    ]
  })
  const html = renderAiConversationHtml(message)

  assert.ok(message.indexOf('票据识别结果') < message.indexOf('可能关联单据'))
  assert.match(message, /票面识别/)
  assert.match(html, /ai-ocr-recognition-card/)
  assert.match(html, /金额：354元/)
  assert.match(html, /列车出发时间：2026-02-20 07:55/)
  assert.match(html, /行程：武汉-上海/)
})

test('自动归集卡片不把票据数字残片当成单据事项', () => {
  const dirtyReason = ':26429165800002785705; :2026; 05'
  const ocrDocuments = [
    {
      filename: '2月20 武汉-上海.pdf',
      summary: '电子发票（铁路电子客票） 武汉-上海 票价 354元',
      document_fields: [
        { key: 'invoice_number', label: '', value: '26429165800002785705' },
        { key: 'year', label: '', value: '2026' },
        { key: 'amount', label: '金额', value: '354元' },
        { key: 'route', label: '行程', value: '武汉-上海' }
      ]
    }
  ]
  const match = resolveAiAttachmentAssociationMatch([
    {
      id: 'claim-dirty-reason',
      claim_no: 'R74CB7C2R',
      expense_type: 'travel',
      status: 'draft',
      reason: dirtyReason,
      location: '上海',
      occurred_at: '2026-02-20'
    }
  ], ocrDocuments)

  const message = buildAiAttachmentAssociationMessage({
    match,
    fileNames: ['2月20 武汉-上海.pdf'],
    ocrDocuments
  })
  const html = renderAiConversationHtml(message)

  assert.match(html, /R74CB7C2R/)
  assert.match(html, /ai-ocr-recognition-card/)
  assert.match(html, /票面识别/)
  assert.match(html, /金额：354元/)
  assert.match(html, /行程：武汉-上海/)
  assert.doesNotMatch(html, /单据事项/)
  assert.doesNotMatch(html, /26429165800002785705/)
  assert.doesNotMatch(html, /:2026/)
})

test('没有可关联草稿时给出清晰提示', () => {
  const match = resolveAiAttachmentAssociationMatch([
    {
      id: 'claim-submitted',
      claim_no: 'BX-20260220-001',
      status: 'submitted',
      reason: '已提交报销单',
      location: '上海',
      occurred_at: '2026-02-20'
    }
  ], [
    {
      filename: '2月20 武汉-上海.pdf',
      summary: '武汉至上海高铁票',
      document_fields: [
        { key: 'date', label: '日期', value: '2026-02-20' },
        { key: 'route', label: '行程', value: '武汉-上海' }
      ]
    }
  ])

  assert.equal(match.highConfidence, false)
  assert.equal(match.rankedRecords.length, 0)

  const message = buildAiAttachmentAssociationMessage({ match, fileNames: ['2月20 武汉-上海.pdf'] })
  assert.match(message, /没有查到可关联的报销草稿/)
})

test('自动归集结果用卡片告知上传结果', () => {
  const message = buildAiAttachmentAssociationResultMessage({
    claimNo: 'BX-20260220-001',
    uploadedCount: 2,
    skippedCount: 0,
    fileNames: ['2月20 武汉-上海.pdf', '2月23 上海-武汉.pdf']
  })
  const html = renderAiConversationHtml(message)

  assert.match(message, /已完成自动归集/)
  assert.match(html, /ai-attachment-association-card/)
  assert.match(html, /2 份/)
  assert.match(html, /BX-20260220-001/)
})

test('低置信候选也提供快捷确认关联动作', () => {
  const claims = [
    {
      id: 'claim-shanghai',
      claim_no: 'R74CB7C2R',
      expense_type: 'travel',
      status: 'draft',
      reason: '出差报销',
      location: '上海',
      occurred_at: '2026-05-18'
    }
  ]
  const ocrDocuments = [
    {
      filename: '2月20 武汉-上海.pdf',
      summary: 'G458 Wuhan Shanghaihongqiao',
      document_fields: [
        { key: 'route', label: '行程', value: 'Wuhan Shanghaihongqiao' }
      ]
    }
  ]

  const match = resolveAiAttachmentAssociationMatch(claims, ocrDocuments)
  assert.equal(match.highConfidence, false)
  assert.equal(match.recommended.record.claimId, 'claim-shanghai')

  const message = buildAiAttachmentAssociationMessage({
    match,
    fileNames: ['2月20 武汉-上海.pdf'],
    ocrDocuments
  })
  const html = renderAiConversationHtml(message)
  assert.match(html, /候选单据待核对/)
  assert.match(html, /ai-attachment-association-card/)

  const actions = buildAiAttachmentAssociationActions(match, 'assoc-low-confidence', { includeOcrDetails: true })
  assert.equal(actions[0].action_type, 'show_ai_attachment_ocr_details')
  assert.equal(findAction(actions, 'confirm_ai_attachment_association').payload.claim_no, 'R74CB7C2R')
})

test('旧版纯文本关联消息也渲染为卡片', () => {
  const legacyMessage = [
    '### 我已先识别票据，并匹配到最可能的报销单',
    '',
    '本次附件：1 份（2月20 武汉-上海.pdf）',
    '',
    '识别摘要：2月20 武汉-上海.pdf：G458 Wuhan Shanghaihongqiao',
    '',
    '推荐关联：R74CB7C2R',
    '',
    '单据事项：上海差旅报销',
    '',
    '匹配依据：地点或行程包含 上海；当前单据仍是可归集草稿',
    '',
    '你可以直接点下方“查看匹配单据”核对详情，不需要再手动查找。'
  ].join('\n')

  const html = renderAiConversationHtml(legacyMessage)
  assert.match(html, /ai-attachment-association-card/)
  assert.match(html, /R74CB7C2R/)
  assert.doesNotMatch(html, /\*\*R74CB7C2R\*\*/)
  assert.doesNotMatch(html, /ai-html-title/)
})
