import * as dotenv from 'dotenv';
import { z } from 'zod';

// Load environment variables
dotenv.config();

/**
 * AI Configuration Schema
 * Validates and structures AI service configuration
 */
const AIConfigSchema = z.object({
  openai: z.object({
    apiKey: z.string().min(1),
    model: z.string().default('gpt-4-turbo'),
    maxTokens: z.number().default(4096),
    temperature: z.number().min(0).max(2).default(0.7),
    retryAttempts: z.number().default(3),
    retryDelayMs: z.number().default(1000),
    timeout: z.number().default(30000), // 30 seconds
  }),
  langchain: z.object({
    verbose: z.boolean().default(false),
    cacheEnabled: z.boolean().default(true),
    cacheTTL: z.number().default(3600), // 1 hour in seconds
    maxConcurrency: z.number().default(5),
    memoryBufferSize: z.number().default(10), // Number of messages to keep in memory
  }),
  rateLimit: z.object({
    maxRequestsPerMinute: z.number().default(60),
    maxTokensPerMinute: z.number().default(90000),
    maxRequestsPerDay: z.number().default(10000),
  }),
  monitoring: z.object({
    trackTokenUsage: z.boolean().default(true),
    logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
    metricsEnabled: z.boolean().default(true),
  }),
});

export type AIConfig = z.infer<typeof AIConfigSchema>;

/**
 * Validates API keys on startup
 * Throws error if required keys are missing or invalid
 */
export function validateAPIKeys(): void {
  const openaiKey = process.env.OPENAI_API_KEY;
  
  if (!openaiKey) {
    throw new Error('OPENAI_API_KEY is required but not found in environment variables');
  }
  
  // Basic format validation for OpenAI key
  if (!openaiKey.startsWith('sk-')) {
    console.warn('Warning: OPENAI_API_KEY does not start with "sk-". This might be an invalid key format.');
  }
  
  // Check for optional LangChain-specific keys if needed
  const langchainApiKey = process.env.LANGCHAIN_API_KEY;
  if (langchainApiKey) {
    console.info('LangChain API key detected and will be used for enhanced features');
  }
}

/**
 * Loads and validates AI configuration from environment variables
 * @returns Validated AI configuration object
 */
export function loadAIConfig(): AIConfig {
  // Validate API keys first
  validateAPIKeys();
  
  // Build configuration object from environment variables
  const config = {
    openai: {
      apiKey: process.env.OPENAI_API_KEY!,
      model: process.env.OPENAI_MODEL || 'gpt-4-turbo',
      maxTokens: parseInt(process.env.OPENAI_MAX_TOKENS || '4096', 10),
      temperature: parseFloat(process.env.OPENAI_TEMPERATURE || '0.7'),
      retryAttempts: parseInt(process.env.OPENAI_RETRY_ATTEMPTS || '3', 10),
      retryDelayMs: parseInt(process.env.OPENAI_RETRY_DELAY_MS || '1000', 10),
      timeout: parseInt(process.env.OPENAI_TIMEOUT || '30000', 10),
    },
    langchain: {
      verbose: process.env.LANGCHAIN_VERBOSE === 'true',
      cacheEnabled: process.env.LANGCHAIN_CACHE_ENABLED !== 'false',
      cacheTTL: parseInt(process.env.LANGCHAIN_CACHE_TTL || '3600', 10),
      maxConcurrency: parseInt(process.env.LANGCHAIN_MAX_CONCURRENCY || '5', 10),
      memoryBufferSize: parseInt(process.env.LANGCHAIN_MEMORY_BUFFER_SIZE || '10', 10),
    },
    rateLimit: {
      maxRequestsPerMinute: parseInt(process.env.AI_MAX_REQUESTS_PER_MINUTE || '60', 10),
      maxTokensPerMinute: parseInt(process.env.AI_MAX_TOKENS_PER_MINUTE || '90000', 10),
      maxRequestsPerDay: parseInt(process.env.AI_MAX_REQUESTS_PER_DAY || '10000', 10),
    },
    monitoring: {
      trackTokenUsage: process.env.AI_TRACK_TOKEN_USAGE !== 'false',
      logLevel: (process.env.AI_LOG_LEVEL || 'info') as 'debug' | 'info' | 'warn' | 'error',
      metricsEnabled: process.env.AI_METRICS_ENABLED !== 'false',
    },
  };
  
  // Validate configuration against schema
  try {
    return AIConfigSchema.parse(config);
  } catch (error: any) {
    if (error instanceof z.ZodError) {
      throw new Error(`Invalid AI configuration: ${error.issues.map(e => `${e.path.join('.')}: ${e.message}`).join(', ')}`);
    }
    throw error;
  }
}

/**
 * Get singleton instance of AI configuration
 */
let cachedConfig: AIConfig | null = null;

export function getAIConfig(): AIConfig {
  if (!cachedConfig) {
    cachedConfig = loadAIConfig();
  }
  return cachedConfig;
}

/**
 * Reset configuration cache (useful for testing)
 */
export function resetConfigCache(): void {
  cachedConfig = null;
}

/**
 * Check if AI services are properly configured
 */
export function isAIConfigured(): boolean {
  try {
    validateAPIKeys();
    return true;
  } catch {
    return false;
  }
}

/**
 * Get configuration summary for logging
 */
export function getConfigSummary(): Record<string, any> {
  const config = getAIConfig();
  return {
    openai: {
      model: config.openai.model,
      maxTokens: config.openai.maxTokens,
      temperature: config.openai.temperature,
      configured: true,
    },
    langchain: {
      cacheEnabled: config.langchain.cacheEnabled,
      cacheTTL: config.langchain.cacheTTL,
      maxConcurrency: config.langchain.maxConcurrency,
    },
    rateLimit: {
      maxRequestsPerMinute: config.rateLimit.maxRequestsPerMinute,
      maxTokensPerMinute: config.rateLimit.maxTokensPerMinute,
    },
    monitoring: {
      trackTokenUsage: config.monitoring.trackTokenUsage,
      logLevel: config.monitoring.logLevel,
      metricsEnabled: config.monitoring.metricsEnabled,
    },
  };
}