/**
 * llm-intent.js
 *
 * LLM 意图解析网关。
 * 接收客服回复文本 + 当前轮次，通过 LLM 做意图分类或实体提取。
 *
 * 支持 OpenAI 兼容接口。客服意图阶段只允许 MiMo 主用、DeepSeek 降级。
 *
 * 环境变量:
 *   CHATBOT_INTENT_LLM_PROVIDER=mimo|deepseek
 *   CHATBOT_INTENT_LLM_MODEL    主模型，默认 mimo-v2.5
 *   CHATBOT_INTENT_LLM_FALLBACK_MODEL 降级模型，默认 deepseek-v4-flash
 */

import process from "node:process";
import { getRoundConfig } from "./chat-templates.js";
import {
  renderPromptTemplate,
  resolveTextPrompt,
} from "../../automation/internal/prompt-runtime.js";
import {
  resolveStageModelFromEnv,
  resolveStageProviderFromEnv,
  resolveProviderCredentialFromEnv,
} from "../../automation/core/llm-env.js";
import { runWithLlmDebugLog } from "../../automation/core/llm-debug-log.js";

// ── 配置 ─────────────────────────────────────────────

export function resolveChatbotIntentModel(env = process.env) {
  return resolveStageModelFromEnv("chatbot_intent", env);
}

function normalizeProvider(value) {
  const normalized = String(value ?? "").trim().toLowerCase();
  return normalized === "mimo" || normalized === "deepseek" ? normalized : "";
}

function defaultModelForProvider(provider) {
  return provider === "mimo" ? "mimo-v2.5" : "deepseek-v4-flash";
}

function getProviderRuntime(provider, model, env = process.env) {
  const credential = resolveProviderCredentialFromEnv(provider, env);
  if (!credential) {
    return null;
  }
  return {
    apiKey: credential.apiKey,
    baseUrl: credential.baseUrl,
    model: String(model || defaultModelForProvider(provider)).trim(),
    provider,
  };
}

function getPrimaryLLMConfig() {
  const requestedProvider = normalizeProvider(resolveStageProviderFromEnv("chatbot_intent", process.env)) || "mimo";
  const runtime = getProviderRuntime(requestedProvider, resolveChatbotIntentModel(), process.env)
    ?? (requestedProvider !== "mimo" ? getProviderRuntime("mimo", "mimo-v2.5", process.env) : null)
    ?? getProviderRuntime("deepseek", process.env.CHATBOT_INTENT_LLM_FALLBACK_MODEL || "deepseek-v4-flash", process.env);
  if (!runtime) {
    throw new Error("缺少客服意图 LLM 配置。请设置 MIMO_LLM_BASE_URL/MIMO_LLM_API_KEY，或配置 DEEPSEEK_LLM_BASE_URL/DEEPSEEK_LLM_API_KEY 作为降级。");
  }
  return runtime;
}

function getFallbackLLMConfig(primaryProvider) {
  const provider = normalizeProvider(process.env.CHATBOT_INTENT_LLM_FALLBACK_PROVIDER) || "deepseek";
  if (provider === primaryProvider) {
    return null;
  }
  return getProviderRuntime(provider, process.env.CHATBOT_INTENT_LLM_FALLBACK_MODEL || defaultModelForProvider(provider), process.env);
}

const CHATBOT_PROMPT_KEYS = {
  1: "chatbot.intent.round_1.system",
  2: "chatbot.intent.round_2.system",
  3: "chatbot.intent.round_3.system",
  4: "chatbot.intent.round_4.system",
  generic: "chatbot.intent.generic_round.system",
};

export function getPromptScope() {
  const provider = normalizeProvider(resolveStageProviderFromEnv("chatbot_intent", process.env)) || "mimo";
  return {
    provider: process.env.PROMPT_PROVIDER || provider,
    model: resolveChatbotIntentModel(),
  };
}

export function buildGenericRoundSystemPrompt(currentRound, roundConfig, template) {
  return renderPromptTemplate(template, {
    current_round: currentRound,
    round_name: roundConfig.name,
    template_text: roundConfig.templateText,
    pass_condition: roundConfig.passCondition || "",
  });
}

export async function buildSystemPrompt(currentRound) {
  const roundConfig = getRoundConfig(currentRound);
  const promptKey = CHATBOT_PROMPT_KEYS[currentRound] ?? CHATBOT_PROMPT_KEYS.generic;
  const prompt = await resolveTextPrompt(promptKey, {
    ...getPromptScope(),
  });
  const template = prompt.text;

  if (!CHATBOT_PROMPT_KEYS[currentRound]) {
    return buildGenericRoundSystemPrompt(currentRound, roundConfig, template);
  }

  return renderPromptTemplate(template, {
    round_name: roundConfig.name,
    template_text: roundConfig.templateText,
    pass_condition: roundConfig.passCondition || "",
  });
}

