/**
 * 단순 non-streaming LLM 호출 — Ollama / LM Studio(OpenAI 호환) 듀얼 엔드포인트.
 *
 * postHocSelfCheck 의 호출 패턴을 재사용 가능한 헬퍼로 분리. 평가 하니스·Critic 등
 * AgentExecutor 밖에서 LLM 1회 호출이 필요한 곳이 사용한다 (확장 명령 등).
 * agent turn 내부에서는 agent.ts 의 callNonStreaming 을 쓸 것 (cloud 라우팅 포함).
 */

export interface SimpleChatOptions {
    baseUrl: string;
    model: string;
    temperature?: number;
    maxTokens?: number;
    timeoutMs?: number;
}

export async function simpleChatCompletion(
    system: string,
    user: string,
    options: SimpleChatOptions,
): Promise<string> {
    const isOllama = options.baseUrl.includes(':11434') || options.baseUrl.includes('ollama');
    const endpoint = isOllama ? `${options.baseUrl}/api/chat` : `${options.baseUrl}/v1/chat/completions`;
    const controller = new AbortController();
    const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 120000);
    try {
        const messages = [
            { role: 'system', content: system },
            { role: 'user', content: user },
        ];
        const body = isOllama
            ? { model: options.model, stream: false, messages, options: { temperature: options.temperature ?? 0.2, num_predict: options.maxTokens ?? 1200 } }
            : { model: options.model, stream: false, temperature: options.temperature ?? 0.2, max_tokens: options.maxTokens ?? 1200, messages };
        const res = await fetch(endpoint, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(body),
            signal: controller.signal,
        });
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        const data: any = await res.json();
        return String(
            data?.message?.content ??
            data?.choices?.[0]?.message?.content ??
            data?.choices?.[0]?.text ??
            data?.response ??
            '',
        );
    } finally {
        clearTimeout(timer);
    }
}
