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

import { runtimeConfig } from '../../config/runtime.js'
import {
  buildWebhookEventInput,
  executeAgisoTradeWebhookWithDeps,
  parseAgisoTradeRequest,
  resolveAgisoTradeIgnoreReason,
  shouldEnrichAgisoXianyuTrade,
  verifyAgisoSignatureWithSecret,
} from './webhook-service.js'

function createParsedTrade(patch = {}) {
  return {
    provider: 'agiso',
    platform: 'xianyu',
    platformRaw: 'xianyu',
    eventType: 'payment_success',
    eventKey: 'agiso:xianyu:shop-9:4502259793206016214:payment_success:1713097840',
    signatureValid: true,
    platformOrderId: '4502259793206016214',
    shopId: 'shop-9',
    shopName: '咸鱼店铺',
    shopIdAliases: ['shop-9'],
    orderStatus: 'paid',
    payStatus: 'paid',
    buyerId: 'buyer-1',
    buyerName: '测试买家',
    receiverContact: '',
    totalAmount: 2550,
    currency: 'CNY',
    paidAt: '2026-04-14T12:30:40.000Z',
    rawPayload: {},
    items: [
      {
        skuCode: 'dnf-cdk-a',
        skuName: 'DNF礼包',
        quantity: 1,
        spec: { title: 'DNF礼包' },
      },
    ],
    ...patch,
  }
}

test('parseAgisoTradeRequest maps Agiso payment_success webhook into stable order fields', () => {
  const rawJson = '{"biz_order_id":4502259793206016214,"seller_id":"shop-9","seller_nick":"咸鱼店铺","buyer_id":"buyer-1","buyer_name":"测试买家","pay_time":"2026-04-14 20:30:40","total_fee":"25.50","currency":"CNY","items":[{"item_id":978102431355,"goods_name":"DNF礼包","quantity":2,"sku":"dnf-cdk-a|商品名称:DNF礼包"}]}'
  const timestamp = '1713097840'
  const appSecret = String(runtimeConfig.platforms?.agiso?.appSecret || '').trim()
  const sign = appSecret
    ? crypto.createHash('md5').update(`${appSecret}json${rawJson}timestamp${timestamp}${appSecret}`, 'utf8').digest('hex')
    : ''

  const parsed = parseAgisoTradeRequest({
    query: {
      aopic: '1',
      timestamp,
      sign,
    },
    body: {
      json: rawJson,
      fromPlatform: 'xianyu',
    },
  })

  assert.equal(parsed.provider, 'agiso')
  assert.equal(parsed.platform, 'xianyu')
  assert.equal(parsed.eventType, 'payment_success')
  assert.equal(parsed.signatureValid, true)
  assert.equal(parsed.platformOrderId, '4502259793206016214')
  assert.equal(parsed.shopId, 'shop-9')
  assert.equal(parsed.shopName, '咸鱼店铺')
  assert.equal(parsed.payStatus, 'paid')
  assert.equal(parsed.orderStatus, 'paid')
  assert.equal(parsed.totalAmount, 2550)
  assert.equal(parsed.items.length, 1)
  assert.equal(parsed.items[0]?.skuCode, 'dnf-cdk-a')
  assert.equal(parsed.items[0]?.quantity, 2)
})

test('shouldEnrichAgisoXianyuTrade only enriches when xianyu trade fields are incomplete', () => {
  assert.equal(shouldEnrichAgisoXianyuTrade({
    provider: 'agiso',
    platform: 'xianyu',
    totalAmount: 0,
    buyerName: '',
    shopName: '',
    items: [],
  }), true)

  assert.equal(shouldEnrichAgisoXianyuTrade({
    provider: 'agiso',
    platform: 'xianyu',
    totalAmount: 2550,
    buyerName: '测试买家',
    shopName: '咸鱼店铺',
    items: [
      {
        skuCode: 'dnf-cdk-a',
        spec: {
          title: 'DNF礼包',
        },
      },
    ],
  }), false)

  assert.equal(shouldEnrichAgisoXianyuTrade({
    provider: 'agiso',
    platform: 'taobao',
    totalAmount: 0,
    items: [],
  }), false)
})

