import { z } from 'zod';
import { NextResponse } from 'next/server';

/**
 * Validation schema for wallet addresses
 */
export const walletAddressSchema = z.string().regex(
  /^0x[a-fA-F0-9]{40}$/,
  "Invalid Ethereum wallet address format"
);

/**
 * Validation schema for address with blockchains
 */
export const addressConfigSchema = z.object({
  address: walletAddressSchema,
  blockchains: z.array(z.string().min(1)).min(1, "At least one blockchain is required")
});

/**
 * Validation schema for session token creation (guest checkout)
 */
export const guestSessionTokenSchema = z.object({
  guestCheckout: z.literal(true),
  assets: z.array(z.string()).optional().default(['ETH', 'USDC'])
});

/**
 * Validation schema for session token creation (with wallet)
 */
export const walletSessionTokenSchema = z.object({
  userAddress: walletAddressSchema,
  assets: z.array(z.string()).optional().default(['ETH', 'USDC'])
});

/**
 * Combined session token validation schema
 */
export const sessionTokenSchema = z.union([
  guestSessionTokenSchema,
  walletSessionTokenSchema
]);

/**
 * Validation schema for onramp URL generation
 */
export const onrampUrlSchema = z.object({
  addresses: z.array(addressConfigSchema).min(1, "At least one address is required"),
  assets: z.array(z.string()).optional(),
  defaultAsset: z.string().optional(),
  defaultNetwork: z.string().optional(),
  presetFiatAmount: z.number()
    .min(5, "Minimum amount is $5")
    .max(500, "Maximum amount is $500 (guest checkout limit)")
    .optional(),
  presetCryptoAmount: z.number().positive("Crypto amount must be positive").optional(),
  redirectUrl: z.string().url("Invalid redirect URL").optional(),
  partnerUserId: z.string().max(50, "Partner user ID must be 50 characters or less").optional()
});

/**
 * Validation schema for amount input
 */
export const amountSchema = z.number()
  .min(5, "Minimum amount is $5")
  .max(500, "Maximum amount is $500");

/**
 * Validation schema for email input
 */
export const emailSchema = z.string().email("Invalid email address");

/**
 * Validation schema for OTP input
 */
export const otpSchema = z.string()
  .length(6, "OTP must be 6 digits")
  .regex(/^\d{6}$/, "OTP must contain only numbers");

/**
 * Common asset symbols validation
 */
export const assetSchema = z.enum([
  'ETH', 'USDC', 'BTC', 'USDT', 'DAI', 'WETH', 'MATIC', 'LINK', 'UNI'
]);

/**
 * Network validation
 */
export const networkSchema = z.enum([
  'base', 'ethereum', 'arbitrum', 'optimism', 'polygon'
]);

/**
 * Error response schema
 */
export const errorResponseSchema = z.object({
  error: z.string(),
  details: z.any().optional(),
  code: z.string().optional()
});

/**
 * Success response schema for session token
 */
export const sessionTokenResponseSchema = z.object({
  sessionToken: z.string(),
  expiresIn: z.number().optional().default(300), // 5 minutes
  channelId: z.string().optional()
});

/**
 * Success response schema for onramp URL
 */
export const onrampUrlResponseSchema = z.object({
  url: z.string().url(),
  expiresIn: z.number().optional().default(300), // 5 minutes
  sessionToken: z.string().optional()
});

/**
 * Utility function to validate and parse request data
 */
export function validateRequest<T>(schema: z.ZodSchema<T>, data: unknown): T {
  const result = schema.safeParse(data);
  
  if (!result.success) {
    const errorMessage = result.error.issues
      .map(issue => `${issue.path.join('.')}: ${issue.message}`)
      .join('; ');
    
    throw new Error(`Validation failed: ${errorMessage}`);
  }
  
  return result.data;
}

/**
 * Utility function to create error response
 */
export function createErrorResponse(
  error: string, 
  statusCode?: number,
  suggestions?: string[]
) {
  return NextResponse.json({
    error,
    ...(statusCode && { statusCode }),
    ...(suggestions && suggestions.length > 0 && { suggestions }),
    timestamp: new Date().toISOString(),
    help: 'Run "npx cdp-wallet-onramp-kit validate" to check your setup'
  }, { 
    status: statusCode || 500 
  });
}

/**
 * Utility function to validate environment variables
 */
export function validateEnvironment(): {
  isValid: boolean;
  missing: string[];
} {
  const required = [
    'CDP_API_KEY_PRIVATE_KEY',
    'CDP_API_KEY_NAME'
  ];
  
  const missing = required.filter(key => !process.env[key]);
  
  return {
    isValid: missing.length === 0,
    missing
  };
}