/**
 * 模型配置校验工具
 *
 * 两层校验：
 * 1. 结构校验（JSON Schema）- 检查必填字段、枚举值、格式
 * 2. 可用性校验（API 测试）- 检查模型是否真正可用
 */

import { ChatOpenAI } from '@langchain/openai';
import { config } from './index';
import fs from 'fs';
import path from 'path';
import { log } from '../services/logger.service';

// ============ 结构校验（无需外部依赖）============

const ALLOWED_INPUTS = ['text', 'tts', 'image', 'video'];
const ALLOWED_API_TYPES = ['openai-chat'];

interface ValidationIssue {
  severity: 'error' | 'warn';
  path: string;       // JSON path, e.g. "vendors.minimax.models[0]"
  message: string;
  fix?: string;
}

/**
 * 校验 models.json 结构（启动时调用，不依赖外部 API）
 * 返回 issues 列表，error=必须修复，warn=建议修复
 */
function validateModelsJsonStructure(): ValidationIssue[] {
  const issues: ValidationIssue[] = [];
  const models = config.models as any;

  if (!models?.vendors) {
    issues.push({ severity: 'error', path: 'vendors', message: '缺少 vendors 配置' });
    return issues;
  }

  for (const [vendorKey, vendorData] of Object.entries(models.vendors) as [string, any][]) {
    // 检查必填字段
    if (!vendorData.name) {
      issues.push({ severity: 'warn', path: `vendors.${vendorKey}`, message: '缺少 name 字段' });
    }
    if (!vendorData.apiKey) {
      issues.push({ severity: 'error', path: `vendors.${vendorKey}.apiKey`, message: '缺少 apiKey 字段' });
    }
    if (!vendorData.baseUrl) {
      issues.push({ severity: 'warn', path: `vendors.${vendorKey}.baseUrl`, message: '缺少 baseUrl 字段' });
    }

    // 检查 models 数组
    const modelsArr = vendorData.models || [];
    if (!Array.isArray(modelsArr)) {
      issues.push({ severity: 'error', path: `vendors.${vendorKey}.models`, message: 'models 必须是数组' });
      continue;
    }

    const seenIds = new Set<string>();
    for (let i = 0; i < modelsArr.length; i++) {
      const model = modelsArr[i];
      const modelPath = `vendors.${vendorKey}.models[${i}]`;

      // 检查 id
      if (!model.id) {
        issues.push({ severity: 'error', path: modelPath, message: '缺少 id 字段' });
        continue;
      }

      // 检查 id 重复
      if (seenIds.has(model.id)) {
        issues.push({ severity: 'error', path: modelPath, message: `id 重复: ${model.id}` });
      }
      seenIds.add(model.id);

      // 检查 input 字段
      if (!model.input) {
        issues.push({ severity: 'error', path: modelPath, message: '缺少 input 字段' });
      } else if (!Array.isArray(model.input)) {
        issues.push({ severity: 'error', path: modelPath, message: `input 必须是数组，当前为 ${typeof model.input}` });
      } else {
        for (const inputVal of model.input) {
          if (!ALLOWED_INPUTS.includes(inputVal)) {
            issues.push({
              severity: 'warn',
              path: `${modelPath}.input`,
              message: `input 包含未知值 "${inputVal}"，可选值: ${ALLOWED_INPUTS.join(', ')}`,
              fix: `移除 "${inputVal}" 或使用允许的值`,
            });
          }
        }
      }

      // TTS 模型必须检查
      if (model.input?.includes('tts')) {
        if (!model.enabled) {
          issues.push({ severity: 'warn', path: modelPath, message: `TTS 模型 ${model.id} 已禁用` });
        }
        if (!model.maxTextLength) {
          issues.push({ severity: 'warn', path: modelPath, message: `TTS 模型 ${model.id} 缺少 maxTextLength，将使用默认值 1000` });
        }
      }

      // text 模型必须检查
      if (model.input?.includes('text')) {
        if (model.enabled && !vendorData.apiKey) {
          issues.push({ severity: 'error', path: modelPath, message: `文本模型 ${model.id} 启用但 vendor 缺少 apiKey` });
        }
      }
    }
  }

  // 检查顶层配置
  if (!models.textGeneration?.defaultModel) {
    issues.push({ severity: 'warn', path: 'textGeneration.defaultModel', message: '缺少默认文本模型配置' });
  }
  if (!models.tts?.defaultModel) {
    issues.push({ severity: 'warn', path: 'tts.defaultModel', message: '缺少默认 TTS 模型配置' });
  }

  return issues;
}

/**
 * 打印校验结果（友好格式）
 */
function printValidationReport(issues: ValidationIssue[]): void {
  if (issues.length === 0) {
    log.info('✅ models.json 结构校验通过');
    return;
  }

  const errors = issues.filter(i => i.severity === 'error');
  const warnings = issues.filter(i => i.severity === 'warn');

  if (errors.length > 0) {
    log.error(`❌ models.json 结构校验失败 (${errors.length} 个错误):`);
    for (const issue of errors) {
      log.error(`   [${issue.path}] ${issue.message}`);
      if (issue.fix) log.error(`      修复: ${issue.fix}`);
    }
  }

  if (warnings.length > 0) {
    log.warn(`⚠️  models.json 结构校验警告 (${warnings.length} 个):`);
    for (const issue of warnings) {
      log.warn(`   [${issue.path}] ${issue.message}`);
      if (issue.fix) log.warn(`      修复: ${issue.fix}`);
    }
  }
}

