'use strict';

const fs = require('fs');
const path = require('path');

const DEFAULT_CONFIG_NAME = 'models.json';
const DEFAULT_CONFIG_PATH = path.resolve(__dirname, '..', DEFAULT_CONFIG_NAME);

function isNonEmptyString(value) {
  return typeof value === 'string' && value.trim().length > 0;
}

function parsePositiveInt(value) {
  if (value === null || value === undefined || value === '') return null;
  const num = Number(value);
  if (!Number.isFinite(num)) return null;
  const out = Math.floor(num);
  return out > 0 ? out : null;
}

function normalizeModes(value) {
  if (!value) return null;
  const text = String(value).trim().toLowerCase();
  if (!text) return null;
  const parts = text.split(/[,，\s]+/).filter(Boolean);
  const hasFast = parts.some((p) => p.includes('fast') || p.includes('快速'));
  const hasThinking = parts.some((p) => p.includes('thinking') || p.includes('思考'));
  if (hasFast && hasThinking) return 'fast+thinking';
  if (hasThinking) return 'thinking';
  if (hasFast) return 'fast';
  return null;
}

function normalizeMultimodal(value) {
  if (value === null || value === undefined) return 'none';
  const text = String(value).trim().toLowerCase();
  if (!text) return 'none';
  if (text.includes('无') || text.includes('none') || text.includes('no')) return 'none';
  const parts = text.split(/[,，\s]+/).filter(Boolean);
  const hasImage = parts.some((p) => p.includes('图片') || p.includes('image'));
  const hasVideo = parts.some((p) => p.includes('视频') || p.includes('video'));
  if (hasVideo && hasImage) return 'image+video';
  if (hasVideo) return 'image+video';
  if (hasImage) return 'image';
  return null;
}

function normalizeModel(raw) {
  const name = String(raw.name || raw.model_name || raw.model || '').trim();
  const url = String(raw.url || raw.base_url || '').trim();
  const apiKey = String(raw.apikey || raw.api_key || '').trim();
  const modes = normalizeModes(raw.modes || raw.mode || raw.supported_modes);
  const multimodal = normalizeMultimodal(raw.multimodal || raw.multi_modal || raw.multi);
  const maxOutput = parsePositiveInt(raw.max_output ?? raw.max_tokens ?? raw.max_output_tokens);
  const maxContext = parsePositiveInt(raw.max_context ?? raw.context_window ?? raw.max_context_tokens);
  const valid = Boolean(
    isNonEmptyString(name)
      && isNonEmptyString(url)
      && isNonEmptyString(apiKey)
      && modes
      && multimodal
      && maxOutput
      && maxContext
  );
  return {
    key: name,
    name,
    model_id: name,
    base_url: url,
    api_key: apiKey,
    modes,
    multimodal,
    max_output: maxOutput,
    max_context: maxContext,
    valid,
  };
}

function buildConfig(raw, filePath) {
  const modelsRaw = Array.isArray(raw.models) ? raw.models : [];
  const models = modelsRaw.map((item) => normalizeModel(item || {}));
  const modelMap = new Map();
  models.forEach((model) => {
    if (model.key) modelMap.set(model.key, model);
  });
  const validModels = models.filter((model) => model.valid);
  const defaultModelKey = String(raw.default_model || raw.default_model_key || '').trim();
  const resolvedDefault = modelMap.get(defaultModelKey)?.valid
    ? defaultModelKey
    : (validModels[0] ? validModels[0].key : '');
  return {
    path: filePath,
    tavily_api_key: String(raw.tavily_api_key || '').trim(),
    models,
    valid_models: validModels,
    model_map: modelMap,
    default_model_key: resolvedDefault,
  };
}

function ensureConfig(customPath) {
  const file = customPath || DEFAULT_CONFIG_PATH;
  if (!fs.existsSync(file)) {
    throw new Error(`子智能体模型配置文件不存在: ${file}`);
  }
  const content = fs.readFileSync(file, 'utf8');
  const raw = JSON.parse(content);
  return buildConfig(raw, file);
}

function maskKey(key) {
  if (!key) return '';
  if (key.length <= 8) return key;
  return `${key.slice(0, 3)}...${key.slice(-3)}`;
}

function getModelByKey(config, key) {
  if (!config || !key) return null;
  if (config.model_map && typeof config.model_map.get === 'function') {
    return config.model_map.get(key) || null;
  }
  if (Array.isArray(config.models)) {
    return config.models.find((m) => m && m.key === key) || null;
  }
  return null;
}

module.exports = { ensureConfig, maskKey, getModelByKey };
