import { resolveEngine, buildApiUrl, logError, logInfo } from '../utils';

/**
 * Discover the model list exposed by the local AI engine at `baseUrl`.
 *
 * [가이드라인] 보유한 모델이 *전부* 나와야 한다. LM Studio 의 REST `/v1/models`
 * 는 JIT(Just-In-Time) 로딩 설정에서 *현재 로드된* 모델만 반환하므로, 그것만
 * 쓰면 dropdown 에 1개만 뜨는 회귀가 생긴다. 따라서 LM Studio 에서는 SDK
 * `system.listDownloadedModels('llm')`(다운로드된 모든 LLM)을 **우선** 시도하고,
 * 실패/0개일 때만 REST 로 폴백한다. 사이드바 `ModelDiscovery` 와 동일한 정책 —
 * 두 경로가 갈라지면 또 회귀하므로 반드시 같은 우선순위를 유지할 것.
 *
 * `opts.lmStudioDownloaded` 는 LM Studio SDK 의 다운로드 모델 목록 콜백
 * (보통 `lmStudioClient.listDownloadedCached`). 제공되지 않으면 REST 만 사용.
 *
 * Returns an empty array on any failure (offline engine, parse error, etc.).
 * Callers should treat the result as a hint, not a hard list.
 */
export async function discoverModels(
    baseUrl: string,
    opts: { timeoutMs?: number; lmStudioDownloaded?: () => Promise<string[]> } = {},
): Promise<string[]> {
    const { timeoutMs = 5000, lmStudioDownloaded } = opts;
    const url = (baseUrl || '').trim();
    if (!url) return [];
    const engine = resolveEngine(url);

    // 1) LM Studio + SDK 우선 — 다운로드된 모든 모델(로드 여부 무관).
    if (engine === 'lmstudio' && lmStudioDownloaded) {
        try {
            const sdk = await lmStudioDownloaded();
            const filtered = sdk.filter((m): m is string => typeof m === 'string' && m.length > 0);
            if (filtered.length > 0) {
                logInfo('discoverModels: SDK 다운로드 모델 사용', { count: filtered.length });
                return filtered;
            }
            logInfo('discoverModels: SDK 0개 — REST 폴백', { engine });
        } catch (e: any) {
            logInfo('discoverModels: SDK 실패 — REST 폴백', { error: e?.message ?? String(e) });
        }
    }

    // 2) REST 폴백 (`/v1/models` lmstudio · `/api/tags` ollama)
    const modelsUrl = buildApiUrl(url, engine, 'models');
    try {
        const res = await fetch(modelsUrl, { signal: AbortSignal.timeout(timeoutMs) });
        if (!res.ok) {
            logInfo('discoverModels: non-OK status', { engine, modelsUrl, status: res.status });
            return [];
        }
        const text = await res.text();
        if (!text) return [];
        const data = JSON.parse(text) as any;
        const list: string[] = engine === 'lmstudio'
            ? (data.data || []).map((m: any) => m.id)
            : (data.models || []).map((m: any) => m.name);
        return list.filter((m): m is string => typeof m === 'string' && m.length > 0);
    } catch (e: any) {
        logError('discoverModels failed.', { engine, modelsUrl, error: e?.message ?? String(e) });
        return [];
    }
}
