import { createRoute, OpenAPIHono , extendZodWithOpenApi} from '@hono/zod-openapi';
import { z } from '@hono/zod-openapi';
import { CrudOptions } from './generic-crud.service';
import { ErrorSchema } from './errorHandler';
import { AuthContext } from '../types/context';
import { ObjectLiteral } from 'typeorm';
import { parseWithAwait } from './parseWithAwait';
import { ConcreteCrudService } from './concrete-crud.service';

extendZodWithOpenApi(z)

export function createCrudRoutes<
  T extends ObjectLiteral,
  CreateSchema extends z.ZodSchema = z.ZodSchema,
  UpdateSchema extends z.ZodSchema = z.ZodSchema,
  GetSchema extends z.ZodSchema = z.ZodSchema,
  ListSchema extends z.ZodSchema = z.ZodSchema
>(options: CrudOptions<T, CreateSchema, UpdateSchema, GetSchema, ListSchema>) {
  const { entity, createSchema, updateSchema, getSchema, listSchema, searchFields, relations, middleware = [], userTracking, relationFields, readOnly = false } = options;
  
  // 创建路由实例
  const app = new OpenAPIHono<AuthContext>();
  
  // 分页查询路由
  const listRoute = createRoute({
    method: 'get',
    path: '/',
    middleware,
    request: {
      query: z.object({
        page: z.coerce.number<number>().int().positive().default(1).openapi({
          example: 1,
          description: '页码，从1开始'
        }),
        pageSize: z.coerce.number<number>().int().positive().default(10).openapi({
          example: 10,
          description: '每页数量'
        }),
        keyword: z.string().optional().openapi({
          example: '搜索关键词',
          description: '搜索关键词'
        }),
        sortBy: z.string().optional().openapi({
          example: 'createdAt',
          description: '排序字段'
        }),
        sortOrder: z.enum(['ASC', 'DESC']).optional().default('DESC').openapi({
          example: 'DESC',
          description: '排序方向'
        }),
        // 增强的筛选参数
        filters: z.string().optional().openapi({
          example: '{"status": 1, "createdAt": {"gte": "2024-01-01", "lte": "2024-12-31"}}',
          description: '筛选条件(JSON字符串)，支持精确匹配、范围查询、IN查询等'
        })
      })
    },
    responses: {
      200: {
        description: '成功获取列表',
        content: {
          'application/json': {
            schema: z.object({
              data: z.array(listSchema),
              pagination: z.object({
                total: z.number().openapi({ example: 100, description: '总记录数' }),
                current: z.number().openapi({ example: 1, description: '当前页码' }),
                pageSize: z.number().openapi({ example: 10, description: '每页数量' })
              })
            })
          }
        }
      },
      400: {
        description: '参数错误',
        content: { 'application/json': { schema: ErrorSchema } }
      },
      500: {
        description: '服务器错误',
        content: { 'application/json': { schema: ErrorSchema } }
      }
    }
  });
  
  // 创建资源路由
  const createRouteDef = createRoute({
    method: 'post',
    path: '/',
    middleware,
    request: {
      body: {
        content: {
          'application/json': { schema: createSchema }
        }
      }
    },
    responses: {
      201: {
        description: '创建成功',
        content: { 'application/json': { schema: getSchema } }
      },
      400: {
        description: '输入数据无效',
        content: { 'application/json': { schema: ErrorSchema } }
      },
      500: {
        description: '服务器错误',
        content: { 'application/json': { schema: ErrorSchema } }
      }
    }
  });
  
  // 获取单个资源路由
  const getRouteDef = createRoute({
    method: 'get',
    path: '/{id}',
    middleware,
    request: {
      params: z.object({
        id: z.coerce.number<number>().openapi({
          param: { name: 'id', in: 'path' },
          example: 1,
          description: '资源ID'
        })
      })
    },
    responses: {
      200: {
        description: '成功获取详情',
        content: { 'application/json': { schema: getSchema } }
      },
      400: {
        description: '资源不存在',
        content: { 'application/json': { schema: ErrorSchema } }
      },
      404: {
        description: '参数验证失败',
        content: { 'application/json': { schema: ErrorSchema } }
      },
      500: {
        description: '服务器错误',
        content: { 'application/json': { schema: ErrorSchema } }
      }
    }
  });
  
  // 更新资源路由
  const updateRouteDef = createRoute({
    method: 'put',
    path: '/{id}',
    middleware,
    request: {
      params: z.object({
        id: z.coerce.number<number>().openapi({
          param: { name: 'id', in: 'path' },
          example: 1,
          description: '资源ID'
        })
      }),
      body: {
        content: {
          'application/json': { schema: updateSchema }
        }
      }
    },
    responses: {
      200: {
        description: '更新成功',
        content: { 'application/json': { schema: getSchema } }
      },
      400: {
        description: '无效输入',
        content: { 'application/json': { schema: ErrorSchema } }
      },
      404: {
        description: '资源不存在',
        content: { 'application/json': { schema: ErrorSchema } }
      },
      500: {
        description: '服务器错误',
        content: { 'application/json': { schema: ErrorSchema } }
      }
    }
  });
  
  // 删除资源路由
  const deleteRouteDef = createRoute({
    method: 'delete',
    path: '/{id}',
    middleware,
    request: {
      params: z.object({
        id: z.coerce.number<number>().openapi({
          param: { name: 'id', in: 'path' },
          example: 1,
          description: '资源ID'
        })
      })
    },
    responses: {
      204: { description: '删除成功' },
      404: {
        description: '资源不存在',
        content: { 'application/json': { schema: ErrorSchema } }
      },
      500: {
        description: '服务器错误',
        content: { 'application/json': { schema: ErrorSchema } }
      }
    }
  });
  
  // 注册路由处理函数
  
  // 只读模式下只注册 GET 路由
  if (!readOnly) {
    // 完整 CRUD 路由
    const routes = app
      .openapi(listRoute, async (c) => {
        try {
          const query = c.req.valid('query') as any;
          const { page, pageSize, keyword, sortBy, sortOrder, filters } = query;

          // 构建排序对象
          const order: any = {};
          if (sortBy) {
            order[sortBy] = sortOrder || 'DESC';
          } else {
            order['id'] = 'DESC';
          }

          // 解析筛选条件
          let parsedFilters: any = undefined;
          if (filters) {
            try {
              parsedFilters = JSON.parse(filters);
            } catch (e) {
              return c.json({ code: 400, message: '筛选条件格式错误' }, 400);
            }
          }
          const crudService = new ConcreteCrudService(entity, {
            userTracking: userTracking,
            relationFields: relationFields
          });

          const [data, total] = await crudService.getList(
            page,
            pageSize,
            keyword,
            searchFields,
            undefined,
            relations || [],
            order,
            parsedFilters
          );

          return c.json({
            // data: z.array(listSchema).parse(data),
            data: await parseWithAwait(z.array(listSchema), data),
            pagination: { total, current: page, pageSize }
          }, 200);
        } catch (error) {
          if (error instanceof z.ZodError) {
            return c.json({ code: 400, message: '参数验证失败', errors: JSON.parse(error.message) }, 400);
          }
          return c.json({
            code: 500,
            message: error instanceof Error ? error.message : '获取列表失败'
          }, 500);
        }
      })
      // @ts-ignore
      .openapi(createRouteDef, async (c: any) => {
        try {
          const data = c.req.valid('json');
          const user = c.get('user');

          const crudService = new ConcreteCrudService(entity, {
            userTracking: userTracking,
            relationFields: relationFields
          });
          const result = await crudService.create(data, user?.id);
          return c.json(result, 201);
        } catch (error) {
          if (error instanceof z.ZodError) {
            return c.json({ code: 400, message: '参数验证失败', errors: JSON.parse(error.message) }, 400);
          }
          return c.json({
            code: 500,
            message: error instanceof Error ? error.message : '创建资源失败'
          }, 500);
        }
      })
      // @ts-ignore
      .openapi(getRouteDef, async (c: any) => {
        try {
          const { id } = c.req.valid('param');

          const crudService = new ConcreteCrudService(entity, {
            userTracking: userTracking,
            relationFields: relationFields
          });
          const result = await crudService.getById(id, relations || []);

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

          // return c.json(await getSchema.parseAsync(result), 200);
          return c.json(await parseWithAwait(getSchema, result), 200);
        } catch (error) {
          if (error instanceof z.ZodError) {
            return c.json({ code: 400, message: '参数验证失败', errors: JSON.parse(error.message) }, 400);
          }
          return c.json({
            code: 500,
            message: error instanceof Error ? error.message : '获取资源失败'
          }, 500);
        }
      })
      // @ts-ignore
      .openapi(updateRouteDef, async (c: any) => {
        try {
          const { id } = c.req.valid('param');
          const data = c.req.valid('json');
          const user = c.get('user');

          const crudService = new ConcreteCrudService(entity, {
            userTracking: userTracking,
            relationFields: relationFields
          });
          const result = await crudService.update(id, data, user?.id);

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

          return c.json(result, 200);
        } catch (error) {
          if (error instanceof z.ZodError) {
            return c.json({ code: 400, message: '参数验证失败', errors: JSON.parse(error.message) }, 400);
          }
          return c.json({
            code: 500,
            message: error instanceof Error ? error.message : '更新资源失败'
          }, 500);
        }
      })
      .openapi(deleteRouteDef, async (c: any) => {
        try {
          const { id } = c.req.valid('param');

          const crudService = new ConcreteCrudService(entity, {
            userTracking: userTracking,
            relationFields: relationFields
          });
          const success = await crudService.delete(id);

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

          return c.body(null, 204);
        } catch (error) {
          if (error instanceof z.ZodError) {
            return c.json({ code: 400, message: '参数验证失败', errors: JSON.parse(error.message) }, 400);
          }
          return c.json({
            code: 500,
            message: error instanceof Error ? error.message : '删除资源失败'
          }, 500);
        }
      });

    return routes;
  } else {
    // 只读模式，只注册 GET 路由
    const routes = app
      .openapi(listRoute, async (c) => {
        try {
          const query = c.req.valid('query') as any;
          const { page, pageSize, keyword, sortBy, sortOrder, filters } = query;

          // 构建排序对象
          const order: any = {};
          if (sortBy) {
            order[sortBy] = sortOrder || 'DESC';
          } else {
            order['id'] = 'DESC';
          }

          // 解析筛选条件
          let parsedFilters: any = undefined;
          if (filters) {
            try {
              parsedFilters = JSON.parse(filters);
            } catch (e) {
              return c.json({ code: 400, message: '筛选条件格式错误' }, 400);
            }
          }
          const crudService = new ConcreteCrudService(entity, {
            userTracking: userTracking,
            relationFields: relationFields
          });

          const [data, total] = await crudService.getList(
            page,
            pageSize,
            keyword,
            searchFields,
            undefined,
            relations || [],
            order,
            parsedFilters
          );

          return c.json({
            data: await parseWithAwait(z.array(listSchema), data),
            pagination: { total, current: page, pageSize }
          }, 200);
        } catch (error) {
          if (error instanceof z.ZodError) {
            return c.json({ code: 400, message: '参数验证失败', errors: JSON.parse(error.message) }, 400);
          }
          return c.json({
            code: 500,
            message: error instanceof Error ? error.message : '获取列表失败'
          }, 500);
        }
      })
      // @ts-ignore
      .openapi(getRouteDef, async (c: any) => {
        try {
          const { id } = c.req.valid('param');

          const crudService = new ConcreteCrudService(entity, {
            userTracking: userTracking,
            relationFields: relationFields
          });
          const result = await crudService.getById(id, relations || []);

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

          return c.json(await parseWithAwait(getSchema, result), 200);
        } catch (error) {
          if (error instanceof z.ZodError) {
            return c.json({ code: 400, message: '参数验证失败', errors: JSON.parse(error.message) }, 400);
          }
          return c.json({
            code: 500,
            message: error instanceof Error ? error.message : '获取资源失败'
          }, 500);
        }
      });
    return routes;
  }
  
}