import { describe, it, expect, beforeEach } from 'vitest';
import { testClient } from 'hono/testing';
import {
  IntegrationTestDatabase,
  setupIntegrationDatabaseHooks,
  TestDataFactory
} from '~/utils/server/integration-test-db';
import { IntegrationTestAssertions } from '~/utils/server/integration-test-utils';
import { routesRoutesExport } from '@d8d/server/api';
import { VehicleType, TravelMode } from '@d8d/server/modules/routes/route.schema';

// 设置集成测试钩子
setupIntegrationDatabaseHooks()

describe('用户端路线搜索API集成测试', () => {
  let client: ReturnType<typeof testClient<typeof routesRoutesExport>>['api']['v1'];

  beforeEach(async () => {
    // 创建测试客户端
    client = testClient(routesRoutesExport).api.v1;

    // 创建测试数据
    const dataSource = await IntegrationTestDatabase.getDataSource();
    if (!dataSource) throw new Error('Database not initialized');

    // 创建测试活动
    const activity1 = await TestDataFactory.createTestActivity(dataSource, {
      name: '测试活动1'
    });
    const activity2 = await TestDataFactory.createTestActivity(dataSource, {
      name: '测试活动2'
    });

    // 创建测试路线，覆盖所有组合查询场景
    // 大巴拼车路线
    await TestDataFactory.createTestRoute(dataSource, {
      name: '大巴拼车路线1',
      vehicleType: VehicleType.BUS,
      travelMode: TravelMode.CARPOOL,
      activityId: activity1.id,
      price: 100,
      availableSeats: 30
    });

    await TestDataFactory.createTestRoute(dataSource, {
      name: '大巴拼车路线2',
      vehicleType: VehicleType.BUS,
      travelMode: TravelMode.CARPOOL,
      activityId: activity2.id,
      price: 120,
      availableSeats: 25
    });

    // 商务车路线（拼车）
    await TestDataFactory.createTestRoute(dataSource, {
      name: '商务车拼车路线',
      vehicleType: VehicleType.BUSINESS,
      travelMode: TravelMode.CARPOOL,
      activityId: activity1.id,
      price: 200,
      availableSeats: 4
    });

    // 商务车路线（包车）
    await TestDataFactory.createTestRoute(dataSource, {
      name: '商务车包车路线',
      vehicleType: VehicleType.BUSINESS,
      travelMode: TravelMode.CHARTER,
      activityId: activity2.id,
      price: 500,
      availableSeats: 4
    });

    // 大巴包车路线
    await TestDataFactory.createTestRoute(dataSource, {
      name: '大巴包车路线',
      vehicleType: VehicleType.BUS,
      travelMode: TravelMode.CHARTER,
      activityId: activity1.id,
      price: 800,
      availableSeats: 40
    });

    // 中巴拼车路线（用于验证排除逻辑）
    await TestDataFactory.createTestRoute(dataSource, {
      name: '中巴拼车路线',
      vehicleType: VehicleType.MINIBUS,
      travelMode: TravelMode.CARPOOL,
      activityId: activity1.id,
      price: 150,
      availableSeats: 15
    });

    // 小车包车路线（用于验证排除逻辑）
    await TestDataFactory.createTestRoute(dataSource, {
      name: '小车包车路线',
      vehicleType: VehicleType.CAR,
      travelMode: TravelMode.CHARTER,
      activityId: activity2.id,
      price: 300,
      availableSeats: 3
    });
  });

  describe('组合查询逻辑测试', () => {
    it('应该正确查询大巴拼车组合', async () => {
      const response = await client.routes.search.$get({
        query: {
          vehicleType: 'bus',
          travelMode: 'carpool'
        }
      });

      IntegrationTestAssertions.expectStatus(response, 200);
      if (response.status === 200) {
        const responseData = await response.json();
        expect(responseData.success).toBe(true);
        expect(responseData.data.routes).toHaveLength(2);

        // 验证所有返回路线都是大巴拼车
        responseData.data.routes.forEach((route: any) => {
          expect(route.vehicleType).toBe(VehicleType.BUS);
          expect(route.travelMode).toBe(TravelMode.CARPOOL);
        });

        // 验证包含正确的路线
        const routeNames = responseData.data.routes.map((route: any) => route.name);
        expect(routeNames).toContain('大巴拼车路线1');
        expect(routeNames).toContain('大巴拼车路线2');

        // 验证不包含其他类型的路线
        expect(routeNames).not.toContain('商务车拼车路线');
        expect(routeNames).not.toContain('大巴包车路线');
      }
    });

    it('应该正确查询商务车组合（支持拼车和包车）', async () => {
      const response = await client.routes.search.$get({
        query: {
          vehicleType: 'business',
          travelMode: 'carpool,charter'
        }
      });

      IntegrationTestAssertions.expectStatus(response, 200);
      if (response.status === 200) {
        const responseData = await response.json();
        expect(responseData.success).toBe(true);
        expect(responseData.data.routes).toHaveLength(2);

        // 验证所有返回路线都是商务车
        responseData.data.routes.forEach((route: any) => {
          expect(route.vehicleType).toBe(VehicleType.BUSINESS);
        });

        // 验证包含商务车拼车和包车路线
        const routeNames = responseData.data.routes.map((route: any) => route.name);
        expect(routeNames).toContain('商务车拼车路线');
        expect(routeNames).toContain('商务车包车路线');

        // 验证不包含其他车型的路线
        expect(routeNames).not.toContain('大巴拼车路线1');
        expect(routeNames).not.toContain('中巴拼车路线');
      }
    });

    it('应该正确查询包车组合（支持大巴和商务车）', async () => {
      const response = await client.routes.search.$get({
        query: {
          vehicleType: 'bus,business',
          travelMode: 'charter'
        }
      });

      IntegrationTestAssertions.expectStatus(response, 200);
      if (response.status === 200) {
        const responseData = await response.json();
        expect(responseData.success).toBe(true);
        expect(responseData.data.routes).toHaveLength(2);

        // 验证所有返回路线都是包车
        responseData.data.routes.forEach((route: any) => {
          expect(route.travelMode).toBe(TravelMode.CHARTER);
        });

        // 验证包含大巴包车和商务车包车路线
        const routeNames = responseData.data.routes.map((route: any) => route.name);
        expect(routeNames).toContain('大巴包车路线');
        expect(routeNames).toContain('商务车包车路线');

        // 验证不包含拼车路线
        expect(routeNames).not.toContain('大巴拼车路线1');
        expect(routeNames).not.toContain('商务车拼车路线');
      }
    });

    it('应该支持多值车型参数查询', async () => {
      const response = await client.routes.search.$get({
        query: {
          vehicleType: 'bus,minibus',
          travelMode: 'carpool'
        }
      });

      IntegrationTestAssertions.expectStatus(response, 200);
      if (response.status === 200) {
        const responseData = await response.json();
        expect(responseData.success).toBe(true);

        // 验证包含大巴拼车和中巴拼车路线
        const routeNames = responseData.data.routes.map((route: any) => route.name);
        expect(routeNames).toContain('大巴拼车路线1');
        expect(routeNames).toContain('大巴拼车路线2');
        expect(routeNames).toContain('中巴拼车路线');

        // 验证不包含商务车和小车路线
        expect(routeNames).not.toContain('商务车拼车路线');
        expect(routeNames).not.toContain('小车包车路线');
      }
    });

    it('应该支持多值出行方式参数查询', async () => {
      const response = await client.routes.search.$get({
        query: {
          vehicleType: 'business',
          travelMode: 'carpool,charter'
        }
      });

      IntegrationTestAssertions.expectStatus(response, 200);
      if (response.status === 200) {
        const responseData = await response.json();
        expect(responseData.success).toBe(true);

        // 验证包含商务车拼车和包车路线
        const routeNames = responseData.data.routes.map((route: any) => route.name);
        expect(routeNames).toContain('商务车拼车路线');
        expect(routeNames).toContain('商务车包车路线');
      }
    });

    it('应该正确处理单个参数查询', async () => {
      // 只查询车型
      const response1 = await client.routes.search.$get({
        query: {
          vehicleType: 'bus'
        }
      });

      IntegrationTestAssertions.expectStatus(response1, 200);
      if (response1.status === 200) {
        const responseData = await response1.json();
        expect(responseData.success).toBe(true);

        // 验证包含所有大巴路线（拼车和包车）
        const routeNames = responseData.data.routes.map((route: any) => route.name);
        expect(routeNames).toContain('大巴拼车路线1');
        expect(routeNames).toContain('大巴拼车路线2');
        expect(routeNames).toContain('大巴包车路线');
      }

      // 只查询出行方式
      const response2 = await client.routes.search.$get({
        query: {
          travelMode: 'carpool'
        }
      });

      IntegrationTestAssertions.expectStatus(response2, 200);
      if (response2.status === 200) {
        const responseData = await response2.json();
        expect(responseData.success).toBe(true);

        // 验证包含所有拼车路线
        const routeNames = responseData.data.routes.map((route: any) => route.name);
        expect(routeNames).toContain('大巴拼车路线1');
        expect(routeNames).toContain('大巴拼车路线2');
        expect(routeNames).toContain('商务车拼车路线');
        expect(routeNames).toContain('中巴拼车路线');
      }
    });

    it('应该正确处理空参数查询', async () => {
      const response = await client.routes.search.$get({
        query: {}
      });

      IntegrationTestAssertions.expectStatus(response, 200);
      if (response.status === 200) {
        const responseData = await response.json();
        expect(responseData.success).toBe(true);

        // 验证返回所有路线
        expect(responseData.data.routes.length).toBeGreaterThan(0);
      }
    });

    it('应该正确处理无效参数', async () => {
      // 无效车型参数
      const response1 = await client.routes.search.$get({
        query: {
          vehicleType: 'invalid_vehicle'
        }
      });

      // 无效参数应该返回400错误
      IntegrationTestAssertions.expectStatus(response1, 400);
      if (response1.status === 400) {
        const responseData = await response1.json();
        console.debug('Invalid vehicle type response:', responseData);
        expect(responseData.success).toBe(false);
        expect(responseData.error.message).toContain('车型必须是有效的类型');
      }

      // 无效出行方式参数
      const response2 = await client.routes.search.$get({
        query: {
          travelMode: 'invalid_mode'
        }
      });

      // 无效参数应该返回400错误
      IntegrationTestAssertions.expectStatus(response2, 400);
      if (response2.status === 400) {
        const responseData = await response2.json();
        expect(responseData.success).toBe(false);
        expect(responseData.error.message).toContain('出行方式必须是有效的类型');
      }
    });
  });

  describe('组合查询与其他筛选条件结合测试', () => {
    it('应该支持组合查询与价格筛选结合', async () => {
      const response = await client.routes.search.$get({
        query: {
          vehicleType: 'bus',
          travelMode: 'carpool',
          minPrice: '110',
          maxPrice: '130'
        }
      });

      IntegrationTestAssertions.expectStatus(response, 200);
      if (response.status === 200) {
        const responseData = await response.json();
        expect(responseData.success).toBe(true);

        // 验证只返回价格在110-130之间的大巴拼车路线
        const routeNames = responseData.data.routes.map((route: any) => route.name);
        expect(routeNames).toContain('大巴拼车路线2'); // 价格120
        expect(routeNames).not.toContain('大巴拼车路线1'); // 价格100

        // 验证价格范围
        responseData.data.routes.forEach((route: any) => {
          expect(Number(route.price)).toBeGreaterThanOrEqual(110);
          expect(Number(route.price)).toBeLessThanOrEqual(130);
        });
      }
    });

    it('应该支持组合查询与活动筛选结合', async () => {
      const dataSource = await IntegrationTestDatabase.getDataSource();
      if (!dataSource) throw new Error('Database not initialized');

      const activity = await TestDataFactory.createTestActivity(dataSource, {
        name: '特定活动'
      });

      // 为特定活动创建路线
      await TestDataFactory.createTestRoute(dataSource, {
        name: '特定活动大巴拼车路线',
        vehicleType: VehicleType.BUS,
        travelMode: TravelMode.CARPOOL,
        activityId: activity.id,
        price: 150
      });

      const response = await client.routes.search.$get({
        query: {
          vehicleType: 'bus',
          travelMode: 'carpool'
        }
      });

      IntegrationTestAssertions.expectStatus(response, 200);
      if (response.status === 200) {
        const responseData = await response.json();
        expect(responseData.success).toBe(true);

        // 验证包含特定活动的路线
        const routeNames = responseData.data.routes.map((route: any) => route.name);
        expect(routeNames).toContain('特定活动大巴拼车路线');
      }
    });
  });

  describe('分页和排序测试', () => {
    it('应该支持组合查询的分页', async () => {
      const response = await client.routes.search.$get({
        query: {
          vehicleType: 'bus',
          travelMode: 'carpool',
          page: '1',
          pageSize: '1'
        }
      });

      IntegrationTestAssertions.expectStatus(response, 200);
      if (response.status === 200) {
        const responseData = await response.json();
        expect(responseData.success).toBe(true);

        // 验证分页信息
        expect(responseData.data.pagination.page).toBe(1);
        expect(responseData.data.pagination.pageSize).toBe(1);
        expect(responseData.data.pagination.total).toBe(2);
        expect(responseData.data.pagination.totalPages).toBe(2);

        // 验证只返回1条路线
        expect(responseData.data.routes).toHaveLength(1);
      }
    });

    it('应该支持组合查询的价格排序', async () => {
      const response = await client.routes.search.$get({
        query: {
          vehicleType: 'bus',
          travelMode: 'carpool',
          sortBy: 'price',
          sortOrder: 'ASC'
        }
      });

      IntegrationTestAssertions.expectStatus(response, 200);
      if (response.status === 200) {
        const responseData = await response.json();
        expect(responseData.success).toBe(true);

        // 验证路线按价格升序排列
        const prices = responseData.data.routes.map((route: any) => Number(route.price));
        expect(prices[0]).toBeLessThanOrEqual(prices[1]);
      }
    });
  });
});