import { useState, useCallback, useRef, useEffect } from "react";
import DashboardLayout from "@/components/DashboardLayout";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { trpc } from "@/lib/trpc";
import {
  Upload as UploadIcon,
  FileText,
  Loader2,
  CheckCircle,
  AlertCircle,
  FolderOpen,
  File,
  X,
  ChevronRight,
} from "lucide-react";
import { toast } from "sonner";
import { useLocation } from "wouter";

interface UploadedFile {
  name: string;
  sourceFileId: number;
  status: "pending" | "processing" | "completed" | "error";
  progress?: string;
  invoicesDetected?: number;
}

export default function Upload() {
  const [, setLocation] = useLocation();
  const [isDragging, setIsDragging] = useState(false);
  const [uploadMode, setUploadMode] = useState<"file" | "folder">("file");
  const [uploadedFiles, setUploadedFiles] = useState<UploadedFile[]>([]);
  const [isUploading, setIsUploading] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const folderInputRef = useRef<HTMLInputElement>(null);

  const uploadMutation = trpc.invoices.upload.useMutation();

  // Poll pour tous les fichiers en cours
  const pendingIds = uploadedFiles
    .filter((f) => f.status === "processing" || f.status === "pending")
    .map((f) => f.sourceFileId);

  const { data: sourceFiles } = trpc.sourceFiles.getByIds.useQuery(
    { ids: pendingIds },
    {
      enabled: pendingIds.length > 0,
      refetchInterval: (query) => {
        const data = query.state.data;
        if (!data || data.length === 0) return false;
        const allDone = data.every(
          (f) => !f || f.processingStatus === "completed" || f.processingStatus === "error"
        );
        return allDone ? false : 2000;
      },
    }
  );

  // Mettre à jour les statuts depuis le polling
  useEffect(() => {
    if (!sourceFiles || sourceFiles.length === 0) return;
    sourceFiles.forEach((sf) => {
      if (!sf) return;
      setUploadedFiles((prev) =>
        prev.map((f) => {
          if (f.sourceFileId !== sf.id) return f;
          if (f.status === sf.processingStatus) return f;
          return {
            ...f,
            status: (sf.processingStatus ?? "pending") as UploadedFile["status"],
            progress: sf.processingProgress ?? undefined,
            invoicesDetected: sf.totalInvoicesDetected ?? undefined,
          };
        })
      );
    });
  }, [sourceFiles]);

  const uploadFile = async (file: File): Promise<number | null> => {
    return new Promise((resolve) => {
      const reader = new FileReader();
      reader.onload = async () => {
        const base64 = (reader.result as string).split(",")[1];
        try {
          const data = await uploadMutation.mutateAsync({
            fileName: file.name,
            fileData: base64!,
          });
          resolve(data.sourceFileId);
        } catch (err: any) {
          toast.error(`Erreur pour ${file.name} : ${err.message || "Erreur inconnue"}`);
          resolve(null);
        }
      };
      reader.readAsDataURL(file);
    });
  };

  const handleFiles = async (files: File[]) => {
    const pdfFiles = files.filter((f) => f.type === "application/pdf");
    if (pdfFiles.length === 0) {
      toast.error("Aucun fichier PDF trouvé");
      return;
    }
    if (pdfFiles.length < files.length) {
      toast.warning(`${files.length - pdfFiles.length} fichier(s) ignoré(s) (non PDF)`);
    }

    setIsUploading(true);
    toast.info(`Envoi de ${pdfFiles.length} fichier(s)...`);

    for (const file of pdfFiles) {
      const sourceFileId = await uploadFile(file);
      if (sourceFileId !== null) {
        setUploadedFiles((prev) => [
          ...prev,
          { name: file.name, sourceFileId, status: "processing" },
        ]);
      }
    }

    setIsUploading(false);
    toast.success(`${pdfFiles.length} fichier(s) envoyé(s) — traitement en cours`);
  };

  const handleDragOver = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(true);
  }, []);

  const handleDragLeave = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(false);
  }, []);

  const handleDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();
      setIsDragging(false);
      const files = Array.from(e.dataTransfer.files);
      handleFiles(files);
    },
    [uploadMode]
  );

  const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = Array.from(e.target.files || []);
    if (files.length > 0) handleFiles(files);
    // Reset input
    e.target.value = "";
  };

  const completedCount = uploadedFiles.filter((f) => f.status === "completed").length;
  const errorCount = uploadedFiles.filter((f) => f.status === "error").length;
  const processingCount = uploadedFiles.filter(
    (f) => f.status === "processing" || f.status === "pending"
  ).length;

  return (
    <DashboardLayout>
      <div className="max-w-3xl mx-auto space-y-6">
        {/* Header */}
        <div>
          <h1 className="text-3xl font-bold">Importer des factures</h1>
          <p className="text-gray-500 mt-1">
            Importez un fichier PDF unique ou tout un dossier de factures
          </p>
        </div>

        {/* Mode selector */}
        <div className="flex gap-3">
          <button
            type="button"
            onClick={() => setUploadMode("file")}
            className={`flex items-center gap-2 px-4 py-2 rounded-lg border-2 text-sm font-medium transition-all ${
              uploadMode === "file"
                ? "border-purple-500 bg-purple-50 dark:bg-purple-950/30 text-purple-700 dark:text-purple-300"
                : "border-muted hover:border-muted-foreground/40 text-muted-foreground"
            }`}
          >
            <File className="w-4 h-4" />
            Fichier unique
          </button>
          <button
            type="button"
            onClick={() => setUploadMode("folder")}
            className={`flex items-center gap-2 px-4 py-2 rounded-lg border-2 text-sm font-medium transition-all ${
              uploadMode === "folder"
                ? "border-blue-500 bg-blue-50 dark:bg-blue-950/30 text-blue-700 dark:text-blue-300"
                : "border-muted hover:border-muted-foreground/40 text-muted-foreground"
            }`}
          >
            <FolderOpen className="w-4 h-4" />
            Dossier entier
          </button>
        </div>

        {/* Drop zone */}
        <Card>
          <CardHeader>
            <CardTitle>
              {uploadMode === "file" ? "Upload de fichier PDF" : "Import d'un dossier"}
            </CardTitle>
            <CardDescription>
              {uploadMode === "file"
                ? "Glissez-déposez un fichier PDF ou cliquez pour sélectionner"
                : "Sélectionnez un dossier — tous les fichiers PDF qu'il contient seront importés"}
            </CardDescription>
          </CardHeader>
          <CardContent>
            <div
              onDragOver={handleDragOver}
              onDragLeave={handleDragLeave}
              onDrop={handleDrop}
              className={`
                border-2 border-dashed rounded-lg p-12 text-center transition-colors
                ${isDragging ? "border-blue-500 bg-blue-50" : "border-gray-300 hover:border-gray-400"}
                ${isUploading ? "opacity-50 pointer-events-none" : "cursor-pointer"}
              `}
              onClick={() => {
                if (uploadMode === "file") fileInputRef.current?.click();
                else folderInputRef.current?.click();
              }}
            >
              {/* Hidden inputs */}
              <input
                ref={fileInputRef}
                type="file"
                accept="application/pdf"
                onChange={handleFileInputChange}
                className="hidden"
                multiple
              />
              <input
                ref={folderInputRef}
                type="file"
                accept="application/pdf"
                onChange={handleFileInputChange}
                className="hidden"
                // @ts-ignore — webkitdirectory is not in TS types but works in all modern browsers
                webkitdirectory=""
                multiple
              />

              {uploadMode === "file" ? (
                <UploadIcon className="w-12 h-12 mx-auto mb-4 text-gray-400" />
              ) : (
                <FolderOpen className="w-12 h-12 mx-auto mb-4 text-blue-400" />
              )}

              <p className="text-lg font-medium mb-2">
                {isUploading
                  ? "Envoi en cours..."
                  : uploadMode === "file"
                  ? "Glissez-déposez un fichier PDF ici"
                  : "Cliquez pour sélectionner un dossier"}
              </p>
              <p className="text-sm text-gray-500">
                {uploadMode === "file"
                  ? "ou cliquez pour sélectionner un ou plusieurs fichiers PDF"
                  : "Tous les fichiers PDF du dossier sélectionné seront importés"}
              </p>
            </div>
          </CardContent>
        </Card>

        {/* Liste des fichiers uploadés */}
        {uploadedFiles.length > 0 && (
          <Card>
            <CardHeader className="border-b">
              <div className="flex items-center justify-between">
                <div>
                  <CardTitle>Fichiers importés</CardTitle>
                  <CardDescription>
                    {completedCount > 0 && (
                      <span className="text-green-600 font-medium">{completedCount} terminé(s) </span>
                    )}
                    {processingCount > 0 && (
                      <span className="text-blue-600 font-medium">{processingCount} en cours </span>
                    )}
                    {errorCount > 0 && (
                      <span className="text-red-600 font-medium">{errorCount} erreur(s)</span>
                    )}
                  </CardDescription>
                </div>
                <div className="flex gap-2">
                  {completedCount > 0 && (
                    <Button
                      size="sm"
                      onClick={() => setLocation("/invoices")}
                      className="bg-green-600 hover:bg-green-700 text-white"
                    >
                      <FileText className="w-4 h-4 mr-1" />
                      Voir les factures
                      <ChevronRight className="w-4 h-4 ml-1" />
                    </Button>
                  )}
                  <Button
                    size="sm"
                    variant="outline"
                    onClick={() => setUploadedFiles([])}
                  >
                    <X className="w-4 h-4 mr-1" />
                    Effacer
                  </Button>
                </div>
              </div>
            </CardHeader>
            <CardContent className="p-0">
              <div className="divide-y">
                {uploadedFiles.map((f, i) => (
                  <div key={i} className="flex items-center gap-3 px-4 py-3">
                    {f.status === "processing" || f.status === "pending" ? (
                      <Loader2 className="w-4 h-4 animate-spin text-blue-500 shrink-0" />
                    ) : f.status === "completed" ? (
                      <CheckCircle className="w-4 h-4 text-green-500 shrink-0" />
                    ) : (
                      <AlertCircle className="w-4 h-4 text-red-500 shrink-0" />
                    )}
                    <div className="flex-1 min-w-0">
                      <p className="text-sm font-medium truncate">{f.name}</p>
                      {f.status === "processing" && (
                        <p className="text-xs text-muted-foreground">{f.progress || "Traitement en cours..."}</p>
                      )}
                      {f.status === "completed" && f.invoicesDetected !== undefined && (
                        <p className="text-xs text-green-600">
                          {f.invoicesDetected} facture(s) détectée(s)
                        </p>
                      )}
                      {f.status === "error" && (
                        <p className="text-xs text-red-500">{f.progress || "Erreur de traitement"}</p>
                      )}
                    </div>
                    <Badge
                      variant={
                        f.status === "completed"
                          ? "default"
                          : f.status === "error"
                          ? "destructive"
                          : "secondary"
                      }
                      className={`text-xs shrink-0 ${f.status === "completed" ? "bg-green-500" : ""}`}
                    >
                      {f.status === "processing" || f.status === "pending"
                        ? "En cours"
                        : f.status === "completed"
                        ? "Terminé"
                        : "Erreur"}
                    </Badge>
                  </div>
                ))}
              </div>
            </CardContent>
          </Card>
        )}
      </div>
    </DashboardLayout>
  );
}
