'use strict';

const { toOpenAI, messagesToOpenAI, responseFromOpenAI } = require('./tool-adapter');
const { filterToSupportedModels, supportedModelsForProvider } = require('./supported-models');

const DEFAULT_BASE_URL = 'https://api.moonshot.ai/v1';
const DEFAULT_MODEL = 'kimi-k2.6';
const FALLBACK_MODELS = supportedModelsForProvider('moonshot');

function isPlaceholderApiKey(key) {
  return !key || /^(test|test-key|dummy|fake|example)(-|$)/i.test(key) || /^sk-test/i.test(key);
}

function normalizeThinkingMode(value) {
  if (value === true) return 'enabled';
  if (value === false) return 'disabled';
  if (value == null) return null;
  const text = String(value).trim().toLowerCase();
  if (!text) return null;
  if (text === 'true' || text === 'on') return 'enabled';
  if (text === 'false' || text === 'off') return 'disabled';
  if (text === 'enabled' || text === 'disabled') return text;
  return null;
}

function modelNameFromId(id) {
  return String(id || '')
    .replace(/^kimi-/, 'Kimi ')
    .replace(/^moonshot-v1-/, 'Moonshot V1 ')
    .replace(/k2\.6/i, 'K2.6')
    .replace(/k2\.5/i, 'K2.5')
    .replace(/k2-/i, 'K2 ')
    .replace(/-/g, ' ')
    .replace(/\b\w/g, (ch) => ch.toUpperCase())
    .replace(/\bK2\.([56])\b/g, 'K2.$1');
}

function createMoonshotProvider(config = {}) {
  const { apiKey, baseUrl, thinking } = config;

  let _client;
  function client() {
    if (!_client) {
      const OpenAI = require('openai');
      _client = new OpenAI({
        apiKey: apiKey || 'placeholder',
        baseURL: baseUrl || process.env.MOONSHOT_BASE_URL || DEFAULT_BASE_URL,
      });
    }
    return _client;
  }

  return {
    type: 'moonshot',

    async chat({ model, messages, tools, system, maxTokens, temperature, signal, thinking: thinkingOverride } = {}) {
      const t0 = Date.now();
      const targetModel = model || DEFAULT_MODEL;

      const converted = messagesToOpenAI(messages || []);
      if (system) {
        const systemText = typeof system === 'string' ? system : JSON.stringify(system);
        converted.unshift({ role: 'system', content: systemText });
      }

      const params = {
        model: targetModel,
        messages: converted,
      };

      if (tools && tools.length > 0) {
        params.tools = toOpenAI(tools);
      }
      if (maxTokens != null) {
        params.max_tokens = maxTokens;
      }
      if (temperature != null) {
        params.temperature = temperature;
      }

      const resolvedThinking = normalizeThinkingMode(
        thinkingOverride !== undefined ? thinkingOverride : thinking
      );
      if (resolvedThinking) {
        params.extra_body = {
          ...(params.extra_body || {}),
          thinking: { type: resolvedThinking },
        };
      }

      const raw = await client().chat.completions.create(params, {
        ...(signal ? { signal } : {}),
      });

      const latencyMs = Date.now() - t0;
      const normalized = responseFromOpenAI(raw);
      const reasoning = raw?.choices?.[0]?.message?.reasoning_content;

      let stopReason = 'end_turn';
      if (normalized.stopReason === 'tool_calls') {
        stopReason = 'tool_use';
      } else if (normalized.stopReason === 'stop') {
        stopReason = 'end_turn';
      } else if (normalized.stopReason) {
        stopReason = normalized.stopReason;
      }

      return {
        content: normalized.content,
        toolCalls: normalized.toolCalls || [],
        stopReason,
        usage: normalized.usage || { input: 0, output: 0 },
        latencyMs,
        model: raw.model || targetModel,
        provider: 'moonshot',
        reasoningContent: reasoning && typeof reasoning === 'string' ? reasoning : null,
        raw,
      };
    },

    async listModels(options = {}) {
      const exact = Boolean(options.exact || options.liveOnly);
      if (isPlaceholderApiKey(apiKey)) return exact ? [] : FALLBACK_MODELS;
      try {
        const response = await client().models.list();
        const seen = new Set();
        const raw = [];
        for await (const m of response) {
          const id = m.id;
          if (!id || seen.has(id)) continue;
          seen.add(id);
          raw.push({ id, name: modelNameFromId(id) });
        }
        const models = filterToSupportedModels('moonshot', raw);
        return models.length > 0 ? models : FALLBACK_MODELS;
      } catch (err) {
        if (exact) throw err;
        console.warn('[moonshot] Failed to list models from API, using fallback:', err.message);
        return FALLBACK_MODELS;
      }
    },
  };
}

module.exports = {
  createMoonshotProvider,
  DEFAULT_BASE_URL,
  DEFAULT_MODEL,
};
