import type { ModelStatusEntry, PredictResponse, PredictionsListResponse, SuggestedVideo, VideoResponse, } from "../types/api"; const BASE = import.meta.env.VITE_API_BASE_URL ?? ""; function parseApiError(body: unknown, fallback: string): string { if (!body || typeof body !== "object") return fallback; const detail = (body as { detail?: unknown }).detail; if (typeof detail === "string") return detail; if (Array.isArray(detail)) { return detail .map((item) => { if (item && typeof item === "object" && "msg" in item) { return String((item as { msg: unknown }).msg); } return String(item); }) .join("; "); } return fallback; } async function request(path: string, init?: RequestInit): Promise { const res = await fetch(`${BASE}${path}`, { ...init, headers: { "Content-Type": "application/json", ...init?.headers }, }); if (!res.ok) { const err = await res.json().catch(() => ({})); throw new Error(parseApiError(err, res.statusText)); } return res.json() as Promise; } export function predict(text: string, threshold: number) { return request("/predict", { method: "POST", body: JSON.stringify({ text, threshold }), }); } export function predictVideo(url: string, maxComments: number, threshold: number) { return request("/predict-video", { method: "POST", body: JSON.stringify({ url, max_comments: maxComments, threshold }), }); } export function getModels() { return request<{ available: string[]; active: string }>("/models"); } export async function getModelsStatus() { try { return await request<{ models: ModelStatusEntry[]; active: string }>("/models/status"); } catch (e) { if (e instanceof Error && e.message.toLowerCase().includes("not found")) { const legacy = await getModels(); return { active: legacy.active, models: legacy.available.map((name) => ({ name, available: true, reason: null, type: "unknown", })), }; } throw e; } } export function setModel(name: string) { return request<{ message: string; model: string }>("/models/select", { method: "POST", body: JSON.stringify({ model_name: name }), }); } export function getSuggestedVideos() { return request<{ videos: SuggestedVideo[]; max_comments: number }>("/videos/suggested"); } export function listPredictions(videoId?: string, limit = 20) { const params = new URLSearchParams(); if (videoId) params.set("video_id", videoId); params.set("limit", String(limit)); return request(`/predictions?${params.toString()}`); } export function getModelInfo() { return request<{ name: string; description: string; predictions_served: number; display_banner?: string | null; train_test_gap_pp?: number | null; recommended_threshold?: number | null; accuracy?: string; }>("/model-info"); }