/** * Service API pour communiquer avec le backend * Remplace le traitement local par des appels au serveur backend */ import type { ExtractionResult, AnalysisResult, ContextResult, ConseilResult } from '../types' const BACKEND_URL = import.meta.env.VITE_BACKEND_URL || 'http://localhost:3001' export interface BackendExtractionResult { success: boolean documentId: string fileName: string fileSize: number mimeType: string processing: { ocr: { text: string confidence: number wordCount: number } ner: { identities: any[] addresses: any[] cniNumbers: any[] dates: any[] documentType: string } globalConfidence: number } extractedData: { documentType: string identities: any[] addresses: any[] cniNumbers: any[] dates: any[] } timestamp: string } export interface BackendTestFiles { success: boolean files: Array<{ name: string size: number type: string lastModified: string }> } /** * Extrait le texte et les entitĂ©s d'un document via le backend */ export async function extractDocumentBackend( _documentId: string, file?: File, hooks?: { onOcrProgress?: (progress: number) => void; onLlmProgress?: (progress: number) => void } ): Promise { console.log('🚀 [BACKEND] DĂ©but de l\'extraction via le backend...') if (!file) { throw new Error('Aucun fichier fourni pour l\'extraction') } // Simuler la progression OCR if (hooks?.onOcrProgress) { hooks.onOcrProgress(0.1) console.log('⏳ [BACKEND] Envoi du fichier au backend...') } const formData = new FormData() formData.append('document', file) try { const response = await fetch(`${BACKEND_URL}/api/extract`, { method: 'POST', body: formData }) if (!response.ok) { throw new Error(`Erreur HTTP: ${response.status} ${response.statusText}`) } const result = await response.json() // VĂ©rifier si c'est le nouveau format JSON standard if (!result.document || !result.classification || !result.extraction) { throw new Error('Format de rĂ©ponse backend invalide') } console.log('✅ [BACKEND] Extraction terminĂ©e avec succĂšs') // Convertir le rĂ©sultat backend vers le format frontend const extractionResult: ExtractionResult = { documentId: result.document.id, text: result.extraction.text.raw, language: result.classification.language, documentType: result.classification.documentType, identities: result.extraction.entities.persons.map((person: any) => ({ id: person.id, type: 'person', firstName: person.firstName, lastName: person.lastName, confidence: person.confidence || 0.9 })), addresses: result.extraction.entities.addresses.map((address: any) => ({ id: address.id, street: address.street, city: address.city, postalCode: address.postalCode, country: address.country || 'France', confidence: address.confidence || 0.9 })), properties: [], contracts: [], signatures: result.extraction.entities.contractual?.signatures?.map((sig: any) => sig.signatory || 'Signature dĂ©tectĂ©e') || [], confidence: result.metadata.quality.globalConfidence, confidenceReasons: [ `OCR: ${Math.round(result.metadata.quality.textExtractionConfidence * 100)}% de confiance`, `Texte extrait: ${result.extraction.text.characterCount} caractĂšres`, `EntitĂ©s trouvĂ©es: ${result.extraction.entities.persons.length} personnes, ${result.extraction.entities.companies.length} sociĂ©tĂ©s, ${result.extraction.entities.addresses.length} adresses`, `Type dĂ©tectĂ©: ${result.classification.documentType}`, `Traitement backend: ${result.document.uploadTimestamp}` ] } // Extraction terminĂ©e console.log('🎉 [BACKEND] Extraction terminĂ©e avec succĂšs:', { documentType: extractionResult.documentType, identitiesCount: extractionResult.identities.length, addressesCount: extractionResult.addresses.length, confidence: extractionResult.confidence }) return extractionResult } catch (error) { console.error('❌ [BACKEND] Erreur lors de l\'extraction:', error) throw error } } /** * RĂ©cupĂšre la liste des fichiers de test depuis le backend */ export async function getTestFilesBackend(): Promise { try { const response = await fetch(`${BACKEND_URL}/api/test-files`) if (!response.ok) { throw new Error(`Erreur HTTP: ${response.status} ${response.statusText}`) } const result: BackendTestFiles = await response.json() console.log('📁 [BACKEND] Fichiers de test rĂ©cupĂ©rĂ©s:', result.files.length) return result } catch (error) { console.error('❌ [BACKEND] Erreur lors de la rĂ©cupĂ©ration des fichiers de test:', error) throw error } } // Cache pour le health check let backendHealthCache: { isHealthy: boolean; timestamp: number } | null = null const HEALTH_CHECK_CACHE_DURATION = 5000 // 5 secondes /** * VĂ©rifie la santĂ© du backend avec cache */ export async function checkBackendHealth(): Promise { const now = Date.now() // Utiliser le cache si disponible et rĂ©cent if (backendHealthCache && (now - backendHealthCache.timestamp) < HEALTH_CHECK_CACHE_DURATION) { return backendHealthCache.isHealthy } try { const response = await fetch(`${BACKEND_URL}/api/health`) const result = await response.json() const isHealthy = result.status === 'OK' console.log('đŸ„ [BACKEND] Health check:', result.status) // Mettre en cache le rĂ©sultat backendHealthCache = { isHealthy, timestamp: now } return isHealthy } catch (error) { console.error('❌ [BACKEND] Backend non accessible:', error) // Mettre en cache le rĂ©sultat nĂ©gatif backendHealthCache = { isHealthy: false, timestamp: now } return false } } // API mock pour compatibilitĂ© avec l'ancien systĂšme export const backendDocumentApi = { extract: extractDocumentBackend, analyze: async (documentId: string): Promise => { // Pour l'instant, retourner une analyse basique return { documentId, documentType: 'Document', isCNI: false, credibilityScore: 0.8, summary: 'Analyse en cours...', recommendations: [] } }, getContext: async (documentId: string): Promise => { return { documentId, lastUpdated: new Date(), georisquesData: {}, cadastreData: {} } }, getConseil: async (documentId: string): Promise => { return { documentId, analysis: 'Analyse en cours...', recommendations: [], risks: [], nextSteps: [], generatedAt: new Date() } } }