test('parseAgisoTradeRequest maps buyer confirm goods webhook into ignored event type', () => {
  const rawJson = '{"biz_order_id":2701836516013026052,"seller_id":"shop-9","seller_nick":"大锤商行","buyer_id":"buyer-1","buyer_name":"测试买家","order_status":4,"Status":"TRADE_FINISHED","total_fee":"95.88","items":[{"item_id":978102431355,"goods_name":"DNF礼包","quantity":1,"sku":"dnf-cdk-a|商品名称:DNF礼包"}]}'
  const timestamp = '1776096226'
  const appSecret = String(runtimeConfig.platforms?.agiso?.appSecret || '').trim()
  const sign = appSecret
    ? crypto.createHash('md5').update(`${appSecret}json${rawJson}timestamp${timestamp}${appSecret}`, 'utf8').digest('hex')
    : ''

  const parsed = parseAgisoTradeRequest({
    query: {
      aopic: '16',
      timestamp,
      sign,
    },
    body: {
      json: rawJson,
      fromPlatform: 'AldsIdle',
    },
  })

  assert.equal(parsed.platform, 'xianyu')
  assert.equal(parsed.eventType, 'buyer_confirm_goods')
  assert.equal(resolveAgisoTradeIgnoreReason(parsed), 'buyer_confirm_goods')
})

test('trade finished payload is still treated as buyer confirm goods when aopic drifts', () => {
  const parsed = parseAgisoTradeRequest({
    query: {
      aopic: '1',
      timestamp: '1776096226',
      sign: '',
    },
    body: {
      json: '{"biz_order_id":2701836516013026052,"order_status":4,"Status":"TRADE_FINISHED"}',
      fromPlatform: 'xianyu',
    },
  })

  assert.equal(parsed.eventType, 'buyer_confirm_goods')
  assert.equal(resolveAgisoTradeIgnoreReason(parsed), 'buyer_confirm_goods')
})

test('verifyAgisoSignatureWithSecret supports documented and legacy signatures', () => {
  const appSecret = 'unit-test-secret'
  const rawJson = '{"biz_order_id":"4502259793206016214"}'
  const timestamp = '1713097840'
  const documentedSign = crypto
    .createHash('md5')
    .update(`${appSecret}json${rawJson}timestamp${timestamp}${appSecret}`, 'utf8')
    .digest('hex')
  const legacySign = crypto
    .createHash('md5')
    .update(`${appSecret}${rawJson}${timestamp}`, 'utf8')
    .digest('hex')

  assert.equal(
    verifyAgisoSignatureWithSecret({ rawJson, timestamp, sign: documentedSign, appSecret }),
    true,
  )
  assert.equal(
    verifyAgisoSignatureWithSecret({ rawJson, timestamp, sign: legacySign, appSecret }),
    true,
  )
  assert.equal(
    verifyAgisoSignatureWithSecret({ rawJson, timestamp, sign: 'bad-sign', appSecret }),
    false,
  )
})

test('buildWebhookEventInput preserves raw request payload for later replay', () => {
  const input = buildWebhookEventInput(
    {
      headers: { 'x-request-id': 'req-1' },
      query: { timestamp: '1713097840', sign: 'bad-sign' },
      body: { json: '{"biz_order_id":"4502259793206016214"}' },
    },
    {
      provider: 'agiso',
      platform: 'xianyu',
      shopId: 'shop-9',
      shopName: '咸鱼店铺',
      eventType: 'payment_success',
      eventKey: 'agiso:xianyu:4502259793206016214:payment_success',
      signatureValid: false,
    },
  )

  assert.equal(input.provider, 'agiso')
  assert.equal(input.platform, 'xianyu')
  assert.equal(input.eventType, 'payment_success')
  assert.equal(input.eventKey, 'agiso:xianyu:4502259793206016214:payment_success')
  assert.equal(input.signatureValid, false)
  assert.equal(input.processed, false)
  assert.equal(input.processError, '')
  assert.equal(input.relatedOrderId, null)
  assert.deepEqual(JSON.parse(input.headersJson), { 'x-request-id': 'req-1' })
  assert.deepEqual(JSON.parse(input.queryJson), { timestamp: '1713097840', sign: 'bad-sign' })
  assert.deepEqual(JSON.parse(input.bodyJson), { json: '{"biz_order_id":"4502259793206016214"}' })
  assert.match(input.createdAt, /^\d{4}-\d{2}-\d{2}T/)
})

