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

import {
  buildAiDocumentQueryConditionSummary,
  buildAiDocumentQueryMessage,
  filterAiDocumentQueryRecords,
  mergeAiDocumentQueryPayloads,
  resolveAiDocumentQueryIntent
} from '../src/utils/aiDocumentQueryModel.js'
import { renderAiConversationHtml } from '../src/utils/aiConversationHtmlRenderer.js'
import { resolveWorkbenchIntentActionRoute } from '../src/composables/workbenchAiMode/workbenchIntentActionPolicy.js'
import { resolveWorkbenchIntentFrame } from '../src/composables/workbenchAiMode/workbenchIntentFrameModel.js'

const today = '2026-06-20'

const claims = [
  {
    id: 'claim-1',
    claim_no: 'CL-20260221001',
    document_type_code: 'reimbursement',
    expense_type: 'travel',
    status: 'submitted',
    reason: '上海出差报销',
    employee_name: '曹小筑',
    department_name: '交付部',
    location: '上海',
    occurred_at: '2026-02-21T09:00:00Z',
    updated_at: '2026-02-22T10:00:00Z',
    amount: 1200
  },
  {
    id: 'app-1',
    claim_no: 'AP-20260220001',
    document_type_code: 'application',
    expense_type: 'travel_application',
    status: 'approved',
    reason: '辅助国网仿生产服务器部署',
    employee_name: '曹小筑',
    department_name: '交付部',
    location: '上海',
    occurred_at: '2026-02-20T09:00:00Z',
    updated_at: '2026-02-20T10:00:00Z',
    amount: 3000
  },
  {
    id: 'claim-2',
    claim_no: 'CL-20260305001',
    document_type_code: 'reimbursement',
    expense_type: 'office',
    status: 'draft',
    reason: '办公用品采购',
    occurred_at: '2026-03-05T09:00:00Z',
    amount: 500
  }
]

test('AI document query intent detects my document list questions', () => {
  const intent = resolveAiDocumentQueryIntent('我现在有哪些单据？', { today })

  assert.equal(intent?.source, 'accessible')
  assert.equal(intent?.documentType, 'all')
  assert.equal(intent?.sourceLabel, '我可见的单据')
})

test('AI document query intent detects approval document questions', () => {
  const intent = resolveAiDocumentQueryIntent('我有哪些审核单', { today })

  assert.equal(intent?.source, 'approval')
  assert.equal(intent?.sourceLabel, '待我审核的单据')
})

test('AI document query intent detects short approval workbench commands', () => {
  const reviewIntent = resolveAiDocumentQueryIntent('我要审核', { today })
  const todoIntent = resolveAiDocumentQueryIntent('待办审批', { today })

  assert.equal(reviewIntent?.source, 'approval')
  assert.equal(reviewIntent?.documentType, 'all')
  assert.equal(reviewIntent?.sourceLabel, '待我审核的单据')
  assert.equal(todoIntent?.source, 'approval')
  assert.equal(todoIntent?.sourceLabel, '待我审核的单据')
})

test('AI document query intent keeps approval policy questions out of document query', () => {
  assert.equal(resolveAiDocumentQueryIntent('审批规则怎么走', { today }), null)
})

test('AI document query keeps explicit own-document scope separate from accessible documents', () => {
  const intent = resolveAiDocumentQueryIntent('我名下有哪些单据？', { today })

  assert.equal(intent?.source, 'mine')
  assert.equal(intent?.sourceLabel, '我的单据')
})

test('AI document query merges own and approval records for generic document list questions', () => {
  const intent = resolveAiDocumentQueryIntent('我现在有哪些单据？', { today })
  const approvalClaims = [{
    id: 'approval-1',
    claim_no: 'CL-APPROVAL-001',
    document_type_code: 'reimbursement',
    expense_type: 'meeting',
    status: 'pending',
    approval_stage: '直属领导审批',
    reason: '待我审核的会议费',
    employee_name: '李文静',
    department_name: '市场部',
    occurred_at: '2026-02-22T09:00:00Z',
    amount: 880
  }]
  const merged = mergeAiDocumentQueryPayloads(claims, { items: approvalClaims, querySource: 'approval' }, [claims[0]])
  const records = filterAiDocumentQueryRecords(merged, intent)

  assert.equal(intent?.source, 'accessible')
  assert.deepEqual(
    records.map((record) => record.documentNo),
    ['CL-20260305001', 'CL-APPROVAL-001', 'CL-20260221001', 'AP-20260220001']
  )
})

