import assert from 'node:assert/strict'

import {
  AI_APPLICATION_ACTION_SAVE_DRAFT,
  AI_APPLICATION_ACTION_SUBMIT,
  forgetAiApplicationMemory,
  normalizeAiApplicationMemory,
  registerAiApplicationPreviewDecision,
  resolveAiApplicationLearningReceipts,
  runAiApplicationPreviewAction
} from '../src/services/aiApplicationPreviewActions.js'

async function testSubmitActionUsesFastPreviewEndpoint() {
  let capturedUrl = ''
  let capturedOptions = null

  global.fetch = async (url, options) => {
    capturedUrl = String(url)
    capturedOptions = options
    return {
      ok: true,
      async json() {
        return {
          status: 'succeeded',
          result: {
            draft_payload: {
              claim_id: 'claim-fast-submit',
              claim_no: 'AP-20260620-FAST',
              status: 'submitted',
              approval_stage: '直属领导审批'
            }
          }
        }
      }
    }
  }

  await runAiApplicationPreviewAction({
    actionType: AI_APPLICATION_ACTION_SUBMIT,
    applicationPreview: {
      decisionId: 'decision-fast-submit',
      fields: {
        applicationType: '差旅费用申请',
        time: '2026-07-01 至 2026-07-03',
        location: '北京',
        reason: '项目实施',
        days: '3天',
        transportMode: '火车',
        amount: '1000元'
      },
      aiDecisionFeedback: {
        schemaVersion: 1,
        changedFields: [
          {
            fieldKey: 'transportMode',
            suggestedValue: '飞机',
            finalValue: '火车'
          }
        ]
      }
    },
    currentUser: { username: 'zhangsan@example.com', name: '张三' },
    conversationId: 'conversation-fast-submit',
    requestId: 'action-fast-submit'
  })

  assert.equal(capturedUrl, '/api/v1/reimbursements/application-preview-action')
  assert.equal(capturedOptions.method, 'POST')
  const body = JSON.parse(capturedOptions.body)
  assert.equal(body.context_json.session_type, 'application')
  assert.equal(body.context_json.application_stage, 'expense_application')
  assert.equal(body.action_type, 'submit')
  assert.equal(body.decision_id, 'decision-fast-submit')
  assert.equal(body.request_id, 'action-fast-submit')
  assert.equal(body.context_json.application_preview.fields.transportMode, '火车')
  assert.deepEqual(body.context_json.application_preview.aiDecisionFeedback.changedFields, [
    {
      fieldKey: 'transportMode',
      suggestedValue: '飞机',
      finalValue: '火车'
    }
  ])
}

async function testSaveDraftActionUsesFastPreviewEndpoint() {
  let capturedUrl = ''
  let capturedOptions = null

  global.fetch = async (url, options) => {
    capturedUrl = String(url)
    capturedOptions = options
    return {
      ok: true,
      async json() {
        return {
          status: 'succeeded',
          result: {
            draft_payload: {
              claim_id: 'claim-fast-draft',
              claim_no: 'AP-20260620-DRAFT',
              status: 'draft',
              approval_stage: '待提交'
            }
          }
        }
      }
    }
  }

  await runAiApplicationPreviewAction({
    actionType: AI_APPLICATION_ACTION_SAVE_DRAFT,
    applicationPreview: { fields: { reason: '项目实施' } },
    currentUser: { username: 'zhangsan@example.com', name: '张三' }
  })

  assert.equal(capturedUrl, '/api/v1/reimbursements/application-preview-action')
  assert.equal(capturedOptions.method, 'POST')
  const body = JSON.parse(capturedOptions.body)
  assert.equal(body.context_json.application_action, 'save_draft')
  assert.equal(body.context_json.application_save_mode, true)
  assert.equal(body.context_json.application_stage, 'expense_application')
  assert.equal(body.action_type, 'save_draft')
  assert.equal('decision_id' in body, false)
  assert.equal('request_id' in body, false)
}