// ── LLM 调用 ─────────────────────────────────────────

/**
 * 调用 OpenAI 兼容 Chat Completion API
 *
 * @param {string} systemPrompt
 * @param {string} userMessage
 * @returns {Promise<string>} 模型输出的文本
 */
export async function callLLM(systemPrompt, userMessage) {
  const config = getPrimaryLLMConfig();
  console.log(`  🤖 [LLM] 使用客服意图模型: ${config.model}`);

  const request = {
    model: config.model,
    messages: [
      { role: "system", content: systemPrompt },
      { role: "user", content: userMessage },
    ],
    temperature: 0.1,
    max_tokens: 512,
  };
  const invoke = async (runtimeConfig) => runWithLlmDebugLog(
    {
      scope: "chatbot",
      stage: "chatbot_intent",
      label: "callLLM",
      provider: runtimeConfig.provider,
      model: runtimeConfig.model,
    },
    { ...request, model: runtimeConfig.model },
    async () => {
      const response = await fetch(`${runtimeConfig.baseUrl}/chat/completions`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          ...(runtimeConfig.provider === "mimo"
            ? { "api-key": runtimeConfig.apiKey }
            : { Authorization: `Bearer ${runtimeConfig.apiKey}` }),
        },
        body: JSON.stringify({ ...request, model: runtimeConfig.model }),
      });

      if (!response.ok) {
        const body = await response.text().catch(() => "");
        throw new Error(`LLM API 调用失败: HTTP ${response.status} - ${body.slice(0, 200)}`);
      }

      return response.json();
    },
  );

  try {
    const data = await invoke(config);
    const content = data.choices?.[0]?.message?.content ?? "";
    if (!String(content).trim()) {
      throw new Error("LLM API 调用失败: 返回内容为空");
    }
    return content;
  } catch (error) {
    const fallback = getFallbackLLMConfig(config.provider);
    if (!fallback) {
      throw error;
    }
    const message = error instanceof Error ? error.message : String(error);
    console.warn(`  🤖 [LLM] 客服意图主模型失败，降级到 ${fallback.provider}/${fallback.model}: ${message}`);
    const data = await invoke(fallback);
    return data.choices?.[0]?.message?.content ?? "";
  }
}

/**
 * 解析 LLM 输出的 JSON（容错：处理 markdown 代码块包裹）
 */
function parseLLMJson(raw) {
  let cleaned = raw.trim();
  // 去掉 ```json ... ``` 包裹
  if (cleaned.startsWith("```")) {
    cleaned = cleaned.replace(/^```(?:json)?\s*/, "").replace(/\s*```$/, "");
  }
  return JSON.parse(cleaned);
}

// ── 公共入口 ─────────────────────────────────────────

/**
 * 分析客服回复
 *
 * @param {string} replyText    客服回复文本
 * @param {number} currentRound 当前轮次 (1-N)
 * @param {object} [context]    可选的上下文 (材料名/规格等，附加到 user message)
 * @returns {Promise<object>}   各轮次对应的结构化结果
 */
export async function analyzeReply(replyText, currentRound, context = {}) {
  const systemPrompt = await buildSystemPrompt(currentRound);

  // 构造 user message，附加上下文
  let userMessage = `客服回复内容：\n"${replyText}"`;
  const itemName = context.standardized_name || context.original_name || context.material_name || context.title;
  if (itemName) {
    userMessage += `\n\n参考信息：商品名称=${itemName}`;
    if (context.standardized_spec || context.original_spec || context.specification) {
      userMessage += `，规格=${context.standardized_spec || context.original_spec || context.specification}`;
    }
    if (context.quantity) userMessage += `，需求量=${context.quantity}${context.standardized_unit || context.unit || ""}`;
    if (context.brand) userMessage += `，品牌=${context.brand}`;
  }

  console.log(`  🤖 [LLM] 分析第 ${currentRound} 轮回复，模型=${resolveChatbotIntentModel()}...`);

  const raw = await callLLM(systemPrompt, userMessage);
  console.log(`  🤖 [LLM] 原始输出: ${raw.slice(0, 120)}`);

  try {
    const parsed = parseLLMJson(raw);
    return { ...parsed, _raw: raw };
  } catch {
    console.error(`  ⚠️ [LLM] JSON 解析失败，原始输出: ${raw}`);
    // 解析失败 → 保守处理为 PENDING（人工接管）
    return {
      passed: false,
      status: "PENDING",
      reason: `LLM 输出解析失败: ${raw.slice(0, 100)}`,
      _raw: raw,
    };
  }
}