// ============ 可用性校验（需要外部 API）============

// ============ 可用性校验（需要外部 API）============

interface ModelValidationResult {
  id: string;
  name: string;
  input: string[];
  vendor: string;
  available: boolean;
  error?: string;
  responseTime?: number; // 毫秒
}

interface ValidationReport {
  timestamp: string;
  totalModels: number;
  availableModels: number;
  unavailableModels: number;
  results: ModelValidationResult[];
}

/**
 * 验证单个模型是否可用
 */
async function validateModel(model: any): Promise<ModelValidationResult> {
  const result: ModelValidationResult = {
    id: model.id,
    name: model.name,
    input: model.input,
    vendor: model.vendorName || model.vendor,
    available: false,
  };

  // 检查 baseUrl 和 apiKey（现在在 vendor 级别，通过 config 注入到 model）
  if (!model.apiKey || !model.baseUrl) {
    result.error = '缺少 apiKey 或 baseUrl';
    return result;
  }

  const startTime = Date.now();

  try {
    // 只有 text 类型用 LangChain 测试
    if (model.input?.includes('text')) {
      const llm = new ChatOpenAI({
        model: model.id,
        apiKey: model.apiKey,
        configuration: { baseURL: model.baseUrl },
        temperature: 0.7,
        timeout: 15000,
      });
      await llm.invoke('你好');
    } else {
      // TTS/Image/Video 暂时标记为待验证（需要不同的 SDK）
      result.available = false;
      result.responseTime = Date.now() - startTime;
      result.error = '需要手动验证';
      return result;
    }

    result.available = true;
    result.responseTime = Date.now() - startTime;
  } catch (error: any) {
    result.responseTime = Date.now() - startTime;
    const errorMsg = error.response?.data?.message || error.message || '未知错误';
    result.error = errorMsg;

    // 检查是否是认证错误（key 无效）
    if (error.response?.status === 401 || errorMsg.includes('invalid')) {
      result.error = `认证失败: ${errorMsg}`;
    } else if (error.response?.status === 403) {
      result.error = `权限不足: ${errorMsg}`;
    } else if (error.response?.status === 429) {
      result.error = `限流: ${errorMsg}`;
    }
  }

  return result;
}

/**
 * 批量验证所有模型
 */
async function validateAllModels(): Promise<ValidationReport> {
  const models = config.models.list.filter((m: any) => m.enabled !== false);
  const results: ModelValidationResult[] = [];

  console.log('\n========== 模型验证开始 ==========\n');

  for (const model of models) {
    process.stdout.write(`验证 ${model.id}... `);
    const result = await validateModel(model);
    results.push(result);

    if (result.available) {
      console.log(`✅ 可用 (${result.responseTime}ms)`);
    } else {
      console.log(`❌ 不可用 - ${result.error}`);
    }
  }

  const availableCount = results.filter(r => r.available).length;
  const unavailableCount = results.filter(r => !r.available).length;

  console.log('\n========== 验证结果 ==========');
  console.log(`总计: ${models.length} | 可用: ${availableCount} | 不可用: ${unavailableCount}`);

  const report: ValidationReport = {
    timestamp: new Date().toISOString(),
    totalModels: models.length,
    availableModels: availableCount,
    unavailableModels: unavailableCount,
    results,
  };

  // 保存报告到文件
  const reportPath = path.join(process.cwd(), 'model-validation-report.json');
  fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
  console.log(`\n详细报告已保存: ${reportPath}`);

  return report;
}

/**
 * 仅验证特定类型的模型
 */
async function validateModelsByType(type: 'text' | 'tts' | 'image' | 'video'): Promise<ValidationReport> {
  const models = config.models.getModelsByType(type);
  const results: ModelValidationResult[] = [];

  console.log(`\n========== 验证 ${type} 模型 ==========\n`);

  for (const model of models) {
    process.stdout.write(`验证 ${model.id}... `);
    const result = await validateModel(model);
    results.push(result);

    if (result.available) {
      console.log(`✅ 可用 (${result.responseTime}ms)`);
    } else {
      console.log(`❌ 不可用 - ${result.error}`);
    }
  }

  const report: ValidationReport = {
    timestamp: new Date().toISOString(),
    totalModels: models.length,
    availableModels: results.filter(r => r.available).length,
    unavailableModels: results.filter(r => !r.available).length,
    results,
  };

  return report;
}

// 如果直接运行此文件，执行校验
if (require.main === module) {
  const args = process.argv.slice(2);
  const type = args[0] as 'text' | 'tts' | 'image' | 'video' | undefined;
  const onlyStructure = args.includes('--check');

  (async () => {
    console.log('\n========== 模型配置校验 ==========\n');

    // 1. 结构校验（无需 API 调用）
    const structureIssues = validateModelsJsonStructure();
    printValidationReport(structureIssues);

    const hasErrors = structureIssues.some(i => i.severity === 'error');
    if (hasErrors) {
      console.log('\n❌ 结构校验失败，跳过可用性校验');
      process.exit(1);
    }

    if (onlyStructure) {
      console.log('\n✅ 结构校验通过（--check 模式，仅做结构检查）');
      process.exit(0);
    }

    // 2. 可用性校验
    if (type) {
      await validateModelsByType(type);
    } else {
      await validateAllModels();
    }

    process.exit(0);
  })();
}

export {
  validateModelsJsonStructure,
  printValidationReport,
  validateAllModels,
  validateModelsByType,
  validateModel,
  type ModelValidationResult,
  type ValidationReport,
  type ValidationIssue,
};
