'use strict';

const { getModelProfile } = require('./model_profiles');

function computeMaxTokens(profile, currentContextTokens) {
  const baseMax = Number.isFinite(profile.max_output) ? Math.max(1, Math.floor(profile.max_output)) : null;
  if (!baseMax) return null;
  const maxContext = Number.isFinite(profile.max_context) ? Math.max(1, Math.floor(profile.max_context)) : null;
  if (!maxContext) return baseMax;
  const used = Number.isFinite(currentContextTokens) ? Math.max(0, Math.floor(currentContextTokens)) : 0;
  const available = maxContext - used;
  if (available <= 0) return 1;
  return Math.min(baseMax, available);
}

async function* streamChat({ config, modelKey, messages, tools, thinkingMode, currentContextTokens, abortSignal }) {
  const profile = getModelProfile(config, modelKey);
  const url = `${profile.base_url}/chat/completions`;
  const headers = {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${profile.api_key}`,
  };

  const payload = {
    model: profile.model_id,
    messages,
    tools,
    tool_choice: tools && tools.length ? 'auto' : undefined,
    stream: true,
    stream_options: { include_usage: true },
  };
  payload.include_usage = true;
  payload.reasoning_split = true;
  const maxTokens = computeMaxTokens(profile, currentContextTokens);
  if (maxTokens) payload.max_tokens = maxTokens;

  const useThinking = thinkingMode && profile.supports_thinking;
  if (useThinking) {
    Object.assign(payload, profile.thinking_params.thinking);
  } else {
    Object.assign(payload, profile.thinking_params.fast);
  }

  let res;
  try {
    res = await fetch(url, {
      method: 'POST',
      headers,
      body: JSON.stringify(payload),
      signal: abortSignal,
    });
  } catch (err) {
    if (abortSignal && abortSignal.aborted) {
      const error = new Error('请求已取消');
      error.code = 'aborted';
      throw error;
    }
    const cause = err && err.cause ? ` (${err.cause.code || err.cause.message || err.cause})` : '';
    throw new Error(`请求失败: ${err.message || err}${cause}`);
  }

  if (!res.ok || !res.body) {
    const text = await res.text();
    throw new Error(`API错误 ${res.status}: ${text}`);
  }

  const reader = res.body.getReader();
  const decoder = new TextDecoder('utf-8');
  let buffer = '';

  while (true) {
    if (abortSignal && abortSignal.aborted) {
      const error = new Error('请求已取消');
      error.code = 'aborted';
      throw error;
    }
    const { value, done } = await reader.read();
    if (done) break;
    buffer += decoder.decode(value, { stream: true });
    let idx;
    while ((idx = buffer.indexOf('\n\n')) !== -1) {
      const chunk = buffer.slice(0, idx);
      buffer = buffer.slice(idx + 2);
      const lines = chunk.split(/\r?\n/);
      for (const line of lines) {
        const trimmed = line.trim();
        if (!trimmed.startsWith('data:')) continue;
        const data = trimmed.slice(5).trim();
        if (!data) continue;
        if (data === '[DONE]') return;
        try {
          const json = JSON.parse(data);
          yield json;
        } catch (_) {
          continue;
        }
      }
    }
  }
}

module.exports = { streamChat };
