/**
 * MCP 配置加载和验证
 */

import * as fs from 'fs';
import * as path from 'path';
import * as yaml from 'yaml';
import type {
  MCPConfig,
  MCPServerConfig,
  LocalMCPServer,
  RemoteMCPServer,
} from './types.js';
import { getConfigDir } from '../constants/paths.js';

/** 默认配置值 */
const DEFAULTS = {
  timeout: 30000,
  enabled: true,
};

/**
 * 解析环境变量引用
 * 支持 {env:VAR_NAME} 语法
 */
export function resolveEnvVariables(value: string): string {
  return value.replace(/\{env:([^}]+)\}/g, (_, varName) => {
    const envValue = process.env[varName];
    if (envValue === undefined) {
      console.warn(`警告: 环境变量 ${varName} 未设置`);
      return '';
    }
    return envValue;
  });
}

/**
 * 递归解析对象中的环境变量
 */
export function resolveEnvInObject<T>(obj: T): T {
  if (typeof obj === 'string') {
    return resolveEnvVariables(obj) as T;
  }
  if (Array.isArray(obj)) {
    return obj.map((item) => resolveEnvInObject(item)) as T;
  }
  if (obj !== null && typeof obj === 'object') {
    const result: Record<string, unknown> = {};
    for (const [key, value] of Object.entries(obj)) {
      result[key] = resolveEnvInObject(value);
    }
    return result as T;
  }
  return obj;
}

/**
 * 验证本地服务器配置
 */
function validateLocalServer(
  name: string,
  config: LocalMCPServer
): string | null {
  if (!config.command || !Array.isArray(config.command)) {
    return `服务器 "${name}": command 必须是字符串数组`;
  }
  if (config.command.length === 0) {
    return `服务器 "${name}": command 不能为空`;
  }
  if (config.timeout !== undefined && typeof config.timeout !== 'number') {
    return `服务器 "${name}": timeout 必须是数字`;
  }
  return null;
}

/**
 * 验证远程服务器配置
 */
function validateRemoteServer(
  name: string,
  config: RemoteMCPServer
): string | null {
  if (!config.url || typeof config.url !== 'string') {
    return `服务器 "${name}": url 是必需的`;
  }
  try {
    new URL(config.url);
  } catch {
    return `服务器 "${name}": url 格式无效`;
  }
  if (config.timeout !== undefined && typeof config.timeout !== 'number') {
    return `服务器 "${name}": timeout 必须是数字`;
  }
  return null;
}

/**
 * 验证服务器配置
 */
function validateServerConfig(
  name: string,
  config: MCPServerConfig
): string | null {
  if (!config.type) {
    return `服务器 "${name}": type 是必需的 (local 或 remote)`;
  }
  if (config.type === 'local') {
    return validateLocalServer(name, config as LocalMCPServer);
  }
  if (config.type === 'remote') {
    return validateRemoteServer(name, config as RemoteMCPServer);
  }
  return `服务器 "${name}": type 必须是 "local" 或 "remote"`;
}

/**
 * 验证 MCP 配置
 */
export function validateMCPConfig(config: MCPConfig): string[] {
  const errors: string[] = [];

  if (!config.mcp) {
    return errors; // 没有 MCP 配置是合法的
  }

  if (typeof config.mcp !== 'object' || Array.isArray(config.mcp)) {
    errors.push('mcp 配置必须是对象格式');
    return errors;
  }

  for (const [name, serverConfig] of Object.entries(config.mcp)) {
    // 验证服务器名称
    if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name)) {
      errors.push(
        `服务器名称 "${name}" 无效: 必须以字母开头，只能包含字母、数字、下划线和连字符`
      );
      continue;
    }

    const error = validateServerConfig(name, serverConfig);
    if (error) {
      errors.push(error);
    }
  }

  // 验证 tools 配置
  if (config.tools) {
    if (typeof config.tools !== 'object' || Array.isArray(config.tools)) {
      errors.push('tools 配置必须是对象格式');
    } else {
      for (const [pattern, enabled] of Object.entries(config.tools)) {
        if (typeof enabled !== 'boolean') {
          errors.push(`tools["${pattern}"] 的值必须是布尔值`);
        }
      }
    }
  }

  return errors;
}

/**
 * 规范化服务器配置（添加默认值）
 */
function normalizeServerConfig(config: MCPServerConfig): MCPServerConfig {
  return {
    ...config,
    enabled: config.enabled ?? DEFAULTS.enabled,
    timeout: config.timeout ?? DEFAULTS.timeout,
  };
}

/**
 * 规范化 MCP 配置
 */
