import { z } from 'zod';

export const LLM_PROVIDERS = ['gemini-cli', 'ollama', 'anthropic', 'openai', 'deepseek', 'vllm', 'vllm-managed', 'none'] as const;
export type LlmProviderName = typeof LLM_PROVIDERS[number];

export const LLM_TIERS = ['fast', 'heavy'] as const;
export type LlmTier = typeof LLM_TIERS[number];

/** Legacy single-provider format. */
export const LlmConfigSchema = z.object({
  /** LLM provider name */
  provider: z.enum(LLM_PROVIDERS),
  /** Model name */
  model: z.string().optional(),
  /** Provider URL (for ollama, vllm, openai with custom endpoint) */
  url: z.string().optional(),
  /** Binary path override (for gemini-cli) */
  binaryPath: z.string().optional(),
}).strict();

export type LlmConfig = z.infer<typeof LlmConfigSchema>;

/** Multi-provider entry (advanced mode). */
export const LlmProviderEntrySchema = z.object({
  /** User-chosen name for this provider instance (e.g. "vllm-local") */
  name: z.string(),
  /** Provider type */
  type: z.enum(LLM_PROVIDERS),
  /** Model name */
  model: z.string().optional(),
  /** Provider URL (for ollama, vllm, openai with custom endpoint) */
  url: z.string().optional(),
  /** Binary path override (for gemini-cli) */
  binaryPath: z.string().optional(),
  /** Tier assignment */
  tier: z.enum(LLM_TIERS).optional(),
  /** vllm-managed: path to Python venv (e.g. "~/vllm_env") */
  venvPath: z.string().optional(),
  /** vllm-managed: port for vLLM HTTP server */
  port: z.number().int().positive().optional(),
  /** vllm-managed: GPU memory utilization fraction */
  gpuMemoryUtilization: z.number().min(0.1).max(1.0).optional(),
  /** vllm-managed: max model context length */
  maxModelLen: z.number().int().positive().optional(),
  /** vllm-managed: minutes of idle before stopping vLLM */
  idleTimeoutMinutes: z.number().int().positive().optional(),
  /** vllm-managed: extra args for `vllm serve` */
  extraArgs: z.array(z.string()).optional(),
  /** When true, mcplocal keeps the provider registered but suppresses
   *  auto-start. Toggle via `mcpctl provider {enable,disable} <name>`. */
  disabled: z.boolean().optional(),
}).strict();

export type LlmProviderEntry = z.infer<typeof LlmProviderEntrySchema>;

/** Multi-provider format with providers array. */
export const LlmMultiConfigSchema = z.object({
  providers: z.array(LlmProviderEntrySchema).min(1),
}).strict();

export type LlmMultiConfig = z.infer<typeof LlmMultiConfigSchema>;

export const McpctlConfigSchema = z.object({
  /** mcplocal daemon endpoint (local LLM pre-processing proxy) */
  mcplocalUrl: z.string().default('http://localhost:3200'),
  /** mcpd daemon endpoint (remote instance manager) */
  mcpdUrl: z.string().default('http://localhost:3100'),
  /** @deprecated Use mcplocalUrl instead. Kept for backward compatibility. */
  daemonUrl: z.string().optional(),
  /** Active registries for search */
  registries: z.array(z.enum(['official', 'glama', 'smithery'])).default(['official', 'glama', 'smithery']),
  /** Cache TTL in milliseconds */
  cacheTTLMs: z.number().int().positive().default(3_600_000),
  /** HTTP proxy URL */
  httpProxy: z.string().optional(),
  /** HTTPS proxy URL */
  httpsProxy: z.string().optional(),
  /** Default output format */
  outputFormat: z.enum(['table', 'json', 'yaml']).default('table'),
  /** Smithery API key */
  smitheryApiKey: z.string().optional(),
  /** LLM provider configuration — accepts legacy single-provider or multi-provider format */
  llm: z.union([LlmConfigSchema, LlmMultiConfigSchema]).optional(),
}).transform((cfg) => {
  // Backward compatibility: if old daemonUrl is set but mcplocalUrl wasn't explicitly changed,
  // use daemonUrl as mcplocalUrl
  if (cfg.daemonUrl && cfg.mcplocalUrl === 'http://localhost:3200') {
    return { ...cfg, mcplocalUrl: cfg.daemonUrl };
  }
  return cfg;
});

export type McpctlConfig = z.infer<typeof McpctlConfigSchema>;

export const DEFAULT_CONFIG: McpctlConfig = McpctlConfigSchema.parse({});
