/**
 * Cloud LLM provider public API.
 *
 * 일반 호출 흐름:
 *   1. agent.ts 의 chat 진입부에서 `parseModelPrefix(modelId)` 호출
 *   2. null → local engine 경로 (옛 로직). 객체 → `streamCloudCompletion(context, hit, params)` 호출
 *   3. Response 의 body 는 *OpenAI 호환 SSE* (transformer 가 변환해둠) → 기존 SSE 파서 그대로 소비
 */

import * as vscode from 'vscode';
import { ProviderId, StreamParams, ChatMessage, parseModelPrefix, makeModelId, providerLabel } from './types';
import { streamOpenRouter, listOpenRouterModels } from './openrouter';
import { streamAnthropic, listAnthropicModels } from './anthropic';
import { streamGemini, listGeminiModels } from './gemini';
import { readProviderConfig, writeProviderConfig, readProviderStatus, ProviderConfig } from './providerConfig';

export type { ProviderId, ChatMessage, StreamParams, ProviderConfig };
export { parseModelPrefix, makeModelId, providerLabel, readProviderConfig, writeProviderConfig, readProviderStatus };

/**
 * Provider 별 stream adapter 로 dispatch. 항상 *OpenAI 호환 SSE* body 를 가진 Response 반환.
 * 에러 (인증 실패 / 4xx / 5xx) 시 .ok=false 인 Response — caller 가 .text() 로 메시지 추출.
 */
export async function streamCloudCompletion(
    context: vscode.ExtensionContext,
    hit: { provider: ProviderId; model: string },
    params: Omit<StreamParams, 'model'>,
): Promise<Response> {
    const fullParams: StreamParams = { ...params, model: hit.model };
    switch (hit.provider) {
        case 'openrouter': return streamOpenRouter(context, fullParams);
        case 'anthropic':  return streamAnthropic(context, fullParams);
        case 'gemini':     return streamGemini(context, fullParams);
    }
}

/**
 * 활성화된 provider 들의 model id 목록을 한 번에 — sidebar 드롭다운에 합칠 때 사용.
 * 각 모델 id 는 `provider:` prefix 가 붙어 반환되므로 parseModelPrefix 와 1:1 매칭.
 */
export async function listAllCloudModels(context: vscode.ExtensionContext): Promise<Array<{
    id: string;
    provider: ProviderId;
    label: string;
}>> {
    const out: Array<{ id: string; provider: ProviderId; label: string }> = [];
    const tasks: Array<Promise<void>> = [];

    const orCfg = await readProviderConfig(context, 'openrouter');
    if (orCfg.enabled && orCfg.apiKey) {
        tasks.push(listOpenRouterModels(context).then((ids) => {
            for (const id of ids) out.push({ id: makeModelId('openrouter', id), provider: 'openrouter', label: `OpenRouter · ${id}` });
        }));
    }
    const anCfg = await readProviderConfig(context, 'anthropic');
    if (anCfg.enabled && anCfg.apiKey) {
        for (const id of listAnthropicModels()) {
            out.push({ id: makeModelId('anthropic', id), provider: 'anthropic', label: `Anthropic · ${id}` });
        }
    }
    const geCfg = await readProviderConfig(context, 'gemini');
    if (geCfg.enabled && geCfg.apiKey) {
        tasks.push(listGeminiModels(context).then((ids) => {
            for (const id of ids) out.push({ id: makeModelId('gemini', id), provider: 'gemini', label: `Gemini · ${id}` });
        }));
    }
    await Promise.all(tasks);
    return out;
}
