import { IntegrationTestDatabase } from './integration-test-db';
import { EntityTarget, ObjectLiteral } from 'typeorm';

/**
 * 集成测试断言工具
 * 通用版本，不依赖特定实体
 */
export class IntegrationTestAssertions {
  /**
   * 断言响应状态码
   */
  static expectStatus(response: { status: number }, expectedStatus: number): void {
    if (response.status !== expectedStatus) {
      throw new Error(`Expected status ${expectedStatus}, but got ${response.status}`);
    }
  }

  /**
   * 断言响应包含特定字段
   */
  static expectResponseToHave(response: { data: any }, expectedFields: Record<string, any>): void {
    for (const [key, value] of Object.entries(expectedFields)) {
      if (response.data[key] !== value) {
        throw new Error(`Expected field ${key} to be ${value}, but got ${response.data[key]}`);
      }
    }
  }

  /**
   * 断言响应包含特定结构
   */
  static expectResponseStructure(response: { data: any }, structure: Record<string, any>): void {
    for (const key of Object.keys(structure)) {
      if (!(key in response.data)) {
        throw new Error(`Expected response to have key: ${key}`);
      }
    }
  }

  /**
   * 断言实体存在于数据库中
   */
  static async expectEntityToExist<T extends ObjectLiteral>(
    entity: EntityTarget<T>,
    condition: Partial<T>
  ): Promise<void> {
    const dataSource = await IntegrationTestDatabase.getDataSource();
    if (!dataSource) {
      throw new Error('Database not initialized');
    }

    const repository = dataSource.getRepository(entity);
    const entityInstance = await repository.findOne({ where: condition });

    if (!entityInstance) {
      throw new Error(`Expected entity to exist in database with condition: ${JSON.stringify(condition)}`);
    }
  }

  /**
   * 断言实体不存在于数据库中
   */
  static async expectEntityNotToExist<T extends ObjectLiteral>(
    entity: EntityTarget<T>,
    condition: Partial<T>
  ): Promise<void> {
    const dataSource = await IntegrationTestDatabase.getDataSource();
    if (!dataSource) {
      throw new Error('Database not initialized');
    }

    const repository = dataSource.getRepository(entity);
    const entityInstance = await repository.findOne({ where: condition });

    if (entityInstance) {
      throw new Error(`Expected entity not to exist in database with condition: ${JSON.stringify(condition)}`);
    }
  }

  /**
   * 断言响应包含错误信息
   */
  static expectErrorResponse(response: { data: any }, expectedError: string): void {
    if (!response.data || !response.data.error || !response.data.error.includes(expectedError)) {
      throw new Error(`Expected error response to contain "${expectedError}", but got: ${JSON.stringify(response.data)}`);
    }
  }

  /**
   * 断言响应包含成功信息
   */
  static expectSuccessResponse(response: { data: any }): void {
    if (!response.data || response.data.error) {
      throw new Error(`Expected success response, but got: ${JSON.stringify(response.data)}`);
    }
  }

  /**
   * 断言列表响应包含特定数量的项目
   */
  static expectListResponseCount(response: { data: any }, expectedCount: number): void {
    if (!Array.isArray(response.data)) {
      throw new Error(`Expected array response, but got: ${typeof response.data}`);
    }

    if (response.data.length !== expectedCount) {
      throw new Error(`Expected ${expectedCount} items, but got ${response.data.length}`);
    }
  }

  /**
   * 断言响应包含分页信息
   */
  static expectPaginationResponse(response: { data: any }): void {
    if (!response.data || typeof response.data !== 'object') {
      throw new Error(`Expected object response, but got: ${typeof response.data}`);
    }

    const requiredFields = ['data', 'total', 'page', 'pageSize'];
    for (const field of requiredFields) {
      if (!(field in response.data)) {
        throw new Error(`Expected pagination response to have field: ${field}`);
      }
    }

    if (!Array.isArray(response.data.data)) {
      throw new Error(`Expected pagination data to be an array, but got: ${typeof response.data.data}`);
    }
  }
}

/**
 * API 响应断言工具
 */
export class ApiResponseAssertions {
  /**
   * 断言成功的 API 响应
   */
  static expectSuccess(response: { status: number; data: any }): void {
    IntegrationTestAssertions.expectStatus(response, 200);
    IntegrationTestAssertions.expectSuccessResponse(response);
  }

  /**
   * 断言创建的 API 响应
   */
  static expectCreated(response: { status: number; data: any }): void {
    IntegrationTestAssertions.expectStatus(response, 201);
    IntegrationTestAssertions.expectSuccessResponse(response);
  }

  /**
   * 断言未授权的 API 响应
   */
  static expectUnauthorized(response: { status: number; data: any }): void {
    IntegrationTestAssertions.expectStatus(response, 401);
    IntegrationTestAssertions.expectErrorResponse(response, 'Unauthorized');
  }

  /**
   * 断言禁止访问的 API 响应
   */
  static expectForbidden(response: { status: number; data: any }): void {
    IntegrationTestAssertions.expectStatus(response, 403);
    IntegrationTestAssertions.expectErrorResponse(response, 'Forbidden');
  }

  /**
   * 断言未找到的 API 响应
   */
  static expectNotFound(response: { status: number; data: any }): void {
    IntegrationTestAssertions.expectStatus(response, 404);
    IntegrationTestAssertions.expectErrorResponse(response, 'not found');
  }

  /**
   * 断言验证错误的 API 响应
   */
  static expectValidationError(response: { status: number; data: any }): void {
    IntegrationTestAssertions.expectStatus(response, 400);
    IntegrationTestAssertions.expectErrorResponse(response, 'Validation');
  }
}