import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
import { z } from '@hono/zod-openapi';
import { AppDataSource } from '../../data-source';
import { RouteService } from '../../modules/routes/route.service';
import { VehicleType, TravelMode } from '../../modules/routes/route.schema';

// 路线搜索参数Schema
const searchRoutesSchema = z.object({
  startLocationId: z.coerce.number().int().positive('出发地ID必须为正整数').optional().openapi({
    example: 1,
    description: '出发地ID'
  }),
  endLocationId: z.coerce.number().int().positive('目的地ID必须为正整数').optional().openapi({
    example: 2,
    description: '目的地ID'
  }),
  startAreaIds: z.string().optional().openapi({
    example: '[1,34,1001]',
    description: '出发地区ID数组 [provinceId,cityId,districtId]'
  }),
  endAreaIds: z.string().optional().openapi({
    example: '[2,35,1002]',
    description: '目的地区ID数组 [provinceId,cityId,districtId]'
  }),
  date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, '日期格式必须为YYYY-MM-DD').optional().openapi({
    example: '2025-10-18',
    description: '出发日期'
  }),
  routeType: z.enum(['departure', 'return']).optional().openapi({
    example: 'departure',
    description: '路线类型'
  }),
  minPrice: z.coerce.number().min(0, '最低价格不能为负数').optional().openapi({
    example: 100,
    description: '最低价格'
  }),
  maxPrice: z.coerce.number().min(0, '最高价格不能为负数').optional().openapi({
    example: 500,
    description: '最高价格'
  }),
  vehicleType: z.string().optional()
    .refine(
      (val) => !val || val.split(',').every(type => Object.values(VehicleType).includes(type as VehicleType)),
      { message: '车型必须是有效的类型(bus/minibus/car/business)' }
    )
    .openapi({
      example: 'bus',
      description: '车型，支持逗号分隔的多个值，如：bus,business'
    }),
  travelMode: z.string().optional()
    .refine(
      (val) => !val || val.split(',').every(mode => Object.values(TravelMode).includes(mode as TravelMode)),
      { message: '出行方式必须是有效的类型(carpool/charter)' }
    )
    .openapi({
      example: 'carpool',
      description: '出行方式，支持逗号分隔的多个值，如：carpool,charter'
    }),
  sortBy: z.enum(['price', 'departureTime']).default('departureTime').openapi({
    example: 'departureTime',
    description: '排序字段'
  }),
  sortOrder: z.enum(['ASC', 'DESC']).default('ASC').openapi({
    example: 'ASC',
    description: '排序方向'
  }),
  page: z.coerce.number().int().min(1).default(1).openapi({
    example: 1,
    description: '页码'
  }),
  pageSize: z.coerce.number().int().min(1).max(50).default(20).openapi({
    example: 20,
    description: '每页数量'
  }),
});

// 路线搜索结果Schema
const routeSearchResultSchema = z.object({
  success: z.boolean(),
  data: z.object({
    routes: z.array(z.object({
      id: z.number(),
      name: z.string(),
      description: z.string().nullable(),
      startLocationId: z.number(),
      endLocationId: z.number(),
      startLocation: z.object({
        id: z.number(),
        name: z.string(),
        provinceId: z.number(),
        cityId: z.number(),
        districtId: z.number(),
        address: z.string(),
        province: z.object({
          id: z.number(),
          name: z.string(),
          level: z.number(),
          code: z.string(),
          isDisabled: z.number(),
          isDeleted: z.number(),
          createdBy: z.number().nullable(),
          updatedBy: z.number().nullable(),
          createdAt: z.string(),
          updatedAt: z.string()
        }).nullable(),
        city: z.object({
          id: z.number(),
          name: z.string(),
          level: z.number(),
          code: z.string(),
          isDisabled: z.number(),
          isDeleted: z.number(),
          createdBy: z.number().nullable(),
          updatedBy: z.number().nullable(),
          createdAt: z.string(),
          updatedAt: z.string()
        }).nullable(),
        district: z.object({
          id: z.number(),
          name: z.string(),
          level: z.number(),
          code: z.string(),
          isDisabled: z.number(),
          isDeleted: z.number(),
          createdBy: z.number().nullable(),
          updatedBy: z.number().nullable(),
          createdAt: z.string(),
          updatedAt: z.string()
        }).nullable()
      }),
      endLocation: z.object({
        id: z.number(),
        name: z.string(),
        provinceId: z.number(),
        cityId: z.number(),
        districtId: z.number(),
        address: z.string(),
        province: z.object({
          id: z.number(),
          name: z.string(),
          level: z.number(),
          code: z.string(),
          isDisabled: z.number(),
          isDeleted: z.number(),
          createdBy: z.number().nullable(),
          updatedBy: z.number().nullable(),
          createdAt: z.string(),
          updatedAt: z.string()
        }).nullable(),
        city: z.object({
          id: z.number(),
          name: z.string(),
          level: z.number(),
          code: z.string(),
          isDisabled: z.number(),
          isDeleted: z.number(),
          createdBy: z.number().nullable(),
          updatedBy: z.number().nullable(),
          createdAt: z.string(),
          updatedAt: z.string()
        }).nullable(),
        district: z.object({
          id: z.number(),
          name: z.string(),
          level: z.number(),
          code: z.string(),
          isDisabled: z.number(),
          isDeleted: z.number(),
          createdBy: z.number().nullable(),
          updatedBy: z.number().nullable(),
          createdAt: z.string(),
          updatedAt: z.string()
        }).nullable()
      }),
      pickupPoint: z.string(),
      dropoffPoint: z.string(),
      departureTime: z.string(),
      vehicleType: z.nativeEnum(VehicleType),
      travelMode: z.nativeEnum(TravelMode),
      price: z.number(),
      seatCount: z.number(),
      availableSeats: z.number(),
      activityId: z.number(),
      activity: z.object({
        id: z.number(),
        name: z.string(),
        description: z.string().nullable(),
        venueLocationId: z.number(),
        venueLocation: z.object({
          id: z.number(),
          name: z.string(),
          provinceId: z.number(),
          cityId: z.number(),
          districtId: z.number(),
          address: z.string()
        }),
        startDate: z.string(),
        endDate: z.string()
      }),
      routeType: z.enum(['departure', 'return']),
      isDisabled: z.number(),
      isDeleted: z.number(),
      createdBy: z.number().nullable(),
      updatedBy: z.number().nullable(),
      createdAt: z.string(),
      updatedAt: z.string()
    })),
    activities: z.array(z.object({
      id: z.number(),
      name: z.string(),
      description: z.string().nullable(),
      venueLocationId: z.number(),
      venueLocation: z.object({
        id: z.number(),
        name: z.string(),
        provinceId: z.number(),
        cityId: z.number(),
        districtId: z.number(),
        address: z.string()
      }),
      startDate: z.string(),
      endDate: z.string()
    })),
    pagination: z.object({
      page: z.number(),
      pageSize: z.number(),
      total: z.number(),
      totalPages: z.number()
    })
  }),
  message: z.string()
});