test('AI document query filters by month and document type', () => {
  const intent = resolveAiDocumentQueryIntent('我2月有哪些申请单？', { today })
  const records = filterAiDocumentQueryRecords(claims, intent)

  assert.equal(intent?.documentType, 'application')
  assert.equal(intent?.timeRange?.start, '2026-02-01')
  assert.equal(intent?.timeRange?.end, '2026-02-28')
  assert.deepEqual(records.map((record) => record.documentNo), ['AP-20260220001'])
})

test('AI document query filters by single day and document type', () => {
  const intent = resolveAiDocumentQueryIntent('2月20日发生的申请单有哪些？', { today })
  const records = filterAiDocumentQueryRecords(claims, intent)

  assert.equal(intent?.timeRange?.start, '2026-02-20')
  assert.equal(intent?.timeRange?.end, '2026-02-20')
  assert.deepEqual(records.map((record) => record.documentNo), ['AP-20260220001'])
})

test('AI document query combines natural-language filters', () => {
  const intent = resolveAiDocumentQueryIntent('查一下2月审批中的差旅报销单，金额超过1000，上海相关的单据有哪些？', { today })
  const records = filterAiDocumentQueryRecords(claims, intent)

  assert.equal(intent?.documentType, 'reimbursement')
  assert.equal(intent?.timeRange?.label, '2026年2月')
  assert.equal(intent?.statusFilter?.label, '审批中')
  assert.equal(intent?.expenseTypeFilter?.label, '差旅费')
  assert.equal(intent?.keywordFilter?.label, '上海')
  assert.equal(intent?.amountFilter?.min, 1000)
  assert.deepEqual(records.map((record) => record.documentNo), ['CL-20260221001'])
  assert.match(buildAiDocumentQueryConditionSummary(intent), /状态：审批中/)
  assert.match(buildAiDocumentQueryConditionSummary(intent), /费用类型：差旅费/)
  assert.match(buildAiDocumentQueryConditionSummary(intent), /关键词：上海/)
  assert.match(buildAiDocumentQueryConditionSummary(intent), /金额：不少于1000元/)
})

test('AI document query filters draft candidates by relative day', () => {
  const intent = resolveAiDocumentQueryIntent('我的 3天前 草稿单据', { today: '2026-06-24' })
  const records = filterAiDocumentQueryRecords([
    {
      id: 'draft-3-days-ago',
      claim_no: 'AP-20260621001',
      document_type_code: 'application',
      status: 'draft',
      reason: '三天前保存的申请草稿',
      created_at: '2026-06-21T09:00:00Z'
    },
    {
      id: 'draft-yesterday',
      claim_no: 'AP-20260623001',
      document_type_code: 'application',
      status: 'draft',
      reason: '昨天保存的申请草稿',
      created_at: '2026-06-23T09:00:00Z'
    }
  ], intent)

  assert.equal(intent?.source, 'mine')
  assert.equal(intent?.statusFilter?.label, '草稿')
  assert.equal(intent?.timeRange?.start, '2026-06-21')
  assert.equal(intent?.timeRange?.end, '2026-06-21')
  assert.deepEqual(records.map((record) => record.documentNo), ['AP-20260621001'])
})

test('AI document query filters no-risk approval application candidates', () => {
  const intent = resolveAiDocumentQueryIntent('待我审核 无风险 申请单', { today })
  const payload = [{
    id: 'approval-no-risk',
    claim_no: 'AP-NORISK-001',
    document_type_code: 'application',
    expense_type: 'travel_application',
    status: 'submitted',
    reason: '合规差旅申请',
    created_at: '2026-06-20T09:00:00Z',
    risk_flags_json: [],
    risk_summary: '无'
  }, {
    id: 'approval-high-risk',
    claim_no: 'AP-RISK-001',
    document_type_code: 'application',
    expense_type: 'travel_application',
    status: 'submitted',
    reason: '住宿超标申请',
    created_at: '2026-06-20T10:00:00Z',
    risk_flags_json: [{ severity: 'high', summary: '住宿超标' }],
    risk_summary: '住宿超标'
  }]
  const records = filterAiDocumentQueryRecords({ items: payload, querySource: 'approval' }, intent)

  assert.equal(intent?.source, 'approval')
  assert.equal(intent?.documentType, 'application')
  assert.equal(intent?.riskFilter?.level, 'none')
  assert.match(buildAiDocumentQueryConditionSummary(intent), /风险：无风险/)
  assert.deepEqual(records.map((record) => record.documentNo), ['AP-NORISK-001'])
})

