import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
import { z } from '@hono/zod-openapi';
import { AppDataSource, ErrorSchema, ZodErrorSchema, parseWithAwait, createZodErrorResponse } from '@d8d/shared-utils';
import { authMiddleware } from '@d8d/auth-module';
import { AuthContext } from '@d8d/shared-types';
import { SalaryService } from '../services/salary.service';
import {
  SalaryLevelSchema,
  CreateSalarySchema,
  UpdateSalarySchema,
  QuerySalarySchema,
  GetSalaryByProvinceCitySchema
} from '../schemas/salary.schema';

// 创建薪资路由
const createSalaryRoute = createRoute({
  method: 'post',
  path: '/create',
  middleware: [authMiddleware],
  request: {
    body: {
      content: {
        'application/json': { schema: CreateSalarySchema }
      }
    }
  },
  responses: {
    200: {
      description: '薪资记录创建成功',
      content: {
        'application/json': { schema: SalaryLevelSchema }
      }
    },
    400: {
      description: '参数错误或区域重复',
      content: { 'application/json': { schema: ZodErrorSchema } }
    },
    401: {
      description: '认证失败',
      content: { 'application/json': { schema: ErrorSchema } }
    },
    500: {
      description: '创建薪资记录失败',
      content: { 'application/json': { schema: ErrorSchema } }
    }
  }
});

// 更新薪资路由
const updateSalaryRoute = createRoute({
  method: 'put',
  path: '/update/{id}',
  middleware: [authMiddleware],
  request: {
    params: z.object({
      id: z.coerce.number().int().positive().openapi({
        param: { name: 'id', in: 'path' },
        example: 1,
        description: '薪资ID'
      })
    }),
    body: {
      content: {
        'application/json': { schema: UpdateSalarySchema }
      }
    }
  },
  responses: {
    200: {
      description: '薪资记录更新成功',
      content: {
        'application/json': { schema: SalaryLevelSchema }
      }
    },
    400: {
      description: '参数错误或区域重复',
      content: { 'application/json': { schema: ZodErrorSchema } }
    },
    401: {
      description: '认证失败',
      content: { 'application/json': { schema: ErrorSchema } }
    },
    404: {
      description: '薪资记录不存在',
      content: { 'application/json': { schema: ErrorSchema } }
    },
    500: {
      description: '更新薪资记录失败',
      content: { 'application/json': { schema: ErrorSchema } }
    }
  }
});

// 删除薪资路由
const deleteSalaryRoute = createRoute({
  method: 'delete',
  path: '/delete/{id}',
  middleware: [authMiddleware],
  request: {
    params: z.object({
      id: z.coerce.number().int().positive().openapi({
        param: { name: 'id', in: 'path' },
        example: 1,
        description: '薪资ID'
      })
    })
  },
  responses: {
    200: {
      description: '薪资记录删除成功',
      content: {
        'application/json': {
          schema: z.object({
            success: z.boolean().openapi({ description: '是否成功' })
          })
        }
      }
    },
    400: {
      description: '参数错误',
      content: { 'application/json': { schema: ZodErrorSchema } }
    },
    401: {
      description: '认证失败',
      content: { 'application/json': { schema: ErrorSchema } }
    },
    404: {
      description: '薪资记录不存在',
      content: { 'application/json': { schema: ErrorSchema } }
    },
    500: {
      description: '删除薪资记录失败',
      content: { 'application/json': { schema: ErrorSchema } }
    }
  }
});

// 获取所有薪资路由 - 分页查询
const getAllSalariesRoute = createRoute({
  method: 'get',
  path: '/list',
  middleware: [authMiddleware],
  request: {
    query: QuerySalarySchema
  },
  responses: {
    200: {
      description: '获取薪资列表成功',
      content: {
        'application/json': {
          schema: z.object({
            data: z.array(SalaryLevelSchema).openapi({ description: '薪资列表' }),
            total: z.number().int().openapi({ description: '总记录数' })
          })
        }
      }
    },
    400: {
      description: '参数错误',
      content: { 'application/json': { schema: ZodErrorSchema } }
    },
    401: {
      description: '认证失败',
      content: { 'application/json': { schema: ErrorSchema } }
    },
    500: {
      description: '获取薪资列表失败',
      content: { 'application/json': { schema: ErrorSchema } }
    }
  }
});

