/**
 * ${VOCAB.factory} RAG Router
 * Phase 2: RAG-Augmented Routing with Token Conservation
 * 
 * Main routing engine that coordinates prompt analysis,
 * knowledge retrieval, model selection, and token optimization.
 */

import { analyzePrompt, PromptAnalysis, summarizeAnalysis } from './prompt-analyzer';
import { searchKnowledgeBase, KnowledgeEntry, MODEL_CAPABILITIES } from './knowledge-base';
import {
  applyConservation,
  ConservationStats,
  formatTokenSavings,
  recordTokenUsage,
  cacheResponse,
  generateCacheKey,
  CacheEntry,
  getCacheStats
} from './token-conservation';
import { VOCAB } from '@/lib/white-label/constants';

export interface RoutingDecision {
  model: string;
  systemPrompt: string;
  contextInjection: string[];
  analysis: PromptAnalysis;
  conservation: {
    optimizedPrompt: string;
    stats: ConservationStats;
    cachedResponse: CacheEntry | null;
    budgetOk: boolean;
  };
  metadata: {
    routedAt: string;
    version: string;
    fallbackChain: string[];
  };
}

export interface RouterConfig {
  preferCostEfficient?: boolean;
  maxTokenBudget?: number;
  forcedModel?: string;
  enableKnowledgeInjection?: boolean;
  // Token conservation options
  enableConservation?: boolean;
  userId?: string;
  projectId?: string;
  maxContextTokensPerEntry?: number;
}

const ROUTER_VERSION = '2.0.0-phase2';

/**
 * Route a prompt to the appropriate model with context and conservation
 */
export function routePrompt(
  userPrompt: string,
  config: RouterConfig = {}
): RoutingDecision {
  // Analyze the prompt
  const analysis = analyzePrompt(userPrompt);
  
  // Override model if forced
  const model = config.forcedModel || selectFinalModel(analysis, config);
  
  // Apply token conservation
  const conservationResult = applyConservation(
    userPrompt,
    analysis.relevantKnowledge,
    model,
    analysis.detectedPatterns,
    {
      enableCompression: config.enableConservation !== false,
      enableCaching: config.enableConservation !== false,
      enableSummarization: config.enableConservation !== false,
      maxContextTokens: config.maxContextTokensPerEntry || 200,
      userId: config.userId,
      projectId: config.projectId
    }
  );
  
  // Use optimized knowledge for context injection
  const contextInjection = config.enableKnowledgeInjection !== false
    ? buildContextInjection(conservationResult.optimizedKnowledge)
    : [];
  
  // Generate system prompt based on task
  const systemPrompt = generateSystemPrompt(analysis);
  
  // Build fallback chain
  const fallbackChain = buildFallbackChain(model);
  
  return {
    model,
    systemPrompt,
    contextInjection,
    analysis,
    conservation: {
      optimizedPrompt: conservationResult.optimizedPrompt,
      stats: conservationResult.stats,
      cachedResponse: conservationResult.cachedResponse,
      budgetOk: conservationResult.budgetOk
    },
    metadata: {
      routedAt: new Date().toISOString(),
      version: ROUTER_VERSION,
      fallbackChain
    }
  };
}

/**
 * Record a successful response for caching
 */
export function recordResponse(
  decision: RoutingDecision,
  response: string
): void {
  const cacheKey = generateCacheKey(
    decision.conservation.optimizedPrompt,
    decision.analysis.detectedPatterns,
    decision.model
  );
  
  cacheResponse(cacheKey, decision.conservation.optimizedPrompt, response, decision.model);
}

/**
 * Record token usage after a request
 */
export function recordUsage(
  decision: RoutingDecision,
  actualTokens: number
): boolean {
  if (!decision.conservation.budgetOk) {
    return false;
  }
  
  // This would be called after the LLM response to track actual usage
  // For now, estimate based on analysis
  const userId = 'default'; // Would come from config
  return recordTokenUsage(userId, actualTokens);
}

/**
 * Get router statistics including cache performance
 */
export function getRouterStats(): {
  version: string;
  cache: { size: number; totalHits: number; totalSaved: number };
} {
  return {
    version: ROUTER_VERSION,
    cache: getCacheStats()
  };
}

function selectFinalModel(analysis: PromptAnalysis, config: RouterConfig): string {
  let model = analysis.suggestedModel;
  
  // Cost optimization
  if (config.preferCostEfficient) {
    const currentCost = MODEL_CAPABILITIES[model]?.costTier || 'medium';
    if (currentCost === 'high' && analysis.complexity !== 'high') {
      // Downgrade if task isn't truly complex
      model = 'claude-sonnet-4.6';
    }
  }
  
  // Token budget constraint
  if (config.maxTokenBudget && analysis.estimatedTokens > config.maxTokenBudget) {
    // Need a model with larger context
    if (config.maxTokenBudget > 100000) {
      model = 'gemini-2.5-pro'; // 1M context
    }
  }
  
  return model;
}

