// ── Provider & Model Types ─────────────────────────────────────

export interface ModelConfig {
  /** Model identifier as the provider expects it */
  id: string;
  /** Human-readable label */
  label: string;
  /** Max context window tokens */
  contextWindow: number;
  /** What this model is good at */
  strengths: PromptCategory[];
  /** Relative speed tier: 1 = fastest, 3 = slowest */
  speedTier: 1 | 2 | 3;
  /** Whether the model supports vision (image) inputs */
  supportsVision?: boolean;
  /** Whether the model supports text embedding generation */
  supportsEmbedding?: boolean;
}

export interface ProviderConfig {
  /** Unique provider name */
  name: string;
  /** OpenAI-compatible base URL (e.g. https://api.groq.com/openai/v1) */
  baseUrl: string;
  /** Environment variable name that holds the API key (omit for local/no-auth providers) */
  apiKeyEnv?: string;
  /** Available models on this provider */
  models: ModelConfig[];
  /** Extra headers to send with every request */
  extraHeaders?: Record<string, string>;
  /** Free-tier rate limit: requests per minute (0 = unknown) */
  rpmLimit: number;
  /** Free-tier rate limit: tokens per minute (0 = unknown) */
  tpmLimit: number;
}

// ── Prompt Classification ──────────────────────────────────────

export type PromptCategory = 'code' | 'math' | 'reasoning' | 'creative' | 'general' | 'vision';

export interface ClassificationResult {
  category: PromptCategory;
  estimatedTokens: number;
}

// ── Health Tracking ────────────────────────────────────────────

export interface HealthSnapshot {
  provider: string;
  model: string;
  /** Total requests in the window */
  totalRequests: number;
  /** Successful requests */
  successes: number;
  /** 429 rate-limit hits */
  rateLimits: number;
  /** 5xx / network errors */
  errors: number;
  /** Average latency in ms (successes only) */
  avgLatencyMs: number;
  /** p95 latency in ms */
  p95LatencyMs: number;
  /** Whether this provider is currently considered healthy */
  healthy: boolean;
}

export interface RequestRecord {
  timestamp: number;
  latencyMs: number;
  status: 'success' | 'rate_limit' | 'error';
}

// ── Router Config ──────────────────────────────────────────────

export interface RouterConfig {
  /** Provider configurations (use DEFAULT_PROVIDERS if omitted) */
  providers?: ProviderConfig[];
  /** Health window in ms (default: 60_000 = 1 minute) */
  healthWindowMs?: number;
  /** Error rate threshold to mark unhealthy (default: 0.5 = 50%) */
  errorThreshold?: number;
  /** Rate-limit rate threshold to mark unhealthy (default: 0.3 = 30%) */
  rateLimitThreshold?: number;
  /** Request timeout in ms (default: 30_000) */
  timeoutMs?: number;
  /** Max retry attempts across providers (default: 3) */
  maxRetries?: number;
}

// ── OpenAI-Compatible Request/Response ─────────────────────────

export interface ChatMessage {
  role: 'system' | 'user' | 'assistant';
  content: string;
}

export interface ChatCompletionRequest {
  messages: ChatMessage[];
  /** Optional: force a specific model (provider:model format or just model id) */
  model?: string;
  temperature?: number;
  max_tokens?: number;
  top_p?: number;
  stream?: boolean;
}

export interface ChatCompletionChoice {
  index: number;
  message: ChatMessage;
  finish_reason: string | null;
}

export interface ChatCompletionUsage {
  prompt_tokens: number;
  completion_tokens: number;
  total_tokens: number;
}

export interface ChatCompletionResponse {
  id: string;
  object: 'chat.completion';
  created: number;
  model: string;
  choices: ChatCompletionChoice[];
  usage?: ChatCompletionUsage;
}

// ── Router Result (wraps response + metadata) ──────────────────

export interface RouteResult {
  response: ChatCompletionResponse;
  /** Which provider served this request */
  provider: string;
  /** Which model was used */
  model: string;
  /** Total latency in ms (including retries) */
  totalLatencyMs: number;
  /** How many attempts were made */
  attempts: number;
}

export interface RoutePlan {
  provider: ProviderConfig;
  model: ModelConfig;
  category: PromptCategory | 'explicit';
  explicit: boolean;
}
