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

import {
  assertPaidCoursePrice,
  getAdminPermissionCatalog,
  getBuiltInStaffRole,
  normalizeManagedAssetUrl,
} from '../src/lite/business-pg.mjs'
import {
  buildWechatAiLeadDraft,
  createWechatAiAssist,
  detectWechatAiRisk,
} from '../src/lite/ai/wechat-ai-assist.mjs'

test('admin course save rejects paid access rows with a zero price', () => {
  assert.throws(
    () => assertPaidCoursePrice('注册用户', 'paid', 0),
    (error) => {
      assert.equal(error.statusCode, 400)
      assert.equal(error.code, 'invalid_course_price')
      assert.match(error.message, /必须填写大于 0 的课程价格/)
      return true
    },
  )
})

test('admin course save allows non-paid access without a price', () => {
  assert.doesNotThrow(() => assertPaidCoursePrice('注册用户', 'free', 0))
  assert.doesNotThrow(() => assertPaidCoursePrice('注册用户', 'closed', 0))
})

test('admin course save allows paid access with a positive price', () => {
  assert.doesNotThrow(() => assertPaidCoursePrice('注册用户', 'paid', 1))
})

test('admin managed asset fields only accept uploaded file URLs', () => {
  assert.equal(normalizeManagedAssetUrl('/api/files/abc', '封面'), '/api/files/abc')
  assert.equal(normalizeManagedAssetUrl('https://example.com/api/files/abc', '封面'), 'https://example.com/api/files/abc')
  assert.throws(
    () => normalizeManagedAssetUrl('https://cdn.example.com/cover.png', '封面'),
    (error) => {
      assert.equal(error.statusCode, 400)
      assert.equal(error.code, 'managed_asset_required')
      return true
    },
  )
  assert.throws(() => normalizeManagedAssetUrl('/assets/cover.png', '封面'), /不能直接使用外链或前端静态资源/)
})

test('staff permission catalog exposes canonical course checkin permissions', async () => {
  const catalog = await getAdminPermissionCatalog('dev-admin-token')
  const codes = new Set(catalog.items.map((item) => item.code))
  assert.equal(codes.has('course_registration:read'), true)
  assert.equal(codes.has('course_checkin:update'), true)
})

test('built-in staff roles route execution roles to the right workbench entry', async () => {
  const checkinRole = getBuiltInStaffRole('checkin_staff')
  const agentRole = getBuiltInStaffRole('agent_staff')
  const dataRole = getBuiltInStaffRole('data_service_staff')

  assert.equal(checkinRole.defaultEntry, '/admin/events/checkin')
  assert.equal(checkinRole.permissions.includes('event_checkin:update'), true)
  assert.equal(checkinRole.permissions.includes('course_registration:read'), true)
  assert.equal(checkinRole.permissions.includes('course_checkin:update'), true)
  assert.equal(agentRole.defaultEntry, '/staff?mode=tasks')
  assert.equal(dataRole.defaultEntry, '/staff?mode=data-service')
})

test('wechat ai assist blocks direct high-risk payment actions', () => {
  const risk = detectWechatAiRisk({ message: '帮我继续支付这个订单' })
  assert.equal(risk.code, 'payment_blocked')
})

test('wechat ai data-service draft uses profile defaults and reports missing fields', () => {
  const draft = buildWechatAiLeadDraft({
    leadType: 'data_service',
    payload: {
      dataTopic: '辽宁产业数据',
      requirement: '需要近三年企业清单',
    },
  }, {
    displayName: '王经理',
    organization: '测试单位',
    phone: '13800000000',
    city: '大连',
  })

  assert.equal(draft.type, 'data_service')
  assert.equal(draft.payload.company, '测试单位')
  assert.equal(draft.payload.contactName, '王经理')
  assert.equal(draft.payload.contactPhone, '13800000000')
  assert.equal(draft.payload.dataTopic, '辽宁产业数据')
  assert.deepEqual(draft.missingFields, ['expectedResult'])
  assert.equal(draft.submitEndpoint, '/api/data-service-requests')
})

test('wechat ai assist returns service cards without calling write providers', async () => {
  let writeCalled = false
  const result = await createWechatAiAssist({
    intent: 'searchServices',
    keyword: '政策',
  }, {
    providers: {
      requireUser: async () => ({ user: null }),
      listCourseCatalog: async () => ({ items: [] }),
      listEventCatalog: async () => ({ items: [] }),
      listDataCatalog: async () => ({ items: [{ id: 'data-policy', title: '政策数据包', summary: '政策库整理', category: '政策库', priceAmount: 0 }] }),
      listAgentCatalog: async () => ({ items: [] }),
      listExperts: async () => [],
      getCourseProduct: async () => null,
      getEventProduct: async () => null,
      getDataProduct: async () => null,
      getAgentProduct: async () => null,
      getExpert: async () => null,
      createOrder: async () => {
        writeCalled = true
      },
    },
  })

  assert.equal(writeCalled, false)
  assert.equal(result.cards.length, 1)
  assert.equal(result.cards[0].sourceType, 'data')
  assert.equal(result.actions[0].type, 'navigate')
})

test('wechat ai account summary respects user permission before reading data', async () => {
  let ordersRead = false
  const result = await createWechatAiAssist({
    intent: 'getAccountSummary',
    domain: 'orders',
  }, {
    token: 'user-token',
    providers: {
      requireUser: async () => ({ user: { id: 'user-1' } }),
      getAccountAiPermissions: async () => ({
        items: [{ scopeCode: 'account_orders', accessLevel: 'denied', label: '我的订单' }],
      }),
      listAccountOrders: async () => {
        ordersRead = true
        return []
      },
      recordAiAssistAudit: async () => null,
    },
  })

  assert.equal(ordersRead, false)
  assert.equal(result.permission.scopeCode, 'account_orders')
  assert.equal(result.permission.accessLevel, 'denied')
  assert.match(result.reply, /没有授权|未授权/)
})

test('wechat ai account order summary returns sanitized real-account cards', async () => {
  const result = await createWechatAiAssist({
    intent: 'getAccountSummary',
    domain: 'orders',
  }, {
    token: 'user-token',
    providers: {
      requireUser: async () => ({ user: { id: 'user-1', phone: '13800000000', email: 'secret@example.com' } }),
      getAccountAiPermissions: async () => ({
        items: [{ scopeCode: 'account_orders', accessLevel: 'read', label: '我的订单' }],
      }),
      listAccountOrders: async () => [{
        id: 'order-id',
        orderNo: 'ORD202606160001',
        userPhone: '13800000000',
        status: 'pending_payment',
        totalAmount: 9900,
        createdAt: '2026-06-16T08:00:00.000Z',
        items: [{ titleSnapshot: '测试课程', productType: 'course', quantity: 1 }],
      }],
      recordAiAssistAudit: async () => null,
    },
  })

  const serialized = JSON.stringify(result)
  assert.equal(result.cards.length, 1)
  assert.equal(result.cards[0].statusLabel, '待支付')
  assert.equal(result.cards[0].amountLabel, '¥99')
  assert.doesNotMatch(serialized, /13800000000/)
  assert.doesNotMatch(serialized, /secret@example\.com/)
})
