// {{ display_name }} MCP server — generated by mcpify. Do not hand-edit.

import { existsSync, readFileSync } from 'node:fs';
import { homedir } from 'node:os';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

import yaml from 'js-yaml';

import { ConfigSchema, type Config } from './config-schema.js';
import { ConfigurationError } from './errors.js';

const ENV_PREFIX = '{{ tool_prefix_env }}';
const CONFIG_DIR_NAME = '.{{ project_name }}';

function readYamlIfExists(path: string): Record<string, unknown> {
  if (!existsSync(path)) return {};
  return (yaml.load(readFileSync(path, 'utf8')) as Record<string, unknown>) ?? {};
}

function envOverrides(): Record<string, unknown> {
  const pick = (key: string): string | undefined => process.env[`${ENV_PREFIX}_${key}`];
  const candidates: Record<string, string | undefined> = {
    url: pick('URL'),
    auth_method: pick('AUTH_METHOD'),
    api_version: pick('API_VERSION'),
    log_level: pick('LOG_LEVEL'),
    transport: pick('TRANSPORT'),
    host: pick('HOST'),
    cors_allow: pick('CORS_ALLOW'),
    rate_limit: pick('RATE_LIMIT'),
    timeout_ms: pick('TIMEOUT_MS'),
    cache_size: pick('CACHE_SIZE'),
    retry_attempts: pick('RETRY_ATTEMPTS'),
    port: pick('PORT'),
  };
  return Object.fromEntries(Object.entries(candidates).filter(([, value]) => value !== undefined));
}

/**
 * Resolves configuration through the strict, stop-at-first-match cascade
 * (REQ-2.2): CLI flags -> env vars -> local file (./{{ project_name }}.config.yml)
 * -> home file (~/.{{ project_name }}/config.yml) -> system file
 * (/etc/{{ project_name }}/config.yml) -> install-dir file -> built-in defaults
 * (applied by ConfigSchema's per-field `.default()`).
 */
export function loadConfig(cliFlags: Partial<Config> = {}): Config {
  const installDir = dirname(fileURLToPath(import.meta.url));

  const layers: Record<string, unknown>[] = [
    cliFlags,
    envOverrides(),
    readYamlIfExists(join(process.cwd(), '{{ project_name }}.config.yml')),
    readYamlIfExists(join(homedir(), CONFIG_DIR_NAME, 'config.yml')),
    readYamlIfExists(join('/etc', '{{ project_name }}', 'config.yml')),
    readYamlIfExists(join(installDir, 'config.yml')),
  ];

  // reduceRight applies the lowest-priority layer first, then spreads each
  // higher-priority layer on top — cliFlags (index 0) is applied last, so
  // it always wins, matching the cascade's stop-at-first-match ordering.
  const merged = layers.reduceRight<Record<string, unknown>>((acc, layer) => ({ ...acc, ...layer }), {});

  const result = ConfigSchema.safeParse(merged);
  if (!result.success) {
    throw new ConfigurationError(`invalid configuration: ${result.error.message}`);
  }
  return result.data;
}
