import { describe, it, expect, beforeEach, vi } from 'vitest';
import { DataSource } from 'typeorm';
import {
  IntegrationTestDatabase,
  setupIntegrationDatabaseHooksWithEntities
} from '@d8d/shared-test-util';
import { PaymentMtService } from '../../src/services/payment.mt.service.js';
import { PaymentMtEntity } from '../../src/entities/payment.mt.entity.js';
import { PaymentStatus } from '../../src/entities/payment.types.js';

// Mock 微信支付SDK
vi.mock('wechatpay-node-v3', () => {
  return {
    default: vi.fn().mockImplementation(() => ({
      refunds: vi.fn().mockResolvedValue({
        id: 'mock_refund_id_123',
        out_refund_no: 'REFUND_ORDER_123_1234567890',
        status: 'SUCCESS'
      }),
      verifySign: vi.fn().mockResolvedValue(true),
      decipher_gcm: vi.fn().mockReturnValue(JSON.stringify({
        out_refund_no: 'REFUND_ORDER_123_1234567890',
        refund_status: 'SUCCESS'
      }))
    }))
  };
});

// Mock 系统配置服务
vi.mock('@d8d/core-module-mt/system-config-module-mt', () => ({
  SystemConfigServiceMt: vi.fn().mockImplementation(() => ({
    getConfigsByKeys: vi.fn().mockResolvedValue({
      'wx.payment.merchant.id': 'mock_merchant_id',
      'wx.mini.app.id': 'mock_app_id',
      'wx.payment.v3.key': 'mock_v3_key',
      'wx.payment.notify.url': 'mock_notify_url',
      'wx.payment.cert.serial.no': 'mock_cert_serial_no',
      'wx.payment.public.key': 'mock_public_key',
      'wx.payment.private.key': 'mock_private_key'
    })
  }))
}));

// Mock 订单服务
vi.mock('@d8d/orders-module-mt', () => ({
  OrderMtService: vi.fn().mockImplementation(() => ({})),
  OrderMt: vi.fn()
}));

// 设置集成测试钩子
setupIntegrationDatabaseHooksWithEntities([PaymentMtEntity])