export function normalizeMCPConfig(config: MCPConfig): MCPConfig {
  if (!config.mcp) {
    return config;
  }

  const normalizedMcp: Record<string, MCPServerConfig> = {};
  for (const [name, serverConfig] of Object.entries(config.mcp)) {
    normalizedMcp[name] = normalizeServerConfig(serverConfig);
  }

  return {
    ...config,
    mcp: normalizedMcp,
  };
}

/**
 * 从文件加载配置
 */
function loadConfigFile(filePath: string): MCPConfig | null {
  if (!fs.existsSync(filePath)) {
    return null;
  }

  try {
    const content = fs.readFileSync(filePath, 'utf-8');
    const ext = path.extname(filePath).toLowerCase();

    if (ext === '.json' || ext === '.jsonc') {
      // 移除 JSONC 注释
      const jsonContent = content.replace(
        /\/\/.*$|\/\*[\s\S]*?\*\//gm,
        ''
      );
      return JSON.parse(jsonContent);
    }
    if (ext === '.yaml' || ext === '.yml') {
      return yaml.parse(content);
    }

    console.warn(`不支持的配置文件格式: ${ext}`);
    return null;
  } catch (error) {
    console.error(`加载配置文件失败 ${filePath}:`, error);
    return null;
  }
}

/**
 * 合并配置（后者覆盖前者）
 */
function mergeConfigs(base: MCPConfig, override: MCPConfig): MCPConfig {
  return {
    mcp: {
      ...base.mcp,
      ...override.mcp,
    },
    tools: {
      ...base.tools,
      ...override.tools,
    },
  };
}

/**
 * 加载 MCP 配置
 * 按优先级从低到高加载：
 * 1. 用户级: ~/.ai-terminal-assistant/mcp.{json,yaml}
 * 2. 项目级: .ai-assist/config.{json,yaml}
 */
export function loadMCPConfig(workdir?: string): MCPConfig {
  const cwd = workdir || process.cwd();
  const configDir = getConfigDir();

  // 配置文件搜索路径
  const searchPaths = [
    // 用户级配置（统一到 ~/.ai-terminal-assistant/）
    path.join(configDir, 'mcp.json'),
    path.join(configDir, 'mcp.jsonc'),
    path.join(configDir, 'mcp.yaml'),
    path.join(configDir, 'mcp.yml'),
    // 项目级配置
    path.join(cwd, '.ai-assist', 'config.json'),
    path.join(cwd, '.ai-assist', 'config.jsonc'),
    path.join(cwd, '.ai-assist', 'config.yaml'),
    path.join(cwd, '.ai-assist', 'config.yml'),
  ];

  let mergedConfig: MCPConfig = {};

  for (const configPath of searchPaths) {
    const config = loadConfigFile(configPath);
    if (config) {
      mergedConfig = mergeConfigs(mergedConfig, config);
    }
  }

  // 验证配置
  const errors = validateMCPConfig(mergedConfig);
  if (errors.length > 0) {
    console.error('MCP 配置验证失败:');
    for (const error of errors) {
      console.error(`  - ${error}`);
    }
    // 返回空配置而不是无效配置
    return {};
  }

  // 规范化配置
  const normalizedConfig = normalizeMCPConfig(mergedConfig);

  // 解析环境变量
  return resolveEnvInObject(normalizedConfig);
}

/**
 * 获取已启用的服务器列表
 */
export function getEnabledServers(
  config: MCPConfig
): Array<{ name: string; config: MCPServerConfig }> {
  if (!config.mcp) {
    return [];
  }

  return Object.entries(config.mcp)
    .filter(([, serverConfig]) => serverConfig.enabled !== false)
    .map(([name, serverConfig]) => ({ name, config: serverConfig }));
}

/**
 * 检查工具是否被配置启用
 * 支持通配符匹配，如 "server-*"
 */
export function isToolEnabled(
  toolName: string,
  toolsConfig?: Record<string, boolean>
): boolean {
  if (!toolsConfig) {
    return true; // 默认启用
  }

  // 精确匹配优先
  if (toolName in toolsConfig) {
    return toolsConfig[toolName];
  }

  // 通配符匹配（从最具体到最通用）
  const patterns = Object.keys(toolsConfig)
    .filter((pattern) => pattern.includes('*'))
    .sort((a, b) => {
      // 更具体的模式（* 出现位置更靠后）优先
      const aPos = a.indexOf('*');
      const bPos = b.indexOf('*');
      return bPos - aPos;
    });

  for (const pattern of patterns) {
    const regex = new RegExp(
      '^' + pattern.replace(/\*/g, '.*').replace(/\?/g, '.') + '$'
    );
    if (regex.test(toolName)) {
      return toolsConfig[pattern];
    }
  }

  return true; // 默认启用
}