async function testRegistrationUsesServerCanonicalPreview() {
  let capturedUrl = ''
  let capturedOptions = null
  global.fetch = async (url, options) => {
    capturedUrl = String(url)
    capturedOptions = options
    return {
      ok: true,
      async json() {
        return {
          decision_id: 'decision-issued-1',
          decision_source: 'rule',
          expires_at: '2026-07-14T10:30:00Z',
          application_preview: {
            fields: {
              reason: '服务端规范事由',
              amount: '1800元'
            },
            memoryApplications: [{
              memoryId: 'memory-transport-1',
              fieldKey: 'transport_mode',
              value: '火车',
              status: 'active',
              evidenceCount: 4,
              approvedEvidenceCount: 3,
              scope_type: 'department',
              scope_id: 'department-shanghai-delivery',
              scope_label: '上海交付部',
              source: 'admin_managed_org',
              priority: 200,
              effective_confidence: 0.92,
              conflicts: [{ scope_type: 'user', reason: 'lower_priority' }],
              can_revoke: false,
              message: '根据历史申请偏好填入'
            }]
          }
        }
      }
    }
  }

  const preview = await registerAiApplicationPreviewDecision({
    applicationPreview: {
      fields: {
        reason: '客户端事由',
        location: '上海'
      }
    },
    conversationId: 'conversation-issued-1',
    message: '去上海做客户现场实施',
    requestId: 'preview-request-1'
  })

  assert.equal(capturedUrl, '/api/v1/reimbursements/application-previews')
  assert.equal(capturedOptions.method, 'POST')
  assert.deepEqual(JSON.parse(capturedOptions.body), {
    message: '去上海做客户现场实施',
    conversation_id: 'conversation-issued-1',
    request_id: 'preview-request-1'
  })
  assert.equal(preview.decisionId, 'decision-issued-1')
  assert.equal(preview.decisionSource, 'rule')
  assert.equal(preview.fields.reason, '服务端规范事由')
  assert.equal(preview.fields.location, '上海')
  assert.equal(preview.decisionTrackingStatus, 'registered')
  assert.deepEqual(preview.memoryApplications, [{
    memoryId: 'memory-transport-1',
    fieldKey: 'transport_mode',
    fieldLabel: '出行方式',
    value: '火车',
    status: 'applied',
    evidenceCount: 4,
    approvedEvidenceCount: 3,
    scopeType: 'department',
    scopeId: 'department-shanghai-delivery',
    scopeLabel: '上海交付部',
    source: 'admin_managed_org',
    priority: 200,
    effectiveConfidence: 0.92,
    conflicts: [{ scope_type: 'user', reason: 'lower_priority' }],
    canRevoke: false,
    message: '根据历史申请偏好填入'
  }])
}

async function testLearningReceiptNormalizationAndForgetEndpoint() {
  const receipts = resolveAiApplicationLearningReceipts({
    result: {
      learning_receipts: [{
        memory_id: 'memory-reason-1',
        field_key: 'reason',
        field_label: '申请事由',
        value: '客户现场实施',
        status: 'candidate',
        evidence_count: 2,
        approved_evidence_count: 1,
        message: '再确认一次后可形成稳定偏好'
      }]
    }
  })
  assert.deepEqual(receipts, [{
    memoryId: 'memory-reason-1',
    fieldKey: 'reason',
    fieldLabel: '申请事由',
    value: '客户现场实施',
    status: 'candidate',
    evidenceCount: 2,
    approvedEvidenceCount: 1,
    scopeType: 'user',
    scopeId: '',
    scopeLabel: '个人偏好',
    source: 'verified_user_history',
    priority: 100,
    effectiveConfidence: null,
    conflicts: [],
    canRevoke: true,
    message: '再确认一次后可形成稳定偏好'
  }])

  let capturedUrl = ''
  let capturedOptions = null
  global.fetch = async (url, options) => {
    capturedUrl = String(url)
    capturedOptions = options
    return {
      ok: true,
      async json() {
        return { status: 'forgotten' }
      }
    }
  }
  await forgetAiApplicationMemory('memory/reason 1')
  assert.equal(
    capturedUrl,
    '/api/v1/expense-application-memories/memory%2Freason%201'
  )
  assert.equal(capturedOptions.method, 'DELETE')
}

