import { describe, it, expect, beforeEach } from 'vitest';
import { AppDataSource } from '@d8d/shared-utils';
import {
  IntegrationTestDatabase,
  setupIntegrationDatabaseHooksWithEntities
} from '@d8d/shared-test-util';
import { PaymentMtEntity } from '../../src/entities/payment.mt.entity.js';
import { PaymentStatus } from '../../src/entities/payment.types.js';

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

// 测试数据工厂
const createTestPaymentData = (tenantId: number) => ({
  externalOrderId: 1001,
  userId: 1,
  totalAmount: 1000,
  description: '测试支付订单',
  paymentStatus: PaymentStatus.PENDING,
  openid: 'test_openid_123',
  tenantId
});

describe('多租户支付路由集成测试', () => {
  let dataSource: any;

  beforeEach(async () => {
    dataSource = await IntegrationTestDatabase.getDataSource();
    if (!dataSource) throw new Error('Database not initialized');
  });

  describe('租户数据隔离验证', () => {
    it('应该只返回当前租户的支付记录', async () => {
      // 创建不同租户的测试数据
      const tenant1Payment = createTestPaymentData(1);
      const tenant2Payment = createTestPaymentData(2);

      const paymentRepository = dataSource.getRepository(PaymentMtEntity);
      await paymentRepository.save([tenant1Payment, tenant2Payment]);

      // 模拟租户1的查询
      const tenant1Payments = await paymentRepository.find({
        where: { tenantId: 1 }
      });

      // 模拟租户2的查询
      const tenant2Payments = await paymentRepository.find({
        where: { tenantId: 2 }
      });

      expect(tenant1Payments).toHaveLength(1);
      expect(tenant1Payments[0].tenantId).toBe(1);
      expect(tenant2Payments).toHaveLength(1);
      expect(tenant2Payments[0].tenantId).toBe(2);
    });

    it('应该防止跨租户支付记录访问', async () => {
      // 创建租户1的支付记录
      const tenant1Payment = createTestPaymentData(1);
      const paymentRepository = dataSource.getRepository(PaymentMtEntity);
      await paymentRepository.save(tenant1Payment);

      // 尝试使用租户2的ID查询租户1的支付记录
      const crossTenantPayment = await paymentRepository.findOne({
        where: {
          externalOrderId: tenant1Payment.externalOrderId,
          tenantId: 2 // 错误的租户ID
        }
      });

      expect(crossTenantPayment).toBeNull();
    });

    it('应该正确设置租户ID在创建支付时', async () => {
      const paymentRepository = dataSource.getRepository(PaymentMtEntity);
      const tenantId = 3;

      const newPayment = paymentRepository.create({
        ...createTestPaymentData(tenantId),
        externalOrderId: 1002
      });

      const savedPayment = await paymentRepository.save(newPayment);

      expect(savedPayment.tenantId).toBe(tenantId);
      expect(savedPayment.externalOrderId).toBe(1002);
    });
  });

  describe('支付状态管理', () => {
    it('应该正确更新支付状态', async () => {
      const paymentRepository = dataSource.getRepository(PaymentMtEntity);
      const paymentData = createTestPaymentData(1);

      const payment = paymentRepository.create(paymentData);
      const savedPayment = await paymentRepository.save(payment);

      // 更新支付状态
      savedPayment.paymentStatus = PaymentStatus.PAID;
      savedPayment.wechatTransactionId = 'wx_transaction_123';

      const updatedPayment = await paymentRepository.save(savedPayment);

      expect(updatedPayment.paymentStatus).toBe(PaymentStatus.PAID);
      expect(updatedPayment.wechatTransactionId).toBe('wx_transaction_123');
    });

    it('应该支持所有支付状态枚举值', async () => {
      const paymentRepository = dataSource.getRepository(PaymentMtEntity);

      // 测试所有状态枚举值
      const statuses = Object.values(PaymentStatus);

      for (const status of statuses) {
        const paymentData = createTestPaymentData(1);
        paymentData.paymentStatus = status;
        paymentData.externalOrderId = Math.floor(Math.random() * 10000);

        const payment = paymentRepository.create(paymentData);
        const savedPayment = await paymentRepository.save(payment);

        expect(savedPayment.paymentStatus).toBe(status);
      }
    });
  });

  describe('支付记录唯一性', () => {
    it('应该防止相同外部订单ID的重复支付记录', async () => {
      const paymentRepository = dataSource.getRepository(PaymentMtEntity);
      const paymentData = createTestPaymentData(1);

      // 创建第一个支付记录
      const payment1 = paymentRepository.create(paymentData);
      await paymentRepository.save(payment1);

      // 尝试创建相同外部订单ID的支付记录
      const payment2 = paymentRepository.create({
        ...paymentData,
        userId: 2 // 不同用户
      });

      // 应该成功，因为租户隔离允许相同外部订单ID
      const savedPayment2 = await paymentRepository.save(payment2);

      expect(savedPayment2.externalOrderId).toBe(paymentData.externalOrderId);
      expect(savedPayment2.userId).toBe(2);
    });
  });

  describe('关联实体租户一致性', () => {
    it('应该确保支付与用户的租户一致性', async () => {
      const paymentRepository = dataSource.getRepository(PaymentMtEntity);

      // 创建租户1的支付记录
      const paymentData1 = createTestPaymentData(1);
      const payment1 = paymentRepository.create(paymentData1);
      await paymentRepository.save(payment1);

      // 创建租户2的支付记录
      const paymentData2 = createTestPaymentData(2);
      paymentData2.externalOrderId = 1003;
      const payment2 = paymentRepository.create(paymentData2);
      await paymentRepository.save(payment2);

      // 验证租户隔离
      const tenant1Payments = await paymentRepository.find({ where: { tenantId: 1 } });
      const tenant2Payments = await paymentRepository.find({ where: { tenantId: 2 } });

      expect(tenant1Payments).toHaveLength(1);
      expect(tenant1Payments[0].tenantId).toBe(1);
      expect(tenant2Payments).toHaveLength(1);
      expect(tenant2Payments[0].tenantId).toBe(2);
    });
  });
});