// 获取单个薪资路由
const getSalaryByIdRoute = createRoute({
  method: 'get',
  path: '/detail/{id}',
  middleware: [authMiddleware],
  request: {
    params: z.object({
      id: z.coerce.number().int().positive().openapi({
        param: { name: 'id', in: 'path' },
        example: 1,
        description: '薪资ID'
      })
    })
  },
  responses: {
    200: {
      description: '获取薪资详情成功',
      content: {
        'application/json': { schema: SalaryLevelSchema.nullable() }
      }
    },
    400: {
      description: '参数错误',
      content: { 'application/json': { schema: ZodErrorSchema } }
    },
    401: {
      description: '认证失败',
      content: { 'application/json': { schema: ErrorSchema } }
    },
    404: {
      description: '薪资记录不存在',
      content: { 'application/json': { schema: ErrorSchema } }
    },
    500: {
      description: '获取薪资详情失败',
      content: { 'application/json': { schema: ErrorSchema } }
    }
  }
});

// 按省份城市查询薪资路由
const getSalaryByProvinceCityRoute = createRoute({
  method: 'get',
  path: '/byProvinceCity',
  middleware: [authMiddleware],
  request: {
    query: GetSalaryByProvinceCitySchema
  },
  responses: {
    200: {
      description: '获取薪资记录成功',
      content: {
        'application/json': { schema: SalaryLevelSchema.nullable() }
      }
    },
    400: {
      description: '参数错误',
      content: { 'application/json': { schema: ZodErrorSchema } }
    },
    401: {
      description: '认证失败',
      content: { 'application/json': { schema: ErrorSchema } }
    },
    404: {
      description: '薪资记录不存在',
      content: { 'application/json': { schema: ErrorSchema } }
    },
    500: {
      description: '获取薪资记录失败',
      content: { 'application/json': { schema: ErrorSchema } }
    }
  }
});

