import { useState } from "react"; interface EntityMapping { originalValue: string; anonymizedValue: string; entityType: string; startIndex: number; endIndex: number; } interface AnonymizationLogicProps { sourceText: string; fileContent: string; uploadedFile: File | null; setOutputText: (text: string) => void; setError: (error: string | null) => void; setEntityMappings: (mappings: EntityMapping[]) => void; } export const useAnonymization = ({ sourceText, fileContent, uploadedFile, setOutputText, setError, setEntityMappings, }: AnonymizationLogicProps) => { const [isProcessing, setIsProcessing] = useState(false); const anonymizeData = async () => { const textToProcess = sourceText || fileContent || ""; if (!textToProcess.trim()) { setError( "Veuillez saisir du texte à anonymiser ou télécharger un fichier" ); return; } setIsProcessing(true); setError(null); setOutputText(""); setEntityMappings([]); try { if ( uploadedFile && uploadedFile.type === "application/pdf" && !fileContent ) { const formData = new FormData(); formData.append("file", uploadedFile); const response = await fetch("/api/process-document", { method: "POST", body: formData, }); if (!response.ok) { throw new Error("Erreur lors du traitement du PDF"); } const data = await response.json(); if (data.error) { throw new Error(data.error); } if (data.anonymizedText) { setOutputText(data.anonymizedText); // TODO: Extraire les mappings depuis les résultats Presidio setIsProcessing(false); return; } } await new Promise((resolve) => setTimeout(resolve, 1500)); // Simulation des mappings pour le fallback const mappings: EntityMapping[] = []; let anonymized = textToProcess; // Noms const nameMatches = textToProcess.matchAll(/\b[A-Z][a-z]+ [A-Z][a-z]+\b/g); let nameCounter = 1; for (const match of nameMatches) { const replacement = `[Nom${nameCounter}]`; mappings.push({ originalValue: match[0], anonymizedValue: replacement, entityType: "PERSON", startIndex: match.index!, endIndex: match.index! + match[0].length }); anonymized = anonymized.replace(match[0], replacement); nameCounter++; } // Téléphones const phoneMatches = textToProcess.matchAll(/\b0[1-9](?:[\s.-]?\d{2}){4}\b/g); let phoneCounter = 1; for (const match of phoneMatches) { const replacement = `[Téléphone${phoneCounter}]`; mappings.push({ originalValue: match[0], anonymizedValue: replacement, entityType: "PHONE_NUMBER", startIndex: match.index!, endIndex: match.index! + match[0].length }); anonymized = anonymized.replace(match[0], replacement); phoneCounter++; } // Emails const emailMatches = textToProcess.matchAll(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g); let emailCounter = 1; for (const match of emailMatches) { const replacement = `[Email${emailCounter}]`; mappings.push({ originalValue: match[0], anonymizedValue: replacement, entityType: "EMAIL_ADDRESS", startIndex: match.index!, endIndex: match.index! + match[0].length }); anonymized = anonymized.replace(match[0], replacement); emailCounter++; } // Adresses const addressMatches = textToProcess.matchAll(/\b\d{1,3}\s+[a-zA-Z\s]+,\s*\d{5}\s+[a-zA-Z\s]+\b/g); let addressCounter = 1; for (const match of addressMatches) { const replacement = `[Adresse${addressCounter}]`; mappings.push({ originalValue: match[0], anonymizedValue: replacement, entityType: "LOCATION", startIndex: match.index!, endIndex: match.index! + match[0].length }); anonymized = anonymized.replace(match[0], replacement); addressCounter++; } // Numéros de sécurité sociale const ssnMatches = textToProcess.matchAll(/\b\d\s\d{2}\s\d{2}\s\d{2}\s\d{3}\s\d{3}\s\d{2}\b/g); let ssnCounter = 1; for (const match of ssnMatches) { const replacement = `[NuméroSS${ssnCounter}]`; mappings.push({ originalValue: match[0], anonymizedValue: replacement, entityType: "FR_NIR", startIndex: match.index!, endIndex: match.index! + match[0].length }); anonymized = anonymized.replace(match[0], replacement); ssnCounter++; } setOutputText(anonymized); setEntityMappings(mappings); } catch (error) { console.error("Erreur anonymisation:", error); setError( error instanceof Error ? error.message : "Erreur lors de l'anonymisation" ); } finally { setIsProcessing(false); } }; return { anonymizeData, isProcessing }; };