import { Context } from 'hono'
import { z } from '@hono/zod-openapi'

export const ErrorSchema = z.object({
  code: z.number().openapi({
    example: 400,
  }),
  message: z.string().openapi({
    example: 'Bad Request',
  }),
})

// Zod错误详情schema - 类型安全版本
export const ZodIssueSchema = z.object({
  code: z.string().openapi({
    example: 'invalid_type',
  }),
  expected: z.string().optional().openapi({
    example: 'number',
  }),
  received: z.string().optional().openapi({
    example: 'string',
  }),
  path: z.array(z.union([z.string(), z.number(), z.null()])).openapi({
    example: ['basicSalary'],
  }),
  message: z.string().openapi({
    example: '基本工资必须大于0',
  }),
  origin: z.string().optional().openapi({
    example: 'value',
  }),
  minimum: z.number().optional().openapi({
    example: 0,
  }),
  maximum: z.number().optional().openapi({
    example: 100,
  }),
  inclusive: z.boolean().optional().openapi({
    example: false,
  }),
  // 添加更多可能的字段
  input: z.any().optional().openapi({
    description: '原始输入数据（当reportInput为true时）',
  }),
  fatal: z.boolean().optional().openapi({
    example: false,
  }),
  type: z.string().optional().openapi({
    example: 'string',
  }),
  exact: z.boolean().optional().openapi({
    example: false,
  }),
  validation: z.string().optional().openapi({
    example: 'email',
  }),
  keys: z.array(z.string()).optional().openapi({
    example: ['extraField'],
  }),
  options: z.array(z.union([z.string(), z.number()])).optional().openapi({
    example: ['option1', 'option2'],
  }),
  multipleOf: z.number().optional().openapi({
    example: 5,
  }),
  unionErrors: z.array(z.any()).optional().openapi({
    description: '联合类型错误详情',
  }),
  argumentsError: z.any().optional().openapi({
    description: '参数错误详情',
  }),
  returnTypeError: z.any().optional().openapi({
    description: '返回类型错误详情',
  }),
})

// Zod错误响应schema
export const ZodErrorSchema = z.object({
  code: z.number().openapi({
    example: 400,
  }),
  message: z.string().openapi({
    example: '参数错误',
  }),
  errors: z.array(ZodIssueSchema).openapi({
    description: 'Zod验证错误详情',
  }),
})

// 类型安全的Zod错误处理函数
export function handleZodError(error: z.ZodError): z.infer<typeof ZodErrorSchema> {
  const issues = error.issues.map(issue => {
    // 基础字段 - 过滤掉symbol类型的path，转换null为字符串
    const mappedIssue: z.infer<typeof ZodIssueSchema> = {
      code: issue.code,
      path: issue.path.map(p => {
        if (typeof p === 'string' || typeof p === 'number') {
          return p
        }
        // 将symbol和null转换为字符串
        return String(p)
      }),
      message: issue.message,
    }

    // 根据错误类型添加特定字段
    if ('expected' in issue && issue.expected !== undefined) {
      mappedIssue.expected = String(issue.expected)
    }

    if ('received' in issue && issue.received !== undefined) {
      mappedIssue.received = String(issue.received)
    }

    if ('origin' in issue && issue.origin !== undefined) {
      mappedIssue.origin = String(issue.origin)
    }

    if ('minimum' in issue && issue.minimum !== undefined) {
      mappedIssue.minimum = Number(issue.minimum)
    }

    if ('maximum' in issue && issue.maximum !== undefined) {
      mappedIssue.maximum = Number(issue.maximum)
    }

    if ('inclusive' in issue && issue.inclusive !== undefined) {
      mappedIssue.inclusive = Boolean(issue.inclusive)
    }

    if ('fatal' in issue && issue.fatal !== undefined) {
      mappedIssue.fatal = Boolean(issue.fatal)
    }

    if ('type' in issue && issue.type !== undefined) {
      mappedIssue.type = String(issue.type)
    }

    if ('exact' in issue && issue.exact !== undefined) {
      mappedIssue.exact = Boolean(issue.exact)
    }

    if ('validation' in issue && issue.validation !== undefined) {
      mappedIssue.validation = String(issue.validation)
    }

    if ('keys' in issue && issue.keys !== undefined && Array.isArray(issue.keys)) {
      mappedIssue.keys = issue.keys.map(key => String(key))
    }

    if ('options' in issue && issue.options !== undefined && Array.isArray(issue.options)) {
      mappedIssue.options = issue.options.map(opt =>
        typeof opt === 'string' || typeof opt === 'number' ? opt : String(opt)
      )
    }

    if ('multipleOf' in issue && issue.multipleOf !== undefined) {
      mappedIssue.multipleOf = Number(issue.multipleOf)
    }

    if ('input' in issue && issue.input !== undefined) {
      mappedIssue.input = issue.input
    }

    if ('unionErrors' in issue && issue.unionErrors !== undefined && Array.isArray(issue.unionErrors)) {
      mappedIssue.unionErrors = issue.unionErrors
    }

    if ('argumentsError' in issue && issue.argumentsError !== undefined) {
      mappedIssue.argumentsError = issue.argumentsError
    }

    if ('returnTypeError' in issue && issue.returnTypeError !== undefined) {
      mappedIssue.returnTypeError = issue.returnTypeError
    }

    return mappedIssue
  })

  return {
    code: 400,
    message: '参数错误',
    errors: issues,
  }
}

// 简化的Zod错误处理函数（用于路由）
export function createZodErrorResponse(error: z.ZodError) {
  return {
    code: 400,
    message: '参数错误',
    errors: error.issues.map(issue => ({
      code: issue.code,
      path: issue.path,
      message: issue.message,
      // 可选字段 - 根据实际需要添加
      ...('expected' in issue && issue.expected !== undefined && { expected: String(issue.expected) }),
      ...('received' in issue && issue.received !== undefined && { received: String(issue.received) }),
      ...('minimum' in issue && issue.minimum !== undefined && { minimum: Number(issue.minimum) }),
      ...('maximum' in issue && issue.maximum !== undefined && { maximum: Number(issue.maximum) }),
      ...('inclusive' in issue && issue.inclusive !== undefined && { inclusive: Boolean(issue.inclusive) }),
    }))
  }
}

export const errorHandler = async (err: Error, c: Context) => {
  return c.json(
    {
      code: 500,
      message: err.message || 'Internal Server Error'
    },
    500
  )
}