// 错误响应Schema
const errorSchema = z.object({
  code: z.number(),
  message: z.string(),
});

// Zod验证错误Schema
const zodErrorSchema = z.object({
  success: z.boolean(),
  error: z.object({
    name: z.string(),
    message: z.string()
  })
});

// 创建路线搜索路由
const searchRoutesRoute = createRoute({
  method: 'get',
  path: '/search',
  request: {
    query: searchRoutesSchema
  },
  responses: {
    200: {
      description: '路线搜索成功',
      content: {
        'application/json': { schema: routeSearchResultSchema }
      }
    },
    400: {
      description: '参数错误',
      content: { 'application/json': { schema: zodErrorSchema } }
    },
    500: {
      description: '搜索路线失败',
      content: { 'application/json': { schema: errorSchema } }
    }
  }
});

// 获取单个路线详情Schema
const getRouteSchema = z.object({
  id: z.coerce.number<number>().int().positive('路线ID必须为正整数')
});

// 单个路线响应Schema
const routeResponseSchema = z.object({
  success: z.boolean(),
  data: z.object({
    id: z.number(),
    name: z.string(),
    description: z.string().nullable(),
    startLocationId: z.number(),
    endLocationId: z.number(),
    startLocation: z.object({
      id: z.number(),
      name: z.string(),
      provinceId: z.number(),
      cityId: z.number(),
      districtId: z.number(),
      address: z.string(),
      province: z.object({
        id: z.number(),
        name: z.string(),
        level: z.number(),
        code: z.string(),
        isDisabled: z.number(),
        isDeleted: z.number(),
        createdBy: z.number().nullable(),
        updatedBy: z.number().nullable(),
        createdAt: z.string(),
        updatedAt: z.string()
      }).nullable(),
      city: z.object({
        id: z.number(),
        name: z.string(),
        level: z.number(),
        code: z.string(),
        isDisabled: z.number(),
        isDeleted: z.number(),
        createdBy: z.number().nullable(),
        updatedBy: z.number().nullable(),
        createdAt: z.string(),
        updatedAt: z.string()
      }).nullable(),
      district: z.object({
        id: z.number(),
        name: z.string(),
        level: z.number(),
        code: z.string(),
        isDisabled: z.number(),
        isDeleted: z.number(),
        createdBy: z.number().nullable(),
        updatedBy: z.number().nullable(),
        createdAt: z.string(),
        updatedAt: z.string()
      }).nullable()
    }),
    endLocation: z.object({
      id: z.number(),
      name: z.string(),
      provinceId: z.number(),
      cityId: z.number(),
      districtId: z.number(),
      address: z.string(),
      province: z.object({
        id: z.number(),
        name: z.string(),
        level: z.number(),
        code: z.string(),
        isDisabled: z.number(),
        isDeleted: z.number(),
        createdBy: z.number().nullable(),
        updatedBy: z.number().nullable(),
        createdAt: z.string(),
        updatedAt: z.string()
      }).nullable(),
      city: z.object({
        id: z.number(),
        name: z.string(),
        level: z.number(),
        code: z.string(),
        isDisabled: z.number(),
        isDeleted: z.number(),
        createdBy: z.number().nullable(),
        updatedBy: z.number().nullable(),
        createdAt: z.string(),
        updatedAt: z.string()
      }).nullable(),
      district: z.object({
        id: z.number(),
        name: z.string(),
        level: z.number(),
        code: z.string(),
        isDisabled: z.number(),
        isDeleted: z.number(),
        createdBy: z.number().nullable(),
        updatedBy: z.number().nullable(),
        createdAt: z.string(),
        updatedAt: z.string()
      }).nullable()
    }),
    pickupPoint: z.string(),
    dropoffPoint: z.string(),
    departureTime: z.string(),
    vehicleType: z.nativeEnum(VehicleType),
    travelMode: z.nativeEnum(TravelMode),
    price: z.number(),
    seatCount: z.number(),
    availableSeats: z.number(),
    activityId: z.number(),
    activity: z.object({
      id: z.number(),
      name: z.string(),
      description: z.string().nullable(),
      venueLocationId: z.number(),
      venueLocation: z.object({
        id: z.number(),
        name: z.string(),
        provinceId: z.number(),
        cityId: z.number(),
        districtId: z.number(),
        address: z.string()
      }),
      startDate: z.string(),
      endDate: z.string()
    }),
    routeType: z.enum(['departure', 'return']),
    isDisabled: z.number(),
    isDeleted: z.number(),
    createdBy: z.number().nullable(),
    updatedBy: z.number().nullable(),
    createdAt: z.string(),
    updatedAt: z.string()
  }),
  message: z.string()
});