function testHierarchicalMemoryNormalizationKeepsCompatibilityAndPermissions() {
  const enterpriseMemory = normalizeAiApplicationMemory({
    memory_id: 'memory-enterprise-transport',
    field_key: 'transport_mode',
    value: '火车',
    status: 'applied',
    scope_type: 'enterprise',
    scope_id: 'tenant-acme',
    scope_label: '企业统一制度',
    source: 'admin_managed_org',
    priority: '300',
    effective_confidence: '0.88',
    conflicts: [{ scope_type: 'department', reason: 'lower_priority' }],
    can_revoke: false
  })
  assert.deepEqual(enterpriseMemory, {
    memoryId: 'memory-enterprise-transport',
    fieldKey: 'transport_mode',
    fieldLabel: '出行方式',
    value: '火车',
    status: 'applied',
    evidenceCount: 0,
    approvedEvidenceCount: 0,
    scopeType: 'enterprise',
    scopeId: 'tenant-acme',
    scopeLabel: '企业统一制度',
    source: 'admin_managed_org',
    priority: 300,
    effectiveConfidence: 0.88,
    conflicts: [{ scope_type: 'department', reason: 'lower_priority' }],
    canRevoke: false,
    message: ''
  })

  const legacyPersonalMemory = normalizeAiApplicationMemory({
    memoryId: 'memory-legacy-user',
    fieldKey: 'transport_mode',
    value: '飞机',
    status: 'active'
  })
  assert.equal(legacyPersonalMemory.scopeType, 'user')
  assert.equal(legacyPersonalMemory.source, 'verified_user_history')
  assert.equal(legacyPersonalMemory.canRevoke, true)
  assert.equal(legacyPersonalMemory.status, 'applied')
}

async function testEditDraftActionCarriesClaimAndEditableFields() {
  let capturedOptions = null

  global.fetch = async (_url, options) => {
    capturedOptions = options
    return {
      ok: true,
      async json() {
        return {
          status: 'succeeded',
          result: {
            draft_payload: {
              claim_id: 'claim-edit-application',
              claim_no: 'AP-20260620-EDIT',
              status: 'draft',
              approval_stage: '待提交'
            }
          }
        }
      }
    }
  }

  await runAiApplicationPreviewAction({
    actionType: AI_APPLICATION_ACTION_SAVE_DRAFT,
    applicationPreview: {
      applicationEditMode: true,
      editableFields: ['reason', 'time', 'location', 'transportMode'],
      fields: {
        applicationType: '差旅费用申请',
        time: '2026-07-01 至 2026-07-03',
        location: '北京',
        reason: '项目实施',
        days: '3天',
        transportMode: '火车',
        amount: '1000元'
      }
    },
    currentUser: { username: 'zhangsan@example.com', name: '张三' },
    draftPayload: {
      claim_id: 'claim-edit-application',
      claim_no: 'AP-20260620-EDIT',
      status: 'returned'
    }
  })

  const body = JSON.parse(capturedOptions.body)
  assert.equal(body.context_json.application_edit_claim_id, 'claim-edit-application')
  assert.equal(body.context_json.application_edit_mode, true)
  assert.deepEqual(body.context_json.application_editable_fields, ['reason', 'time', 'location', 'transportMode'])
}

async function testApplicationActionSourceCanBeConfiguredWithoutChangingWorkbenchDefaults() {
  const requests = []
  global.fetch = async (_url, options) => {
    requests.push(JSON.parse(options.body))
    return {
      ok: true,
      async json() {
        return { status: 'succeeded', result: {} }
      }
    }
  }

  await runAiApplicationPreviewAction({
    actionType: AI_APPLICATION_ACTION_SAVE_DRAFT,
    applicationPreview: { fields: { reason: '默认工作台来源' } }
  })
  await runAiApplicationPreviewAction({
    actionType: AI_APPLICATION_ACTION_SAVE_DRAFT,
    applicationPreview: { fields: { reason: '小财管家来源' } },
    entrySource: 'application',
    source: 'financial_assistant',
    requestSource: 'assistant_preview_action'
  })

  assert.equal(requests[0].source, 'user_message')
  assert.equal(requests[0].context_json.entry_source, 'workbench_ai_inline')
  assert.equal(requests[0].context_json.source, 'workbench')
  assert.equal(requests[1].source, 'assistant_preview_action')
  assert.equal(requests[1].context_json.entry_source, 'application')
  assert.equal(requests[1].context_json.source, 'financial_assistant')
}

async function run() {
  await testSubmitActionUsesFastPreviewEndpoint()
  await testSaveDraftActionUsesFastPreviewEndpoint()
  await testRegistrationUsesServerCanonicalPreview()
  await testLearningReceiptNormalizationAndForgetEndpoint()
  testHierarchicalMemoryNormalizationKeepsCompatibilityAndPermissions()
  await testEditDraftActionCarriesClaimAndEditableFields()
  await testApplicationActionSourceCanBeConfiguredWithoutChangingWorkbenchDefaults()
  console.log('ai-application-preview-actions tests passed')
}

run().catch((error) => {
  console.error(error)
  process.exit(1)
})
