import { DataSource } from 'typeorm';
import { UserEntityMt } from '@d8d/core-module-mt/user-module-mt/entities';
import { MerchantMt } from '@d8d/merchant-module-mt';
import { SupplierMt } from '@d8d/supplier-module-mt';
import { DeliveryAddressMt } from '@d8d/delivery-address-module-mt';
import { AreaEntityMt } from '@d8d/geo-areas-mt';
import { OrderMt } from '@d8d/orders-module-mt';
import { JWTUtil } from '@d8d/shared-utils';

/**
 * 信用额度模块测试数据工厂类
 */
export class CreditBalanceTestDataFactory {
  /**
   * 创建测试用户数据
   */
  static createUserData(overrides: Partial<UserEntityMt> = {}): Partial<UserEntityMt> {
    const timestamp = Math.floor(Math.random() * 100000);
    return {
      username: `test_user_${timestamp}`,
      password: 'test_password',
      nickname: '测试用户',
      registrationSource: 'web',
      isDisabled: 0,
      ...overrides
    };
  }

  /**
   * 在数据库中创建测试用户
   */
  static async createTestUser(dataSource: DataSource, tenantId: number, overrides: Partial<UserEntityMt> = {}): Promise<UserEntityMt> {
    const userData = this.createUserData({ tenantId, ...overrides });
    const userRepository = dataSource.getRepository(UserEntityMt);
    const user = userRepository.create(userData);
    return await userRepository.save(user);
  }

  /**
   * 创建测试商户
   */
  static async createTestMerchant(dataSource: DataSource, tenantId: number, userId: number, overrides: Partial<MerchantMt> = {}): Promise<MerchantMt> {
    const merchantRepository = dataSource.getRepository(MerchantMt);
    const timestamp = Date.now();

    const merchant = merchantRepository.create({
      tenantId,
      name: '测试商户',
      username: `m${timestamp}`.slice(-19),
      password: 'test_password',
      state: 1,
      createdBy: userId,
      updatedBy: userId,
      ...overrides
    });

    return await merchantRepository.save(merchant);
  }

  /**
   * 创建测试供货商
   */
  static async createTestSupplier(dataSource: DataSource, tenantId: number, userId: number, overrides: Partial<SupplierMt> = {}): Promise<SupplierMt> {
    const supplierRepository = dataSource.getRepository(SupplierMt);
    const timestamp = Date.now();

    const supplier = supplierRepository.create({
      tenantId,
      name: '测试供货商',
      username: `s${timestamp}`.slice(-49),
      password: 'test_password',
      state: 1,
      createdBy: userId,
      updatedBy: userId,
      ...overrides
    });

    return await supplierRepository.save(supplier);
  }

  /**
   * 创建测试地区记录
   */
  static async createTestArea(dataSource: DataSource, id: number, name: string, level: number, tenantId: number = 1, parentId: number | null = null): Promise<AreaEntityMt> {
    const areaRepository = dataSource.getRepository(AreaEntityMt);

    const area = areaRepository.create({
      id,
      tenantId,
      name,
      level,
      code: id.toString(),
      parentId,
      isDisabled: 0,
      isDeleted: 0,
      createdBy: 1,
      updatedBy: 1
    });

    return await areaRepository.save(area);
  }

  /**
   * 创建测试配送地址
   */
  static async createTestDeliveryAddress(dataSource: DataSource, tenantId: number, userId: number, overrides: Partial<DeliveryAddressMt> = {}): Promise<DeliveryAddressMt> {
    const addressRepository = dataSource.getRepository(DeliveryAddressMt);

    // 创建地区记录
    const province = await this.createTestArea(dataSource, 110000, '北京市', 1, tenantId, null);
    const city = await this.createTestArea(dataSource, 110100, '北京市', 2, tenantId, province.id);
    const district = await this.createTestArea(dataSource, 110101, '东城区', 3, tenantId, city.id);
    const town = await this.createTestArea(dataSource, 110101001, '东华门街道', 4, tenantId, district.id);

    const address = addressRepository.create({
      tenantId,
      userId,
      name: '测试收货人',
      phone: '13800138000',
      receiverProvince: province.id,
      receiverCity: city.id,
      receiverDistrict: district.id,
      receiverTown: town.id,
      address: '测试地址',
      isDefault: 1,
      state: 1,
      createdBy: userId,
      updatedBy: userId,
      ...overrides
    });

    return await addressRepository.save(address);
  }

  /**
   * 创建测试订单
   */
  static async createTestOrder(
    dataSource: DataSource,
    tenantId: number,
    userId: number,
    merchantId: number,
    supplierId: number,
    addressId: number,
    overrides: Partial<OrderMt> = {}
  ): Promise<OrderMt> {
    const orderRepository = dataSource.getRepository(OrderMt);
    const timestamp = Date.now();

    const order = orderRepository.create({
      tenantId,
      orderNo: `ORD${timestamp}`,
      userId,
      amount: 100.00,
      costAmount: 80.00,
      payAmount: 100.00,
      orderType: 1,
      payType: 0, // 未设置支付类型
      payState: 0, // 未支付
      state: 0,
      addressId,
      merchantId,
      supplierId,
      createdBy: userId,
      updatedBy: userId,
      ...overrides
    });

    return await orderRepository.save(order);
  }

  /**
   * 创建完整的测试环境数据
   */
  static async createCompleteTestData(dataSource: DataSource, tenantId: number = 1): Promise<{
    user: UserEntityMt;
    merchant: MerchantMt;
    supplier: SupplierMt;
    address: DeliveryAddressMt;
    order: OrderMt;
  }> {
    // 创建用户
    const user = await this.createTestUser(dataSource, tenantId);

    // 创建商户
    const merchant = await this.createTestMerchant(dataSource, tenantId, user.id);

    // 创建供货商
    const supplier = await this.createTestSupplier(dataSource, tenantId, user.id);

    // 创建配送地址
    const address = await this.createTestDeliveryAddress(dataSource, tenantId, user.id);

    // 创建订单
    const order = await this.createTestOrder(dataSource, tenantId, user.id, merchant.id, supplier.id, address.id);

    return {
      user,
      merchant,
      supplier,
      address,
      order
    };
  }

  /**
   * 为测试用户生成JWT token
   */
  static generateUserToken(user: UserEntityMt): string {
    return JWTUtil.generateToken({
      id: user.id,
      username: user.username,
      tenantId: user.tenantId
    });
  }

  /**
   * 为管理员生成JWT token
   */
  static generateAdminToken(tenantId: number): string {
    return JWTUtil.generateToken({
      id: 1,
      username: 'admin',
      tenantId
    });
  }
}