import { z } from 'zod';

interface SchemaObject {
  type?: string;
  format?: string;
  enum?: (string | number)[];
  properties?: Record<string, SchemaObject>;
  required?: string[];
  items?: SchemaObject;
  additionalProperties?: SchemaObject;
  nullable?: boolean;
  default?: unknown;
  oneOf?: SchemaObject[];
  allOf?: SchemaObject[];
}

type ZodType = z.ZodType<any>;

export function zodToOpenAPI(schema: ZodType): SchemaObject {
  if (schema instanceof z.ZodString) {
    return { type: 'string' };
  }
  
  if (schema instanceof z.ZodNumber) {
    return { type: 'number' };
  }
  
  if (schema instanceof z.ZodBoolean) {
    return { type: 'boolean' };
  }
  
  if (schema instanceof z.ZodArray) {
    return {
      type: 'array',
      items: zodToOpenAPI(schema.element as ZodType)
    };
  }
  
  if (schema instanceof z.ZodObject) {
    const shape = schema.shape;
    const properties: Record<string, SchemaObject> = {};
    const required: string[] = [];
    
    for (const [key, value] of Object.entries(shape)) {
      properties[key] = zodToOpenAPI(value as ZodType);
      
      if (!(value instanceof z.ZodOptional)) {
        required.push(key);
      }
    }
    
    return {
      type: 'object',
      properties,
      required: required.length > 0 ? required : undefined
    };
  }
  
  if (schema instanceof z.ZodOptional) {
    return zodToOpenAPI(schema.unwrap() as ZodType);
  }
  
  if (schema instanceof z.ZodDefault) {
    const inner = zodToOpenAPI(schema.removeDefault() as ZodType);
    return { ...inner };
  }
  
  if (schema instanceof z.ZodEnum) {
    return {
      type: 'string',
      enum: schema.options as string[]
    };
  }
  
  if (schema instanceof z.ZodNullable) {
    return { ...zodToOpenAPI(schema.unwrap() as ZodType), nullable: true };
  }
  
  if (schema instanceof z.ZodRecord) {
    return {
      type: 'object',
      additionalProperties: { type: 'object' }
    };
  }
  
  if (schema instanceof z.ZodDate) {
    return { type: 'string', format: 'date-time' };
  }
  
  if (schema instanceof z.ZodLiteral) {
    return { type: 'string', enum: [schema.value as string] };
  }
  
  if (schema instanceof z.ZodUnion) {
    return {
      oneOf: (schema.options as ZodType[]).map((opt) => zodToOpenAPI(opt))
    };
  }
  
  if (schema instanceof z.ZodIntersection) {
    return {
      allOf: [
        zodToOpenAPI(schema._def.left as ZodType),
        zodToOpenAPI(schema._def.right as ZodType)
      ]
    };
  }
  
  return { type: 'object' };
}

export function createAPIDocumentation(
  name: string,
  requestSchema: ZodType,
  responseSchema: ZodType
): {
  request: SchemaObject;
  response: SchemaObject;
} {
  return {
    request: zodToOpenAPI(requestSchema),
    response: zodToOpenAPI(responseSchema)
  };
}
