// Copyright (c) 2026 defconxt. All rights reserved.
// Licensed under AGPL-3.0 — see LICENSE file for details.
// NERF is a trademark of defconxt.

/**
 * config-validate.js — Validates raw config from loadConfig() into a
 * flat GatewayConfig-like object.
 *
 * Mirrors Python's GatewayConfig.__post_init__ validation:
 * - backend must be one of ['ollama', 'claude', 'openai', 'openrouter', 'openai-compat', 'pi-ai']
 * - required model field per backend
 * - extracts nested sections into flat validated fields
 *
 * API keys are treated as opaque strings — never logged or included
 * in error messages.
 *
 * @module gateway/config-validate
 */

const VALID_BACKENDS = ['ollama', 'claude', 'openai', 'openrouter', 'openai-compat', 'pi-ai', 'pi'];

/**
 * @typedef {Object} GatewayConfig
 * @property {string} backend       - "ollama" | "claude" | "openai" | "openrouter" | "openai-compat" | "pi-ai"
 * @property {string} ollama_base_url
 * @property {string} ollama_model
 * @property {number} ollama_timeout
 * @property {string} claude_api_key
 * @property {string} claude_model
 * @property {number} claude_timeout
 * @property {string} openai_api_key
 * @property {string} openai_model
 * @property {number} openai_timeout
 * @property {string} openrouter_api_key
 * @property {string} openrouter_model
 * @property {number} openrouter_timeout
 * @property {string} compat_base_url
 * @property {string} compat_api_key
 * @property {string} compat_model
 * @property {number} compat_timeout
 * @property {string} pi_provider
 * @property {string} pi_model
 */

/**
 * Validate a raw config object and produce a flat GatewayConfig.
 *
 * @param {Record<string, any>} raw - Raw config from loadConfig()
 * @returns {GatewayConfig}
 * @throws {Error} If backend is invalid or required fields are missing
 */
export function validateConfig(raw) {
  if (!raw || typeof raw !== 'object') {
    throw new Error(
      "No configuration found.\nrun: nerf setup"
    );
  }

  const backend = raw.llm_backend || '';

  if (!backend) {
    throw new Error(
      "No LLM backend configured. Set 'llm_backend' in config.yaml or run: nerf setup"
    );
  }

  if (!VALID_BACKENDS.includes(backend)) {
    throw new Error(
      `Invalid backend '${backend}'. Must be one of ${VALID_BACKENDS.join(', ')}.\n` +
      "Set 'llm_backend' in config.yaml or run: nerf setup"
    );
  }

  const ollamaSection = (raw.ollama && typeof raw.ollama === 'object') ? raw.ollama : {};
  const claudeSection = (raw.claude && typeof raw.claude === 'object') ? raw.claude : {};
  const openaiSection = (raw.openai && typeof raw.openai === 'object') ? raw.openai : {};
  const openrouterSection = (raw.openrouter && typeof raw.openrouter === 'object') ? raw.openrouter : {};
  const compatSection = (raw.openai_compat && typeof raw.openai_compat === 'object') ? raw.openai_compat : {};
  const piSection = (raw.pi_ai && typeof raw.pi_ai === 'object') ? raw.pi_ai : (raw.pi && typeof raw.pi === 'object') ? raw.pi : {};

  const config = {
    backend,
    ollama_base_url: ollamaSection.base_url || 'http://127.0.0.1:11434',
    ollama_model: ollamaSection.model || '',
    ollama_timeout: parseInt(ollamaSection.timeout ?? 300, 10),
    claude_api_key: claudeSection.api_key || '',
    claude_model: claudeSection.model || '',
    claude_timeout: parseInt(claudeSection.timeout ?? 60, 10),
    openai_api_key: openaiSection.api_key || '',
    openai_model: openaiSection.model || '',
    openai_timeout: parseInt(openaiSection.timeout ?? 120, 10),
    openrouter_api_key: openrouterSection.api_key || '',
    openrouter_model: openrouterSection.model || '',
    openrouter_timeout: parseInt(openrouterSection.timeout ?? 120, 10),
    compat_base_url: compatSection.base_url || '',
    compat_api_key: compatSection.api_key || '',
    compat_model: compatSection.model || '',
    compat_timeout: parseInt(compatSection.timeout ?? 120, 10),
    pi_provider: piSection.provider || 'anthropic',
    pi_model: piSection.model || '',
  };

  // Backend-specific required field validation
  if (backend === 'ollama' && !config.ollama_model) {
    throw new Error(
      "ollama_model must be set when backend is 'ollama'.\n" +
      "Set 'ollama.model' in config.yaml or run: nerf setup"
    );
  }

  if (backend === 'claude' && !config.claude_model) {
    throw new Error(
      "claude_model must be set when backend is 'claude'.\n" +
      "Set 'claude.model' in config.yaml or run: nerf setup"
    );
  }

  if (backend === 'openai' && !config.openai_model) {
    throw new Error(
      "openai_model must be set when backend is 'openai'.\n" +
      "Set 'openai.model' in config.yaml or run: nerf setup"
    );
  }

  if (backend === 'openrouter' && !config.openrouter_model) {
    throw new Error(
      "openrouter_model must be set when backend is 'openrouter'.\n" +
      "Set 'openrouter.model' in config.yaml or run: nerf setup"
    );
  }

  if (backend === 'openai-compat') {
    if (!config.compat_model) {
      throw new Error(
        "compat_model must be set when backend is 'openai-compat'.\n" +
        "Set 'openai_compat.model' in config.yaml or run: nerf setup"
      );
    }
    if (!config.compat_base_url) {
      throw new Error(
        "compat_base_url must be set when backend is 'openai-compat'.\n" +
        "Set 'openai_compat.base_url' in config.yaml (e.g. https://api.groq.com/openai/v1)"
      );
    }
  }

  if ((backend === 'pi-ai' || backend === 'pi') && !config.pi_model) {
    throw new Error(
      "pi_model must be set when backend is 'pi-ai'.\n" +
      "Set 'pi_ai.model' in config.yaml (e.g. claude-sonnet-4-20250514) or run: nerf setup"
    );
  }

  return config;
}

export { VALID_BACKENDS };
