import { describe, it, expect } from 'vitest';
import { IntegrationTestAssertions, ApiResponseAssertions } from '../../src/integration-test-utils';

// 模拟实体用于测试
class MockEntity {
  id?: number;
  name?: string;
}

describe('IntegrationTestAssertions', () => {
  describe('expectStatus', () => {
    it('应该在状态码匹配时通过', () => {
      const response = { status: 200 };

      expect(() => {
        IntegrationTestAssertions.expectStatus(response, 200);
      }).not.toThrow();
    });

    it('应该在状态码不匹配时抛出错误', () => {
      const response = { status: 404 };

      expect(() => {
        IntegrationTestAssertions.expectStatus(response, 200);
      }).toThrow('Expected status 200, but got 404');
    });
  });

  describe('expectResponseToHave', () => {
    it('应该在响应包含特定字段时通过', () => {
      const response = { data: { id: 1, name: 'test' } };
      const expectedFields = { id: 1, name: 'test' };

      expect(() => {
        IntegrationTestAssertions.expectResponseToHave(response, expectedFields);
      }).not.toThrow();
    });

    it('应该在字段值不匹配时抛出错误', () => {
      const response = { data: { id: 1, name: 'test' } };
      const expectedFields = { id: 2, name: 'test' };

      expect(() => {
        IntegrationTestAssertions.expectResponseToHave(response, expectedFields);
      }).toThrow('Expected field id to be 2, but got 1');
    });

    it('应该在字段不存在时抛出错误', () => {
      const response = { data: { id: 1 } };
      const expectedFields = { name: 'test' };

      expect(() => {
        IntegrationTestAssertions.expectResponseToHave(response, expectedFields);
      }).toThrow('Expected field name to be test, but got undefined');
    });
  });

  describe('expectResponseStructure', () => {
    it('应该在响应包含特定结构时通过', () => {
      const response = { data: { id: 1, name: 'test', email: 'test@example.com' } };
      const structure = { id: 'number', name: 'string', email: 'string' };

      expect(() => {
        IntegrationTestAssertions.expectResponseStructure(response, structure);
      }).not.toThrow();
    });

    it('应该在响应缺少字段时抛出错误', () => {
      const response = { data: { id: 1, name: 'test' } };
      const structure = { id: 'number', name: 'string', email: 'string' };

      expect(() => {
        IntegrationTestAssertions.expectResponseStructure(response, structure);
      }).toThrow('Expected response to have key: email');
    });
  });

  describe('expectErrorResponse', () => {
    it('应该在响应包含错误信息时通过', () => {
      const response = { data: { error: 'Validation failed' } };

      expect(() => {
        IntegrationTestAssertions.expectErrorResponse(response, 'Validation');
      }).not.toThrow();
    });

    it('应该在响应不包含错误信息时抛出错误', () => {
      const response = { data: { success: true } };

      expect(() => {
        IntegrationTestAssertions.expectErrorResponse(response, 'Validation');
      }).toThrow('Expected error response to contain "Validation"');
    });

    it('应该在错误信息不匹配时抛出错误', () => {
      const response = { data: { error: 'Authentication failed' } };

      expect(() => {
        IntegrationTestAssertions.expectErrorResponse(response, 'Validation');
      }).toThrow('Expected error response to contain "Validation"');
    });
  });

  describe('expectSuccessResponse', () => {
    it('应该在成功响应时通过', () => {
      const response = { data: { success: true, data: {} } };

      expect(() => {
        IntegrationTestAssertions.expectSuccessResponse(response);
      }).not.toThrow();
    });

    it('应该在响应包含错误时抛出错误', () => {
      const response = { data: { error: 'Something went wrong' } };

      expect(() => {
        IntegrationTestAssertions.expectSuccessResponse(response);
      }).toThrow('Expected success response');
    });

    it('应该在响应为空时抛出错误', () => {
      const response = { data: null };

      expect(() => {
        IntegrationTestAssertions.expectSuccessResponse(response);
      }).toThrow('Expected success response');
    });
  });

  describe('expectListResponseCount', () => {
    it('应该在列表响应数量匹配时通过', () => {
      const response = { data: [1, 2, 3] };

      expect(() => {
        IntegrationTestAssertions.expectListResponseCount(response, 3);
      }).not.toThrow();
    });

    it('应该在列表响应数量不匹配时抛出错误', () => {
      const response = { data: [1, 2, 3] };

      expect(() => {
        IntegrationTestAssertions.expectListResponseCount(response, 5);
      }).toThrow('Expected 5 items, but got 3');
    });

    it('应该在响应不是数组时抛出错误', () => {
      const response = { data: { items: [1, 2, 3] } };

      expect(() => {
        IntegrationTestAssertions.expectListResponseCount(response, 3);
      }).toThrow('Expected array response');
    });
  });

  describe('expectPaginationResponse', () => {
    it('应该在分页响应格式正确时通过', () => {
      const response = {
        data: {
          data: [1, 2, 3],
          total: 10,
          page: 1,
          pageSize: 3
        }
      };

      expect(() => {
        IntegrationTestAssertions.expectPaginationResponse(response);
      }).not.toThrow();
    });

    it('应该在缺少分页字段时抛出错误', () => {
      const response = {
        data: {
          data: [1, 2, 3],
          total: 10
          // 缺少 page 和 pageSize
        }
      };

      expect(() => {
        IntegrationTestAssertions.expectPaginationResponse(response);
      }).toThrow('Expected pagination response to have field: page');
    });

    it('应该在数据不是数组时抛出错误', () => {
      const response = {
        data: {
          data: { items: [1, 2, 3] }, // 应该是数组
          total: 10,
          page: 1,
          pageSize: 3
        }
      };

      expect(() => {
        IntegrationTestAssertions.expectPaginationResponse(response);
      }).toThrow('Expected pagination data to be an array');
    });
  });
});

