import { describe, it, expect, beforeEach } from 'vitest';
import { testClient } from 'hono/testing';
import {
  IntegrationTestDatabase,
  setupIntegrationDatabaseHooksWithEntities,
  IntegrationTestAssertions
} from '@d8d/shared-test-util';
import { areasRoutesMt } from '../../src/api/areas/index.mt';
import { AreaEntityMt, AreaLevel } from '../../src/modules/areas/area.entity.mt';
import { DisabledStatus } from '@d8d/shared-types';
import { TestDataFactory } from '../utils/test-data-factory';
import { TestQueryFactory } from '../utils/test-query-factory';

// 定义响应类型
interface SuccessResponse {
  success: boolean;
  data: {
    provinces: Array<{
      id: number;
      name: string;
      code: string;
      level: number;
      parentId: number | null;
    }>;
    pagination: {
      page: number;
      pageSize: number;
      total: number;
      totalPages: number;
    };
  };
  message: string;
}

interface ErrorResponse {
  code: number;
  message: string;
  errors?: Array<{
    path: string[];
    message: string;
  }>;
}

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

describe('区域API集成测试', () => {
  let client: ReturnType<typeof testClient<typeof areasRoutesMt>>;
  let testAreas: AreaEntityMt[];

  beforeEach(async () => {
    // 创建测试客户端
    client = testClient(areasRoutesMt);

    // 创建测试数据
    const dataSource = await IntegrationTestDatabase.getDataSource();

    // 创建启用状态的省份（租户1）
    const province1 = await TestDataFactory.createTestArea(dataSource, {
      name: '北京市',
      level: AreaLevel.PROVINCE,
      isDisabled: DisabledStatus.ENABLED,
      tenantId: 1
    });
    const province2 = await TestDataFactory.createTestArea(dataSource, {
      name: '上海市',
      level: AreaLevel.PROVINCE,
      isDisabled: DisabledStatus.ENABLED,
      tenantId: 1
    });
    const province3 = await TestDataFactory.createTestArea(dataSource, {
      name: '广东省',
      level: AreaLevel.PROVINCE,
      isDisabled: DisabledStatus.ENABLED,
      tenantId: 1
    });

    // 创建启用状态的城市
    const city11 = await TestDataFactory.createTestArea(dataSource, {
      name: '北京市',
      level: AreaLevel.CITY,
      parentId: province1.id,
      isDisabled: DisabledStatus.ENABLED
    });
    const city12 = await TestDataFactory.createTestArea(dataSource, {
      name: '朝阳区',
      level: AreaLevel.CITY,
      parentId: province1.id,
      isDisabled: DisabledStatus.ENABLED
    });
    const city13 = await TestDataFactory.createTestArea(dataSource, {
      name: '海淀区',
      level: AreaLevel.CITY,
      parentId: province1.id,
      isDisabled: DisabledStatus.ENABLED
    });
    const city21 = await TestDataFactory.createTestArea(dataSource, {
      name: '上海市',
      level: AreaLevel.CITY,
      parentId: province2.id,
      isDisabled: DisabledStatus.ENABLED
    });
    const city22 = await TestDataFactory.createTestArea(dataSource, {
      name: '浦东新区',
      level: AreaLevel.CITY,
      parentId: province2.id,
      isDisabled: DisabledStatus.ENABLED
    });

    // 创建启用状态的区县
    const district101 = await TestDataFactory.createTestArea(dataSource, {
      name: '朝阳区',
      level: AreaLevel.DISTRICT,
      parentId: city12.id,
      isDisabled: DisabledStatus.ENABLED
    });
    const district102 = await TestDataFactory.createTestArea(dataSource, {
      name: '海淀区',
      level: AreaLevel.DISTRICT,
      parentId: city13.id,
      isDisabled: DisabledStatus.ENABLED
    });
    const district103 = await TestDataFactory.createTestArea(dataSource, {
      name: '西城区',
      level: AreaLevel.DISTRICT,
      parentId: city12.id,
      isDisabled: DisabledStatus.ENABLED
    });
    const district201 = await TestDataFactory.createTestArea(dataSource, {
      name: '浦东新区',
      level: AreaLevel.DISTRICT,
      parentId: city22.id,
      isDisabled: DisabledStatus.ENABLED
    });

    // 创建禁用状态的区域用于测试过滤
    const disabledProvince = await TestDataFactory.createTestArea(dataSource, {
      name: '禁用省份',
      level: AreaLevel.PROVINCE,
      isDisabled: DisabledStatus.DISABLED
    });
    const disabledCity = await TestDataFactory.createTestArea(dataSource, {
      name: '禁用城市',
      level: AreaLevel.CITY,
      parentId: province3.id,
      isDisabled: DisabledStatus.DISABLED
    });
    const disabledDistrict = await TestDataFactory.createTestArea(dataSource, {
      name: '禁用区县',
      level: AreaLevel.DISTRICT,
      parentId: city12.id,
      isDisabled: DisabledStatus.DISABLED
    });

    testAreas = [
      province1, province2, province3,
      city11, city12, city13, city21, city22,
      district101, district102, district103, district201,
      disabledProvince, disabledCity, disabledDistrict
    ];
  });

  describe('GET /areas/provinces', () => {
    it('应该成功获取启用状态的省份列表', async () => {
      const response = await client.provinces.$get({
        query: TestQueryFactory.createProvincesQuery()
      });

      IntegrationTestAssertions.expectStatus(response, 200);

      if (response.status === 200) {
        const data = await response.json();

        // 验证响应数据格式
        expect(data).toHaveProperty('success', true);
        expect(data).toHaveProperty('data');
        expect(data.data).toHaveProperty('provinces');
        expect(data.data).toHaveProperty('pagination');

        // 验证只返回启用状态的省份
        const provinces = data.data.provinces;
        expect(provinces).toHaveLength(3); // 只返回3个启用状态的省份

        // 验证不包含禁用状态的省份
        const disabledProvince = provinces.find((p: any) => p.isDisabled === DisabledStatus.DISABLED);
        expect(disabledProvince).toBeUndefined();

        // 验证分页信息
        expect(data.data.pagination).toEqual({
          page: 1,
          pageSize: 50,
          total: 3,
          totalPages: 1
        });
      }
    });

    it('应该正确处理分页参数', async () => {
      const response = await client.provinces.$get({
        query: TestQueryFactory.createPaginationQuery(1, 2)
      });

      IntegrationTestAssertions.expectStatus(response, 200);

      if (response.status === 200) {
        const data = await response.json();

        // 验证分页结果
        expect(data.data.provinces).toHaveLength(2);
        expect(data.data.pagination).toEqual({
          page: 1,
          pageSize: 2,
          total: 3,
          totalPages: 2
        });
      }
    });
  });

  describe('GET /areas/cities', () => {
    it('应该成功获取指定省份下启用状态的城市列表', async () => {
      const response = await client.cities.$get({
        query: TestQueryFactory.createCitiesQuery(testAreas[0].id)
      });

      IntegrationTestAssertions.expectStatus(response, 200);

      if (response.status === 200) {
        const data = await response.json();

        // 验证响应数据格式
        expect(data).toHaveProperty('success', true);
        expect(data).toHaveProperty('data');
        expect(data.data).toHaveProperty('cities');

        // 验证只返回启用状态的城市
        const cities = data.data.cities;
        expect(cities).toHaveLength(3); // 北京市下有3个启用状态的城市

        // 验证城市数据正确
        const cityNames = cities.map((c: any) => c.name);
        expect(cityNames).toContain('北京市');
        expect(cityNames).toContain('朝阳区');
        expect(cityNames).toContain('海淀区');

        // 验证不包含禁用状态的城市
        const disabledCity = cities.find((c: any) => c.name === '禁用城市');
        expect(disabledCity).toBeUndefined();
      }
    });

    it('应该处理不存在的省份ID', async () => {
      const response = await client.cities.$get({
        query: TestQueryFactory.createCitiesQuery(999)
      });

      IntegrationTestAssertions.expectStatus(response, 200);

      if (response.status === 200) {
        const data = await response.json();

        // 不存在的省份应该返回空数组
        expect(data.data.cities).toHaveLength(0);
      }
    });

    it('应该验证省份ID参数', async () => {
      const response = await client.cities.$get({
        query: TestQueryFactory.createCitiesQuery(0)
      });

      // 参数验证应该返回400错误
      IntegrationTestAssertions.expectStatus(response, 400);
    });
  });

  describe('GET /areas/districts', () => {
    it('应该成功获取指定城市下启用状态的区县列表', async () => {
      // 找到朝阳区城市对象
      const chaoyangCity = testAreas.find(area => area.name === '朝阳区' && area.level === AreaLevel.CITY);
      expect(chaoyangCity).toBeDefined();

      const response = await client.districts.$get({
        query: TestQueryFactory.createDistrictsQuery(chaoyangCity!.id)
      });

      IntegrationTestAssertions.expectStatus(response, 200);

      if (response.status === 200) {
        const data = await response.json();

        // 验证响应数据格式
        expect(data).toHaveProperty('success', true);
        expect(data).toHaveProperty('data');
        expect(data.data).toHaveProperty('districts');

        // 验证只返回启用状态的区县
        const districts = data.data.districts;
        expect(districts).toHaveLength(2); // 朝阳区下有2个启用状态的区县

        // 验证区县数据正确
        const districtNames = districts.map((d: any) => d.name);
        expect(districtNames).toContain('朝阳区');
        expect(districtNames).toContain('西城区');

        // 验证不包含禁用状态的区县
        const disabledDistrict = districts.find((d: any) => d.name === '禁用区县');
        expect(disabledDistrict).toBeUndefined();
      }
    });

    it('应该处理不存在的城市ID', async () => {
      const response = await client.districts.$get({
        query: TestQueryFactory.createDistrictsQuery(999)
      });

      IntegrationTestAssertions.expectStatus(response, 200);

      if (response.status === 200) {
        const data = await response.json();

        // 不存在的城市应该返回空数组
        expect(data.data.districts).toHaveLength(0);
      }
    });

    it('应该验证城市ID参数', async () => {
      const response = await client.districts.$get({
        query: TestQueryFactory.createDistrictsQuery(0)
      });

      // 参数验证应该返回400错误
      IntegrationTestAssertions.expectStatus(response, 400);
    });
  });

  describe('过滤禁用状态验证', () => {
    it('应该确保所有API只返回启用状态的区域', async () => {
      // 测试省份API
      const provincesResponse = await client.provinces.$get({
        query: TestQueryFactory.createProvincesQuery()
      });
      IntegrationTestAssertions.expectStatus(provincesResponse, 200);
      const provincesData = await provincesResponse.json();

      // 验证省份不包含禁用状态
      if ('data' in provincesData) {
        const provinces = provincesData.data.provinces;
        const hasDisabledProvince = provinces.some((p: any) => p.isDisabled === DisabledStatus.DISABLED);
        expect(hasDisabledProvince).toBe(false);
      }

      // 测试城市API
      const citiesResponse = await client.cities.$get({
        query: TestQueryFactory.createCitiesQuery(testAreas[0].id)
      });
      IntegrationTestAssertions.expectStatus(citiesResponse, 200);
      const citiesData = await citiesResponse.json();

      // 验证城市不包含禁用状态
      if ('data' in citiesData) {
        const cities = citiesData.data.cities;
        const hasDisabledCity = cities.some((c: any) => c.isDisabled === DisabledStatus.DISABLED);
        expect(hasDisabledCity).toBe(false);
      }

      // 测试区县API
      const chaoyangCity = testAreas.find(area => area.name === '朝阳区' && area.level === AreaLevel.CITY);
      const districtsResponse = await client.districts.$get({
        query: TestQueryFactory.createDistrictsQuery(chaoyangCity!.id)
      });
      IntegrationTestAssertions.expectStatus(districtsResponse, 200);
      const districtsData = await districtsResponse.json();

      // 验证区县不包含禁用状态
      if ('data' in districtsData) {
        const districts = districtsData.data.districts;
        const hasDisabledDistrict = districts.some((d: any) => d.isDisabled === DisabledStatus.DISABLED);
        expect(hasDisabledDistrict).toBe(false);
      }
    });
  });

  describe('租户数据隔离测试', () => {
    beforeEach(async () => {
      // 为租户2创建测试数据
      const dataSource = await IntegrationTestDatabase.getDataSource();

      // 租户2的省份
      await TestDataFactory.createTestArea(dataSource, {
        name: '租户2-北京市',
        level: AreaLevel.PROVINCE,
        isDisabled: DisabledStatus.ENABLED,
        tenantId: 2
      });

      // 租户2的城市
      await TestDataFactory.createTestArea(dataSource, {
        name: '租户2-上海市',
        level: AreaLevel.PROVINCE,
        isDisabled: DisabledStatus.ENABLED,
        tenantId: 2
      });
    });

    it('应该只返回指定租户的数据', async () => {
      // 测试租户1的数据
      const response1 = await client.provinces.$get({
        query: TestQueryFactory.createProvincesQuery()
      });

      IntegrationTestAssertions.expectStatus(response1, 200);
      const data1 = await response1.json();

      // 验证租户1只看到租户1的数据
      const successData1 = data1 as SuccessResponse;
      if (successData1.success) {
        const tenant1Provinces = successData1.data.provinces;
        expect(tenant1Provinces).toHaveLength(3); // 租户1有3个省份
        const hasTenant2Data = tenant1Provinces.some((p: any) => p.name.includes('租户2'));
        expect(hasTenant2Data).toBe(false);
      } else {
        throw new Error('租户1数据获取失败');
      }

      // 测试租户2的数据
      const response2 = await client.provinces.$get({
        query: { tenantId: 2, page: 1, pageSize: 50 }
      });

      IntegrationTestAssertions.expectStatus(response2, 200);
      const data2 = await response2.json();

      // 验证租户2只看到租户2的数据
      const successData2 = data2 as SuccessResponse;
      if (successData2.success) {
        const tenant2Provinces = successData2.data.provinces;
        expect(tenant2Provinces).toHaveLength(2); // 租户2有2个省份
        const hasTenant1Data = tenant2Provinces.some((p: any) => p.name.includes('北京市') && !p.name.includes('租户2'));
        expect(hasTenant1Data).toBe(false);
      } else {
        throw new Error('租户2数据获取失败');
      }
    });

    it('不同租户的数据应该完全隔离', async () => {
      // 租户1查询省份
      const response1 = await client.provinces.$get({
        query: TestQueryFactory.createProvincesQuery()
      });

      IntegrationTestAssertions.expectStatus(response1, 200);
      const data1 = await response1.json();

      // 租户2查询省份
      const response2 = await client.provinces.$get({
        query: { tenantId: 2, page: 1, pageSize: 50 }
      });

      IntegrationTestAssertions.expectStatus(response2, 200);
      const data2 = await response2.json();

      // 验证两个租户的数据完全不同
      const successData1 = data1 as SuccessResponse;
      const successData2 = data2 as SuccessResponse;
      if (successData1.success && successData2.success) {
        const tenant1Names = successData1.data.provinces.map((p: any) => p.name);
        const tenant2Names = successData2.data.provinces.map((p: any) => p.name);

        expect(tenant1Names).not.toEqual(tenant2Names);
        expect(tenant1Names).toContain('北京市');
        expect(tenant1Names).toContain('上海市');
        expect(tenant1Names).toContain('广东省');
        expect(tenant2Names).toContain('租户2-北京市');
        expect(tenant2Names).toContain('租户2-上海市');
      } else {
        throw new Error('租户数据获取失败');
      }
    });

    it('应该验证tenantId参数', async () => {
      // 测试缺少tenantId参数 - 明确排除tenantId
      const response = await client.provinces.$get({
        query: { page: 1, pageSize: 50 } as any // 不包含tenantId，使用any绕过类型检查
      });

      // 应该返回400错误，因为缺少必需的tenantId参数
      IntegrationTestAssertions.expectStatus(response, 400);
    });

    it('应该处理不存在的租户ID', async () => {
      const response = await client.provinces.$get({
        query: { tenantId: 999, page: 1, pageSize: 50 }
      });

      IntegrationTestAssertions.expectStatus(response, 200);
      const data = await response.json();

      // 不存在的租户应该返回空数组
      const successData = data as SuccessResponse;
      if (successData.success) {
        expect(successData.data.provinces).toHaveLength(0);
      } else {
        throw new Error('不存在的租户数据获取失败');
      }
    });
  });
});