const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:5123'; export interface FileTreeNode { name: string; path: string; type: 'file' | 'folder'; children?: FileTreeNode[]; } export interface RepositoryInfo { name: string; } export interface FileContentResponse { path: string; content: string; } export interface CheckFileRequest { fileContent: string; fileName: string; checkType: 'language' | 'content'; } export interface CheckFileResponse { result: string; } export type FlashcardDifficulty = 'Easy' | 'Hard'; export interface GenerateFlashcardsRequest { filePaths: string[]; amount: number; difficulty: FlashcardDifficulty; } export interface FlashcardCard { id: number; libraryId: number; front: string; back: string; position: number; correctCount: number; incorrectCount: number; createdAt: string; lastReviewedAt?: string | null; } export interface FlashcardLibrarySummary { id: number; filePath: string; fileName: string; subject: string; difficulty: string; cardCount: number; createdAt: string; updatedAt: string; } export interface FlashcardLibraryDetails extends FlashcardLibrarySummary { cards: FlashcardCard[]; } export interface GenerateFlashcardsResponse { libraries: FlashcardLibraryDetails[]; } export interface FlashcardReviewSessionRequest { libraryIds: number[]; } export interface FlashcardReviewSessionResponse { cards: FlashcardCard[]; } export interface FlashcardReviewAnswerRequest { cardId: number; correct: boolean; } export type FlashcardRagStatus = 'Grey' | 'Red' | 'Amber' | 'Green'; export interface FlashcardRagLibrary { libraryId: number; filePath: string; fileName: string; subject: string; subSubject: string; cardCount: number; correctCount: number; incorrectCount: number; totalAnswers: number; performanceRate: number; lastReviewedAt?: string | null; ragStatus: FlashcardRagStatus; } export interface FlashcardRagSummary { greenCount: number; amberCount: number; redCount: number; greyCount: number; activeCount: number; greenPercentage: number; attentionPercentage: number; } export interface FlashcardRagSubSubjectGroup { subSubject: string; summary: FlashcardRagSummary; libraries: FlashcardRagLibrary[]; } export interface FlashcardRagSubjectGroup { subject: string; summary: FlashcardRagSummary; subSubjects: FlashcardRagSubSubjectGroup[]; } export interface FlashcardRagDashboardResponse { generatedAt: string; subjects: FlashcardRagSubjectGroup[]; } async function throwIfNotOk(response: Response, fallback: string) { if (response.ok) { return; } let apiMessage = ''; try { const body = await response.json(); if (typeof body?.error === 'string' && body.error.length > 0) { apiMessage = body.error; } } catch { // Ignore parse failures and throw fallback below. } throw new Error(apiMessage || fallback); } export const MindforgeApiService = { async checkFile(data: CheckFileRequest): Promise { const response = await fetch(`${BASE_URL}/api/v1/file/check`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); await throwIfNotOk(response, `Erro ao validar arquivo: ${response.statusText}`); return response.json(); }, async generateFlashcards(data: GenerateFlashcardsRequest): Promise { const response = await fetch(`${BASE_URL}/api/v1/flashcard/generate`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); await throwIfNotOk(response, `Erro ao gerar flashcards: ${response.statusText}`); return response.json(); }, async getFlashcardLibraries(): Promise { const response = await fetch(`${BASE_URL}/api/v1/flashcard/libraries`); await throwIfNotOk(response, `Erro ao buscar bibliotecas de flashcards: ${response.statusText}`); return response.json(); }, async getFlashcardLibrary(id: number): Promise { const response = await fetch(`${BASE_URL}/api/v1/flashcard/libraries/${id}`); await throwIfNotOk(response, `Erro ao buscar biblioteca ${id}: ${response.statusText}`); return response.json(); }, async createFlashcardReviewSession(data: FlashcardReviewSessionRequest): Promise { const response = await fetch(`${BASE_URL}/api/v1/flashcard/review-session`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); await throwIfNotOk(response, `Erro ao iniciar revisao: ${response.statusText}`); return response.json(); }, async recordFlashcardReviewAnswer(data: FlashcardReviewAnswerRequest): Promise { const response = await fetch(`${BASE_URL}/api/v1/flashcard/review-answer`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); await throwIfNotOk(response, `Erro ao registrar resposta da revisao: ${response.statusText}`); }, async getFlashcardRagStatus(): Promise { const response = await fetch(`${BASE_URL}/api/v1/flashcard/rag-status`); await throwIfNotOk(response, `Erro ao buscar status RAG de revisao: ${response.statusText}`); return response.json(); }, async getRepositoryInfo(): Promise { const response = await fetch(`${BASE_URL}/api/v1/repository/info`); await throwIfNotOk(response, `Erro ao buscar info do repositorio: ${response.statusText}`); return response.json(); }, async getRepositoryTree(): Promise { const response = await fetch(`${BASE_URL}/api/v1/repository/tree`); await throwIfNotOk(response, `Erro ao buscar arvore do repositorio: ${response.statusText}`); return response.json(); }, async getFileContent(path: string): Promise { const response = await fetch(`${BASE_URL}/api/v1/repository/file?path=${encodeURIComponent(path)}`); await throwIfNotOk(response, `Erro ao buscar arquivo ${path}: ${response.statusText}`); return response.json(); }, };