function buildContextInjection(knowledge: KnowledgeEntry[]): string[] {
  return knowledge.map(entry => {
    return `### ${entry.title}\n${entry.description}\n\n\`\`\`\n${entry.content.trim()}\n\`\`\``;
  });
}

function generateSystemPrompt(analysis: PromptAnalysis): string {
  const basePrompt = `You are ${VOCAB.factory}, an expert AI code generation assistant specializing in Next.js, React, TypeScript, Prisma, and Tailwind CSS.

Your task is to ${getTaskVerb(analysis.taskType)} code following these principles:
- Write production-ready, type-safe code
- Follow Next.js 14 App Router conventions
- Use server components by default, client components only when needed
- Implement proper error handling and loading states
- Write accessible, responsive UI with Tailwind CSS
- Include helpful comments for complex logic
`;

  // Add domain-specific instructions
  const domainInstructions = analysis.domain.map(domain => {
    switch (domain) {
      case 'frontend':
        return '- Use React Server Components where possible, mark interactive components with "use client"';
      case 'backend':
        return '- Create API routes in app/api/ with proper validation and error responses';
      case 'database':
        return '- Use Prisma ORM with proper relations and type-safe queries';
      case 'security':
        return '- Implement proper authentication checks and input validation';
      case 'styling':
        return '- Follow the existing design system with glass-card, gradient-text, and dark theme';
      case 'infrastructure':
        return '- Consider deployment constraints and environment variables';
      default:
        return '';
    }
  }).filter(Boolean).join('\n');

  // Add complexity-specific guidance
  const complexityGuidance = {
    low: '\nKeep the implementation simple and focused. Avoid over-engineering.',
    medium: '\nBalance simplicity with proper patterns. Include error handling.',
    high: '\nConsider edge cases, performance, and maintainability. Document architectural decisions.'
  };

  return basePrompt + '\n' + domainInstructions + complexityGuidance[analysis.complexity];
}

function getTaskVerb(taskType: string): string {
  const verbs: Record<string, string> = {
    create: 'create',
    edit: 'modify',
    debug: 'debug and fix',
    explain: 'explain',
    optimize: 'optimize',
    refactor: 'refactor',
    test: 'write tests for'
  };
  return verbs[taskType] || 'work on';
}

function buildFallbackChain(primaryModel: string): string[] {
  const fallbackMap: Record<string, string[]> = {
    'claude-opus-4.6': ['claude-sonnet-4.6', 'gpt-4.1'],
    'claude-sonnet-4.6': ['claude-haiku-4.5', 'deepseek-v3.1'],
    'claude-haiku-4.5': ['deepseek-v3.1'],
    'o3': ['o4-mini', 'claude-sonnet-4.6'],
    'o4-mini': ['claude-sonnet-4.6'],
    'gemini-2.5-pro': ['claude-opus-4.6'],
    'deepseek-v3.1': ['claude-haiku-4.5'],
    'gpt-4.1': ['claude-sonnet-4.6']
  };
  
  return fallbackMap[primaryModel] || ['claude-sonnet-4.6'];
}

/**
 * Get a human-readable routing explanation
 */
export function explainRouting(decision: RoutingDecision): string {
  const { analysis, model, metadata, conservation } = decision;
  
  const cacheStatus = conservation.cachedResponse 
    ? `✅ Cache hit! Saved ${conservation.cachedResponse.tokensSaved} tokens`
    : '❌ No cache hit';
  
  return `
## 🎯 Routing Decision

**Selected Model:** ${model}
**Confidence:** ${Math.round(analysis.confidence * 100)}%
**Reasoning:** ${analysis.reasoning}

### Analysis
- **Task Type:** ${analysis.taskType}
- **Complexity:** ${analysis.complexity}
- **Domains:** ${analysis.domain.join(', ')}
- **Estimated Tokens:** ~${analysis.estimatedTokens.toLocaleString()}

### 💰 Token Conservation
- **Cache Status:** ${cacheStatus}
- **Prompt Compression:** ${conservation.stats.promptCompressionSavings} tokens saved
- **Context Summarization:** ${conservation.stats.contextSummarizationSavings} tokens saved
- **Total Saved:** ${conservation.stats.totalSavings} tokens (${conservation.stats.percentageSaved.toFixed(1)}%)
- **Budget Status:** ${conservation.budgetOk ? '✅ Within budget' : '⚠️ Budget exceeded'}

### Fallback Chain
${metadata.fallbackChain.map((m, i) => `${i + 1}. ${m}`).join('\n')}

### Relevant Patterns
${analysis.relevantKnowledge.map(k => `- ${k.title}`).join('\n') || 'None matched'}

---
*Router v${metadata.version} | Routed at ${metadata.routedAt}*
  `.trim();
}

/**
 * Log routing decision for analytics
 */
export function logRoutingDecision(decision: RoutingDecision): void {
  console.log(`[DARK-FACTORY-ROUTER] ${summarizeAnalysis(decision.analysis)}`);
  console.log(`[DARK-FACTORY-CONSERVATION] ${formatTokenSavings(decision.conservation.stats)}`);
}