test('executeAgisoTradeWebhookWithDeps records invalid signature failure', async () => {
  const updates = []

  await assert.rejects(
    () => executeAgisoTradeWebhookWithDeps(
      createParsedTrade({ signatureValid: false }),
      701,
      { requestId: 'req-invalid-signature' },
      {
        updateWebhookEvent: async (webhookEventId, patch) => {
          updates.push({ webhookEventId, patch })
          return { id: webhookEventId, ...patch }
        },
        hasConfiguredOrderItems: async () => {
          throw new Error('should not check configured items when signature is invalid')
        },
      },
    ),
    /验签失败/,
  )

  assert.deepEqual(updates, [
    {
      webhookEventId: 701,
      patch: {
        processed: false,
        process_error: '验签失败',
        related_order_id: null,
      },
    },
  ])
})

test('executeAgisoTradeWebhookWithDeps ignores unconfigured products before upsert', async () => {
  const updates = []
  let upsertCalled = false

  const result = await executeAgisoTradeWebhookWithDeps(
    createParsedTrade(),
    702,
    { requestId: 'req-unconfigured' },
    {
      hasConfiguredOrderItems: async (input) => {
        assert.equal(input.provider, 'agiso')
        assert.equal(input.platform, 'xianyu')
        assert.equal(input.shopId, 'shop-9')
        assert.equal(input.items.length, 1)
        return false
      },
      updateWebhookEvent: async (webhookEventId, patch) => {
        updates.push({ webhookEventId, patch })
        return { id: webhookEventId, ...patch }
      },
      upsertOrderFromWebhook: async () => {
        upsertCalled = true
        return {}
      },
    },
  )

  assert.equal(result.accepted, true)
  assert.equal(result.ignored, true)
  assert.equal(result.ignoreReason, 'unconfigured_product')
  assert.equal(result.orderId, null)
  assert.equal(upsertCalled, false)
  assert.deepEqual(updates, [
    {
      webhookEventId: 702,
      patch: {
        processed: true,
        process_error: 'ignored_unconfigured_product',
        related_order_id: null,
      },
    },
  ])
})

test('executeAgisoTradeWebhookWithDeps enriches incomplete xianyu trade and upserts order', async () => {
  const updates = []
  const enrichCalls = []
  const upsertCalls = []
  const parsed = createParsedTrade({
    totalAmount: 0,
    buyerName: '',
    shopName: '',
    items: [
      {
        skuCode: 'dnf-cdk-a',
        skuName: 'dnf-cdk-a',
        quantity: 1,
        spec: {},
      },
    ],
  })

  const result = await executeAgisoTradeWebhookWithDeps(
    parsed,
    703,
    { requestId: 'req-success' },
    {
      hasConfiguredOrderItems: async () => true,
      enrichAgisoXianyuTradeOrder: async (input, options) => {
        enrichCalls.push({ input, options })
        return {
          parsed: {
            ...input,
            totalAmount: 1990,
            buyerName: '补查买家',
            shopName: '补查店铺',
            items: [
              {
                skuCode: 'dnf-cdk-a',
                skuName: 'DNF礼包',
                quantity: 1,
                spec: { title: 'DNF礼包' },
              },
            ],
          },
          enriched: true,
          reason: '',
        }
      },
      upsertOrderFromWebhook: async (input) => {
        upsertCalls.push(input)
        return {
          ignored: false,
          ignoreReason: '',
          order: { id: 801 },
          tasks: [
            { id: 901, task_no: 'DT901', task_status: 'paid' },
          ],
          messageDeliveries: [{ id: 1001 }],
        }
      },
      updateWebhookEvent: async (webhookEventId, patch) => {
        updates.push({ webhookEventId, patch })
        return { id: webhookEventId, ...patch }
      },
    },
  )

  assert.equal(enrichCalls.length, 1)
  assert.equal(enrichCalls[0].options.requestId, 'req-success')
  assert.equal(upsertCalls.length, 1)
  assert.equal(upsertCalls[0].totalAmount, 1990)
  assert.equal(upsertCalls[0].buyerName, '补查买家')
  assert.equal(result.accepted, true)
  assert.equal(result.ignored, false)
  assert.equal(result.enriched, true)
  assert.equal(result.orderId, 801)
  assert.equal(result.totalAmountFen, 1990)
  assert.equal(result.taskCount, 1)
  assert.deepEqual(result.tasks, [
    {
      taskId: 901,
      taskNo: 'DT901',
      status: 'paid',
    },
  ])
  assert.deepEqual(updates, [
    {
      webhookEventId: 703,
      patch: {
        processed: true,
        process_error: '',
        related_order_id: 801,
      },
    },
  ])
})