test('AI document query excludes undated rows when a time condition is present', () => {
  const intent = resolveAiDocumentQueryIntent('我2月有哪些单据？', { today })
  const records = filterAiDocumentQueryRecords([
    ...claims,
    {
      id: 'no-date',
      claim_no: 'CL-NO-DATE',
      document_type_code: 'reimbursement',
      expense_type: 'travel',
      status: 'submitted',
      reason: '缺少业务日期的单据',
      amount: 800
    }
  ], intent)

  assert.deepEqual(records.map((record) => record.documentNo), ['CL-20260221001', 'AP-20260220001'])
})

test('AI document query message renders html document cards with detail actions', () => {
  const intent = resolveAiDocumentQueryIntent('我2月有哪些单据？', { today })
  const message = buildAiDocumentQueryMessage(intent, claims)

  assert.match(message, /### 已查询到相关单据/)
  assert.match(message, /<!-- ai-trusted-html:start -->/)
  assert.match(message, /<section class="ai-document-query-summary" aria-label="单据查询范围">/)
  assert.match(message, /<span class="ai-document-query-summary__label">查询范围<\/span>/)
  assert.match(message, /<strong class="ai-document-query-summary__scope">/)
  assert.match(message, /<span class="ai-document-query-summary__count">/)
  assert.match(message, /<section class="ai-document-card-list" aria-label="单据查询结果">/)
  // 申请单 app-1 状态为 approved → is-success 语义类
  assert.match(message, /<article class="ai-document-card ai-document-card--application is-success" aria-label="单据详情">/)
  assert.match(message, /<header class="ai-document-card__head">/)
  assert.match(message, /<span class="ai-document-card__status">已审批<\/span>/)
  assert.match(message, /<strong class="ai-document-card__reason">差旅费用申请<\/strong>/)
  assert.match(message, /<div class="ai-document-card__summary">/)
  assert.match(message, /<div class="ai-document-card__details">/)
  assert.match(message, /<span class="ai-document-card__label">日期<\/span>/)
  assert.match(message, /2026-02-20/)
  assert.match(message, /<span class="ai-document-card__label">预计金额<\/span>/)
  assert.match(message, /<strong class="ai-document-card__value ai-document-card__amount">¥3,000\.00<\/strong>/)
  assert.doesNotMatch(message, /<span class="ai-document-card__label">当前节点<\/span>/)
  assert.match(message, /<span class="ai-document-card__label">单据类型<\/span>/)
  assert.match(message, /<strong class="ai-document-card__value">申请单 · 差旅费用申请<\/strong>/)
  assert.match(message, /<span class="ai-document-card__label">地点<\/span>/)
  assert.match(message, /上海/)
  assert.match(message, /<span class="ai-document-card__label">事由<\/span>/)
  assert.match(message, /辅助国网仿生产服务器部署/)
  assert.match(message, /<span class="ai-document-card__label">申请人<\/span>/)
  assert.match(message, /<strong class="ai-document-card__value">曹小筑 · 交付部<\/strong>/)
  assert.match(message, /<strong class="ai-document-card__value ai-document-card__number">AP-20260220001<\/strong>/)
  assert.match(message, /<div class="ai-document-card__field ai-document-card__field--action">/)
  assert.doesNotMatch(message, /ai-document-card__meta/)
  assert.doesNotMatch(message, /ai-document-card__meta-item/)
  assert.match(message, /href="#ai-open-document-detail:claim_id%3Dapp-1%26claim_no%3DAP-20260220001"/)
  // 报销单 claim-1 状态为 submitted → is-pending 语义类
  assert.match(message, /<article class="ai-document-card ai-document-card--reimbursement is-pending" aria-label="单据详情">/)
  assert.match(message, /<span class="ai-document-card__status">审批中<\/span>/)
  assert.match(message, /href="#ai-open-document-detail:claim_id%3Dclaim-1%26claim_no%3DCL-20260221001"/)
  assert.doesNotMatch(message, />submitted</)
  assert.doesNotMatch(message, /\| 单据编号 \|/)
  assert.doesNotMatch(message, /^> /m)
  assert.doesNotMatch(message, /\*\*查询范围\*\*/)
})

test('AI document query highlights approval-task cards and shows pending review status', () => {
  const intent = resolveAiDocumentQueryIntent('我有哪些审核单', { today })
  const message = buildAiDocumentQueryMessage(intent, [{
    id: 'approval-1',
    claim_no: 'AP-APPROVAL-001',
    document_type_code: 'application',
    expense_type: 'travel_application',
    status: 'submitted',
    approval_stage: '直属领导审批',
    reason: '参加相关残联会议',
    employee_name: '曹笑竹',
    department_name: '技术部',
    location: '上海',
    occurred_at: '2026-02-20T09:00:00Z',
    amount: 2120
  }])

  assert.match(message, /ai-document-card--application ai-document-card--approval-task is-pending/)
  assert.match(message, /<span class="ai-document-card__status">待审批<\/span>/)
  assert.match(message, /<span class="ai-document-card__label">预计金额<\/span>/)
  assert.match(message, /<strong class="ai-document-card__value ai-document-card__amount">¥2,120\.00<\/strong>/)
  assert.doesNotMatch(message, /<span class="ai-document-card__label">当前节点<\/span>/)
  assert.match(message, /<span class="ai-document-card__label">单据类型<\/span>/)
  assert.match(message, /<strong class="ai-document-card__value">申请单 · 差旅费用申请<\/strong>/)
  assert.match(message, /href="#ai-open-document-detail:claim_id%3Dapproval-1%26claim_no%3DAP-APPROVAL-001"/)
})

test('AI document query html cards render as trusted card markup', () => {
  const intent = resolveAiDocumentQueryIntent('我2月有哪些单据？', { today })
  const rendered = renderAiConversationHtml(buildAiDocumentQueryMessage(intent, claims))

  assert.match(rendered, /<h3 class="ai-html-title">已查询到相关单据<\/h3>/)
  assert.match(rendered, /<section class="ai-document-query-summary" aria-label="单据查询范围">/)
  assert.match(rendered, /<section class="ai-document-card-list" aria-label="单据查询结果">/)
  assert.match(rendered, /<article class="ai-document-card ai-document-card--application is-success" aria-label="单据详情">/)
  assert.match(rendered, /class="ai-document-card__head"/)
  assert.match(rendered, /class="ai-document-card__details"/)
  assert.match(rendered, /class="ai-document-card__field"/)
  assert.match(rendered, /class="ai-document-card__label"/)
  assert.match(rendered, /class="ai-html-action-link ai-html-action-link-document ai-document-card__action"/)
  assert.match(rendered, /href="#ai-open-document-detail:claim_id%3Dclaim-1%26claim_no%3DCL-20260221001"/)
  assert.doesNotMatch(rendered, /ai-document-card__meta/)
  assert.doesNotMatch(rendered, /&lt;section class=&quot;ai-document-card-list/)
  assert.doesNotMatch(rendered, /<blockquote>/)
})

test('AI document query keeps high-risk command guidance in trusted rendered markup', () => {
  const frame = resolveWorkbenchIntentFrame('删除申请单草稿', { today: '2026-06-24' })
  const route = resolveWorkbenchIntentActionRoute(frame)
  const intent = resolveAiDocumentQueryIntent(route.queryPrompt, { today: '2026-06-24' })
  const rendered = renderAiConversationHtml(buildAiDocumentQueryMessage(intent, [{
    id: 'draft-application-1',
    claim_no: 'AP-DRAFT-001',
    document_type_code: 'application',
    expense_type: 'travel_application',
    status: 'draft',
    reason: '测试申请草稿',
    created_at: '2026-06-24T09:00:00Z'
  }], { commandFrame: frame }))

  assert.match(rendered, /<h3 class="ai-html-title">已查询到相关单据<\/h3>/)
  assert.match(rendered, /<section class="ai-document-command-guidance" aria-label="高风险操作提示">/)
  assert.match(rendered, /系统不会直接删除相关单据/)
  assert.match(rendered, /进入单据详情核对后再操作/)
  assert.match(rendered, /<section class="ai-document-card-list" aria-label="单据查询结果">/)
  assert.match(rendered, /进入详情确认删除/)
})

test('AI document query trusted html rejects unsafe card markup', () => {
  const rendered = renderAiConversationHtml([
    '### 查询结果',
    '',
    '<!-- ai-trusted-html:start -->',
    '<section class="ai-document-card-list" aria-label="单据查询结果" onclick="alert(1)">',
    '<article class="ai-document-card"><script>alert(1)</script></article>',
    '</section>',
    '<!-- ai-trusted-html:end -->'
  ].join('\n'))

  assert.match(rendered, /<h3 class="ai-html-title">查询结果<\/h3>/)
  assert.doesNotMatch(rendered, /ai-document-card-list/)
  assert.doesNotMatch(rendered, /<script>/)
  assert.doesNotMatch(rendered, /onclick=/)
})
