import { useState } from "react";
import { patterns } from "@/app/utils/highlightEntities";

interface EntityMapping {
  originalValue: string;
  anonymizedValue: string;
  entityType: string;
  startIndex: number;
  endIndex: number;
}

// L'API retourne des objets avec snake_case
interface PresidioAnalyzerResult {
  entity_type: string;
  start: number;
  end: number;
  score: number;
}

// La réponse de l'API utilise camelCase pour les clés principales
interface ProcessDocumentResponse {
  text?: string; // Texte original en cas de fallback
  anonymizedText?: string;
  analyzerResults?: PresidioAnalyzerResult[];
  error?: string;
}

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 {
      const formData = new FormData();
      if (uploadedFile) {
        formData.append("file", uploadedFile);
      } else {
        const textBlob = new Blob([textToProcess], { type: "text/plain" });
        const textFile = new File([textBlob], "input.txt", {
          type: "text/plain",
        });
        formData.append("file", textFile);
      }

      const response = await fetch("/api/process-document", {
        method: "POST",
        body: formData,
      });

      if (!response.ok) {
        let errorMessage = `Erreur HTTP: ${response.status}`;
        try {
          const errorData = await response.json();
          if (errorData.error) errorMessage = errorData.error;
        } catch {
          /* Ignore */
        }
        throw new Error(errorMessage);
      }

      const data: ProcessDocumentResponse = await response.json();

      if (data.error) {
        throw new Error(data.error);
      }

      // Utiliser camelCase pour les propriétés de la réponse principale
      if (data.anonymizedText && data.analyzerResults) {
        setOutputText(data.anonymizedText);

        const entityTypeMap = new Map<string, string>();
        patterns.forEach((p) => {
          const match = p.regex.toString().match(/<([A-Z_]+)>/);
          if (match && match[1]) {
            entityTypeMap.set(match[1], p.label);
          }
        });

        // 1. Compter les occurrences de chaque tag d'entité dans le texte anonymisé
        const tagCounts = new Map<string, number>();
        data.analyzerResults.forEach((result) => {
          const tag = `<${result.entity_type}>`;
          if (!tagCounts.has(result.entity_type)) {
            const count = (
              data.anonymizedText?.match(new RegExp(tag, "g")) || []
            ).length;
            tagCounts.set(result.entity_type, count);
          }
        });

        // 2. Créer un mapping basé sur l'ordre d'apparition dans le texte anonymisé
        const uniqueMappings: EntityMapping[] = [];
        
        // Vérifier que les données nécessaires sont disponibles
        if (!data.analyzerResults || !data.anonymizedText) {
          setEntityMappings([]);
          return;
        }
        
        const entityCounters = new Map<string, number>();
        
        // Parcourir le texte anonymisé pour trouver les tags dans l'ordre
        const anonymizedText = data.anonymizedText;
        const allMatches: Array<{
          match: RegExpMatchArray;
          entityType: string;
          position: number;
        }> = [];
        
        // Trouver tous les tags dans le texte anonymisé
        patterns.forEach(pattern => {
          const entityTypeKey = pattern.regex.toString().match(/<([A-Z_]+)>/)?.[1];
          if (entityTypeKey) {
            const regex = new RegExp(pattern.regex.source, 'g');
            let match;
            while ((match = regex.exec(anonymizedText)) !== null) {
              allMatches.push({
                match,
                entityType: entityTypeKey,
                position: match.index
              });
            }
          }
        });
        
        // Trier par position dans le texte anonymisé
        allMatches.sort((a, b) => a.position - b.position);
        
        // Créer les mappings dans l'ordre d'apparition
        const seen = new Set<string>();
        allMatches.forEach(({ entityType }) => {
          const frenchLabel = entityTypeMap.get(entityType) || entityType;
          const currentCount = (entityCounters.get(entityType) || 0) + 1;
          entityCounters.set(entityType, currentCount);
          
          // Trouver l'entité correspondante dans les résultats d'analyse
          const correspondingResult = data.analyzerResults
            ?.filter(result => result.entity_type === entityType)
            .find(result => {
              const originalValue = textToProcess.substring(result.start, result.end);
              const uniqueKey = `${frenchLabel}|${originalValue}|${currentCount}`;
              return !seen.has(uniqueKey);
            });
            
          if (correspondingResult) {
            const originalValue = textToProcess.substring(
              correspondingResult.start,
              correspondingResult.end
            );
            const uniqueKey = `${frenchLabel}|${originalValue}|${currentCount}`;
            
            if (!seen.has(uniqueKey)) {
              uniqueMappings.push({
                entityType: frenchLabel,
                originalValue: originalValue,
                anonymizedValue: `${frenchLabel} [${currentCount}]`,
                startIndex: correspondingResult.start,
                endIndex: correspondingResult.end,
              });
              seen.add(uniqueKey);
            }
          }
        });

        setEntityMappings(uniqueMappings);
      } else if (data.text) {
        setOutputText(data.text);
        setError("Presidio temporairement indisponible. Texte non anonymisé.");
      }
    } catch (error) {
      setError(
        error instanceof Error
          ? error.message
          : "Erreur lors de l'anonymisation avec Presidio"
      );
    } finally {
      setIsProcessing(false);
    }
  };

  return { anonymizeData, isProcessing };
};