// 创建获取单个路线详情路由
const getRouteRoute = createRoute({
  method: 'get',
  path: '/{id}',
  request: {
    params: getRouteSchema
  },
  responses: {
    200: {
      description: '获取路线详情成功',
      content: {
        'application/json': { schema: routeResponseSchema }
      }
    },
    404: {
      description: '路线不存在',
      content: { 'application/json': { schema: errorSchema } }
    },
    500: {
      description: '获取路线详情失败',
      content: { 'application/json': { schema: errorSchema } }
    }
  }
});

const app = new OpenAPIHono()
  .openapi(searchRoutesRoute, async (c) => {
    try {
      const {
        startLocationId,
        endLocationId,
        startAreaIds,
        endAreaIds,
        routeType,
        minPrice,
        maxPrice,
        vehicleType,
        travelMode,
        sortBy,
        sortOrder,
        page,
        pageSize
      } = c.req.valid('query');

      // 初始化路线服务
      const routeService = new RouteService(AppDataSource);

      // 解析省市区ID数组
      const parsedStartAreaIds = startAreaIds ? JSON.parse(startAreaIds) : undefined;
      const parsedEndAreaIds = endAreaIds ? JSON.parse(endAreaIds) : undefined;

      // 解析车型参数 - 支持逗号分隔的多值
      const parsedVehicleType = vehicleType ?
        (vehicleType.includes(',') ? vehicleType.split(',') as VehicleType[] : vehicleType as VehicleType) :
        undefined;

      // 解析出行方式参数 - 支持逗号分隔的多值
      const parsedTravelMode = travelMode ?
        (travelMode.includes(',') ? travelMode.split(',') as TravelMode[] : travelMode as TravelMode) :
        undefined;

      // 调用路线服务进行查询
      const result = await routeService.searchRoutes({
        startLocationId,
        endLocationId,
        startAreaIds: parsedStartAreaIds,
        endAreaIds: parsedEndAreaIds,
        routeType: routeType as 'departure' | 'return',
        minPrice,
        maxPrice,
        vehicleType: parsedVehicleType,
        travelMode: parsedTravelMode,
        sortBy: sortBy as 'price' | 'departureTime',
        sortOrder: sortOrder as 'ASC' | 'DESC',
        page,
        pageSize
      });

      return c.json({
        success: true,
        data: {
          routes: result.routes,
          activities: result.activities,
          pagination: result.pagination
        },
        message: '搜索路线成功'
      }, 200);
    } catch (error) {
      console.error('搜索路线失败:', error);
      return c.json({
        code: 500,
        message: error instanceof Error ? error.message : '搜索路线失败'
      }, 500);
    }
  })
  .openapi(getRouteRoute, async (c) => {
  try {
    const { id } = c.req.valid('param');

    // 初始化路线服务
    const routeService = new RouteService(AppDataSource);

    // 获取路线详情
    const route = await routeService.getRouteById(id);
    if (!route) {
      return c.json({
        code: 404,
        message: '路线不存在'
      }, 404);
    }

    return c.json({
      success: true,
      data: route,
      message: '获取路线详情成功'
    }, 200);
  } catch (error) {
    console.error('获取路线详情失败:', error);
    return c.json({
      code: 500,
      message: error instanceof Error ? error.message : '获取路线详情失败'
    }, 500);
  }
});

export default app;