const app = new OpenAPIHono<AuthContext>()
  // 创建薪资
  .openapi(createSalaryRoute, async (c) => {
    try {
      const data = c.req.valid('json');
      const salaryService = new SalaryService(AppDataSource);

      const result = await salaryService.create(data);

      return c.json(await parseWithAwait(SalaryLevelSchema, result), 200);
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json(createZodErrorResponse(error), 400);
      }

      // 处理区域重复错误
      if (error instanceof Error && error.message.includes('该省份城市的薪资记录已存在')) {
        return c.json({
          code: 400,
          message: '该省份城市的薪资记录已存在',
          errors: []
        }, 400);
      }

      // 处理区域验证错误
      if (error instanceof Error && (
        error.message.includes('省份不存在') ||
        error.message.includes('城市不存在') ||
        error.message.includes('区县不存在') ||
        error.message.includes('不属于指定的')
      )) {
        return c.json({
          code: 400,
          message: error.message,
          errors: []
        }, 400);
      }

      return c.json({
        code: 500,
        message: error instanceof Error ? error.message : '创建薪资记录失败'
      }, 500);
    }
  })
  // 更新薪资
  .openapi(updateSalaryRoute, async (c) => {
    try {
      const { id } = c.req.valid('param');
      const data = c.req.valid('json');
      const salaryService = new SalaryService(AppDataSource);

      const result = await salaryService.update(id, data);

      if (!result) {
        return c.json({ code: 404, message: '薪资记录不存在' }, 404);
      }

      const validatedResult = await parseWithAwait(SalaryLevelSchema, result);
      return c.json(validatedResult, 200);
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json(createZodErrorResponse(error), 400);
      }

      // 处理区域重复错误
      if (error instanceof Error && error.message.includes('该省份城市的薪资记录已存在')) {
        return c.json({
          code: 400,
          message: '该省份城市的薪资记录已存在',
          errors: []
        }, 400);
      }

      // 处理区域验证错误
      if (error instanceof Error && (
        error.message.includes('省份不存在') ||
        error.message.includes('城市不存在') ||
        error.message.includes('区县不存在') ||
        error.message.includes('不属于指定的')
      )) {
        return c.json({
          code: 400,
          message: error.message,
          errors: []
        }, 400);
      }

      // 处理薪资不存在错误
      if (error instanceof Error && error.message.includes('薪资记录不存在')) {
        return c.json({
          code: 404,
          message: '薪资记录不存在'
        }, 404);
      }

      return c.json({
        code: 500,
        message: error instanceof Error ? error.message : '更新薪资记录失败'
      }, 500);
    }
  })
  // 删除薪资
  .openapi(deleteSalaryRoute, async (c) => {
    try {
      const { id } = c.req.valid('param');
      const salaryService = new SalaryService(AppDataSource);

      const success = await salaryService.delete(id);

      if (!success) {
        return c.json({ code: 404, message: '薪资记录不存在' }, 404);
      }

      return c.json({ success }, 200);
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json(createZodErrorResponse(error), 400);
      }

      return c.json({
        code: 500,
        message: error instanceof Error ? error.message : '删除薪资记录失败'
      }, 500);
    }
  })
  // 获取所有薪资
  .openapi(getAllSalariesRoute, async (c) => {
    try {
      const { provinceId, cityId, districtId, skip, take } = c.req.valid('query');
      const salaryService = new SalaryService(AppDataSource);

      const result = await salaryService.findAll(
        skip ?? 0,
        take ?? 10,
        provinceId,
        cityId,
        districtId
      );

      // 使用parseWithAwait验证每个薪资记录
      const validatedData = await Promise.all(
        result.data.map(item => parseWithAwait(SalaryLevelSchema, item))
      );

      return c.json({ data: validatedData, total: result.total }, 200);
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json(createZodErrorResponse(error), 400);
      }

      return c.json({
        code: 500,
        message: error instanceof Error ? error.message : '获取薪资列表失败'
      }, 500);
    }
  })
  // 获取单个薪资
  .openapi(getSalaryByIdRoute, async (c) => {
    try {
      const { id } = c.req.valid('param');
      const salaryService = new SalaryService(AppDataSource);

      const result = await salaryService.findOne(id);

      if (!result) {
        return c.json({ code: 404, message: '薪资记录不存在' }, 404);
      }

      const validatedResult = await parseWithAwait(SalaryLevelSchema, result);
      return c.json(validatedResult, 200);
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json(createZodErrorResponse(error), 400);
      }

      return c.json({
        code: 500,
        message: error instanceof Error ? error.message : '获取薪资详情失败'
      }, 500);
    }
  })
  // 按省份城市查询薪资
  .openapi(getSalaryByProvinceCityRoute, async (c) => {
    try {
      const { provinceId, cityId } = c.req.valid('query');
      const salaryService = new SalaryService(AppDataSource);

      const result = await salaryService.findByProvinceCity(provinceId, cityId);

      if (!result) {
        return c.json({ code: 404, message: '该省份城市的薪资记录不存在' }, 404);
      }

      const validatedResult = await parseWithAwait(SalaryLevelSchema, result);
      return c.json(validatedResult, 200);
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json(createZodErrorResponse(error), 400);
      }

      if (error instanceof Error && error.message.includes('该省份城市的薪资记录不存在')) {
        return c.json({
          code: 404,
          message: '该省份城市的薪资记录不存在'
        }, 404);
      }

      return c.json({
        code: 500,
        message: error instanceof Error ? error.message : '获取薪资记录失败'
      }, 500);
    }
  });

export default app;