import { DataSource, EntityTarget, ObjectLiteral } from 'typeorm';
import { beforeEach, afterEach } from 'vitest';
import { AppDataSource, initializeDataSource } from '@d8d/shared-utils';

/**
 * 集成测试数据库工具类 - 使用真实PostgreSQL数据库
 * 通用版本，不依赖特定实体
 */
export class IntegrationTestDatabase {
  /**
   * 清理集成测试数据库
   */
  static async cleanup(): Promise<void> {
    if (AppDataSource.isInitialized) {
      await AppDataSource.destroy();
    }
  }

  /**
   * 获取当前数据源
   */
  static async getDataSource(): Promise<DataSource> {
    if (!AppDataSource.isInitialized) {
      await AppDataSource.initialize();
    }
    return AppDataSource;
  }

  /**
   * 使用特定实体初始化数据源
   */
  static async initializeWithEntities(entities: EntityTarget<ObjectLiteral>[]): Promise<DataSource> {
    initializeDataSource(entities);
    return await this.getDataSource();
  }

  /**
   * 清理特定表的数据
   */
  static async cleanupTable<T extends ObjectLiteral>(
    entity: EntityTarget<T>,
    condition?: Partial<T>
  ): Promise<void> {
    const dataSource = await this.getDataSource();
    const repository = dataSource.getRepository(entity);

    if (condition) {
      await repository.delete(condition);
    } else {
      await repository.clear();
    }
  }

  /**
   * 创建测试数据
   */
  static async createTestData<T extends ObjectLiteral>(
    entity: EntityTarget<T>,
    data: Partial<T>
  ): Promise<T> {
    const dataSource = await this.getDataSource();
    const repository = dataSource.getRepository(entity);

    const entityInstance = repository.create(data);
    return await repository.save(entityInstance);
  }

  /**
   * 查找测试数据
   */
  static async findTestData<T extends ObjectLiteral>(
    entity: EntityTarget<T>,
    condition: Partial<T>
  ): Promise<T | null> {
    const dataSource = await this.getDataSource();
    const repository = dataSource.getRepository(entity);

    return await repository.findOne({ where: condition });
  }

  /**
   * 删除测试数据
   */
  static async deleteTestData<T extends ObjectLiteral>(
    entity: EntityTarget<T>,
    condition: Partial<T>
  ): Promise<void> {
    const dataSource = await this.getDataSource();
    const repository = dataSource.getRepository(entity);

    await repository.delete(condition);
  }
}


/**
 * 集成测试数据库生命周期钩子
 */
export function setupIntegrationDatabaseHooks() {
  beforeEach(async () => {
    await IntegrationTestDatabase.getDataSource();
  });

  afterEach(async () => {
    await IntegrationTestDatabase.cleanup();
  });
}

/**
 * 集成测试数据库生命周期钩子（带实体初始化）
 */
export function setupIntegrationDatabaseHooksWithEntities(entities: EntityTarget<ObjectLiteral>[]) {
  beforeEach(async () => {
    await IntegrationTestDatabase.initializeWithEntities(entities);
  });

  afterEach(async () => {
    await IntegrationTestDatabase.cleanup();
  });
}