describe('PaymentRefund Integration Tests', () => {
  let dataSource: DataSource;
  let paymentService: PaymentMtService;

  beforeEach(async () => {
    // 获取集成测试数据库连接
    dataSource = await IntegrationTestDatabase.getDataSource();
    paymentService = new PaymentMtService(dataSource);
  });

  describe('refund method', () => {
    it('应该成功处理已支付订单的退款', async () => {
      // 准备测试数据
      const payment = new PaymentMtEntity();
      payment.tenantId = 1;
      payment.externalOrderId = 1001;
      payment.userId = 1;
      payment.totalAmount = 1000; // 10元
      payment.description = '测试订单';
      payment.paymentStatus = PaymentStatus.PAID;
      payment.outTradeNo = 'PAYMENT_1001_1234567890';
      payment.openid = 'mock_openid';
      payment.wechatTransactionId = 'mock_transaction_id';

      await dataSource.getRepository(PaymentMtEntity).save(payment);

      // 执行退款
      const refundResult = await paymentService.refund(
        1,
        'PAYMENT_1001_1234567890',
        1000,
        '测试退款'
      );

      // 验证退款结果
      expect(refundResult).toMatchObject({
        refundId: expect.stringContaining('REFUND_PAYMENT_1001_1234567890'),
        outRefundNo: expect.stringContaining('REFUND_PAYMENT_1001_1234567890'),
        refundStatus: 'SUCCESS',
        refundAmount: 1000,
        refundTime: expect.any(String)
      });

      // 验证支付记录已更新
      const updatedPayment = await dataSource.getRepository(PaymentMtEntity).findOne({
        where: { outTradeNo: 'PAYMENT_1001_1234567890', tenantId: 1 }
      });

      expect(updatedPayment).toBeDefined();
      expect(updatedPayment?.refundStatus).toBe(PaymentStatus.REFUNDED);
      expect(updatedPayment?.refundAmount).toBe(1000);
      expect(updatedPayment?.refundTime).toBeInstanceOf(Date);
    });

    it('应该对不存在的支付记录抛出错误', async () => {
      await expect(
        paymentService.refund(1, 'NON_EXISTENT_ORDER', 1000)
      ).rejects.toThrow('支付记录不存在');
    });

    it('应该对未支付订单抛出错误', async () => {
      const payment = new PaymentMtEntity();
      payment.tenantId = 1;
      payment.externalOrderId = 1002;
      payment.userId = 1;
      payment.totalAmount = 1000;
      payment.description = '测试订单';
      payment.paymentStatus = PaymentStatus.PENDING;
      payment.outTradeNo = 'PAYMENT_1002_1234567890';
      payment.openid = 'mock_openid';

      await dataSource.getRepository(PaymentMtEntity).save(payment);

      await expect(
        paymentService.refund(1, 'PAYMENT_1002_1234567890', 1000)
      ).rejects.toThrow('订单支付状态不正确');
    });

    it('应该对无效退款金额抛出错误', async () => {
      const payment = new PaymentMtEntity();
      payment.tenantId = 1;
      payment.externalOrderId = 1003;
      payment.userId = 1;
      payment.totalAmount = 1000;
      payment.description = '测试订单';
      payment.paymentStatus = PaymentStatus.PAID;
      payment.outTradeNo = 'PAYMENT_1003_1234567890';
      payment.openid = 'mock_openid';
      payment.wechatTransactionId = 'mock_transaction_id';

      await dataSource.getRepository(PaymentMtEntity).save(payment);

      // 测试退款金额为0
      await expect(
        paymentService.refund(1, 'PAYMENT_1003_1234567890', 0)
      ).rejects.toThrow('退款金额无效');

      // 测试退款金额超过支付金额
      await expect(
        paymentService.refund(1, 'PAYMENT_1003_1234567890', 2000)
      ).rejects.toThrow('退款金额无效');
    });
  });

  describe('handleRefundCallback method', () => {
    it('应该成功处理退款回调', async () => {
      const mockCallbackData = {
        resource: {
          ciphertext: 'mock_ciphertext',
          associated_data: '',
          nonce: 'mock_nonce'
        }
      };

      const mockHeaders = {
        'wechatpay-timestamp': 'mock_timestamp',
        'wechatpay-nonce': 'mock_nonce',
        'wechatpay-signature': 'mock_signature',
        'wechatpay-serial': 'mock_serial'
      };

      const mockRawBody = 'mock_raw_body';

      // 执行退款回调处理
      await expect(
        paymentService.handleRefundCallback(mockCallbackData, mockHeaders, mockRawBody)
      ).resolves.not.toThrow();
    });
  });

  describe('multi-tenant refund data isolation', () => {
    it('应该只退款特定租户的支付记录', async () => {
      // 创建租户1的支付记录
      const payment1 = new PaymentMtEntity();
      payment1.tenantId = 1;
      payment1.externalOrderId = 1004;
      payment1.userId = 1;
      payment1.totalAmount = 1000;
      payment1.description = '租户1订单';
      payment1.paymentStatus = PaymentStatus.PAID;
      payment1.outTradeNo = 'PAYMENT_1004_1234567890';
      payment1.openid = 'mock_openid';
      payment1.wechatTransactionId = 'mock_transaction_id';

      // 创建租户2的支付记录
      const payment2 = new PaymentMtEntity();
      payment2.tenantId = 2;
      payment2.externalOrderId = 1004;
      payment2.userId = 1;
      payment2.totalAmount = 1000;
      payment2.description = '租户2订单';
      payment2.paymentStatus = PaymentStatus.PAID;
      payment2.outTradeNo = 'PAYMENT_1004_1234567890';
      payment2.openid = 'mock_openid';
      payment2.wechatTransactionId = 'mock_transaction_id';

      await dataSource.getRepository(PaymentMtEntity).save([payment1, payment2]);

      // 为租户1执行退款
      await paymentService.refund(1, 'PAYMENT_1004_1234567890', 1000);

      // 验证租户1的支付记录已更新
      const tenant1Payment = await dataSource.getRepository(PaymentMtEntity).findOne({
        where: { outTradeNo: 'PAYMENT_1004_1234567890', tenantId: 1 }
      });
      expect(tenant1Payment?.refundStatus).toBe(PaymentStatus.REFUNDED);

      // 验证租户2的支付记录未受影响
      const tenant2Payment = await dataSource.getRepository(PaymentMtEntity).findOne({
        where: { outTradeNo: 'PAYMENT_1004_1234567890', tenantId: 2 }
      });
      expect(tenant2Payment?.refundStatus).toBeNull();
    });
  });
});