import { NextResponse } from "next/server";

export class APIError extends Error {
  constructor(
    message: string,
    public statusCode: number = 500,
    public code?: string
  ) {
    super(message);
    this.name = "APIError";
  }
}

export const ErrorCodes = {
  // Authentication errors
  UNAUTHORIZED: "UNAUTHORIZED",
  FORBIDDEN: "FORBIDDEN",
  TOKEN_EXPIRED: "TOKEN_EXPIRED",
  
  // Validation errors
  VALIDATION_ERROR: "VALIDATION_ERROR",
  INVALID_INPUT: "INVALID_INPUT",
  MISSING_REQUIRED_FIELD: "MISSING_REQUIRED_FIELD",
  
  // Rate limiting
  RATE_LIMIT_EXCEEDED: "RATE_LIMIT_EXCEEDED",
  
  // Service errors
  SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE",
  EXTERNAL_SERVICE_ERROR: "EXTERNAL_SERVICE_ERROR",
  
  // Resource errors
  NOT_FOUND: "NOT_FOUND",
  CONFLICT: "CONFLICT",
  
  // Generic error
  INTERNAL_ERROR: "INTERNAL_ERROR",
} as const;

export type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes];

interface ErrorResponse {
  error: string;
  code?: ErrorCode;
  details?: any;
  timestamp: string;
  path?: string;
}

/**
 * Creates a standardized error response
 */
export function createErrorResponse(
  message: string,
  statusCode: number = 500,
  code?: ErrorCode,
  details?: any
): NextResponse<ErrorResponse> {
  const errorResponse: ErrorResponse = {
    error: message,
    code,
    details: process.env.NODE_ENV === "development" ? details : undefined,
    timestamp: new Date().toISOString(),
  };

  return NextResponse.json(errorResponse, { status: statusCode });
}

/**
 * Common error response helpers
 */
export const ErrorResponses = {
  unauthorized: (message = "Unauthorized") => 
    createErrorResponse(message, 401, ErrorCodes.UNAUTHORIZED),
  
  forbidden: (message = "Forbidden") => 
    createErrorResponse(message, 403, ErrorCodes.FORBIDDEN),
  
  notFound: (message = "Not found") => 
    createErrorResponse(message, 404, ErrorCodes.NOT_FOUND),
  
  validation: (message = "Validation error", details?: any) => 
    createErrorResponse(message, 400, ErrorCodes.VALIDATION_ERROR, details),
  
  rateLimit: (message = "Rate limit exceeded", retryAfter?: number) => {
    const response = createErrorResponse(message, 429, ErrorCodes.RATE_LIMIT_EXCEEDED);
    if (retryAfter) {
      response.headers.set("Retry-After", String(retryAfter));
    }
    return response;
  },
  
  internal: (message = "Internal server error", details?: any) => 
    createErrorResponse(message, 500, ErrorCodes.INTERNAL_ERROR, details),
  
  serviceUnavailable: (message = "Service temporarily unavailable") => 
    createErrorResponse(message, 503, ErrorCodes.SERVICE_UNAVAILABLE),
} as const;

/**
 * Wraps an API route handler with error handling
 */
export function withErrorHandler<T extends Request = Request>(
  handler: (request: T) => Promise<Response>
) {
  return async (request: T): Promise<Response> => {
    try {
      return await handler(request);
    } catch (error) {
      console.error("API route error:", error);
      
      if (error instanceof APIError) {
        return createErrorResponse(
          error.message,
          error.statusCode,
          error.code as ErrorCode
        );
      }
      
      if (error instanceof Error) {
        return ErrorResponses.internal(
          "An unexpected error occurred",
          process.env.NODE_ENV === "development" ? error.stack : undefined
        );
      }
      
      return ErrorResponses.internal("An unexpected error occurred");
    }
  };
}