describe('ApiResponseAssertions', () => {
  describe('expectSuccess', () => {
    it('应该在成功响应时通过', () => {
      const response = { status: 200, data: { success: true } };

      expect(() => {
        ApiResponseAssertions.expectSuccess(response);
      }).not.toThrow();
    });

    it('应该在状态码不是200时抛出错误', () => {
      const response = { status: 404, data: { success: true } };

      expect(() => {
        ApiResponseAssertions.expectSuccess(response);
      }).toThrow('Expected status 200, but got 404');
    });
  });

  describe('expectCreated', () => {
    it('应该在创建响应时通过', () => {
      const response = { status: 201, data: { id: 1 } };

      expect(() => {
        ApiResponseAssertions.expectCreated(response);
      }).not.toThrow();
    });
  });

  describe('expectUnauthorized', () => {
    it('应该在未授权响应时通过', () => {
      const response = { status: 401, data: { error: 'Unauthorized access' } };

      expect(() => {
        ApiResponseAssertions.expectUnauthorized(response);
      }).not.toThrow();
    });
  });

  describe('expectForbidden', () => {
    it('应该在禁止访问响应时通过', () => {
      const response = { status: 403, data: { error: 'Forbidden access' } };

      expect(() => {
        ApiResponseAssertions.expectForbidden(response);
      }).not.toThrow();
    });
  });

  describe('expectNotFound', () => {
    it('应该在未找到响应时通过', () => {
      const response = { status: 404, data: { error: 'Resource not found' } };

      expect(() => {
        ApiResponseAssertions.expectNotFound(response);
      }).not.toThrow();
    });
  });

  describe('expectValidationError', () => {
    it('应该在验证错误响应时通过', () => {
      const response = { status: 400, data: { error: 'Validation failed' } };

      expect(() => {
        ApiResponseAssertions.expectValidationError(response);
      }).not.toThrow();
    });
  });
});