"use client";

import type React from "react";

import { useState, useCallback } from "react";
import { useDropzone } from "react-dropzone";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Progress } from "@/components/ui/progress";
import {
  Upload,
  FileText,
  CheckCircle2,
  AlertCircle,
  Loader2,
} from "lucide-react";
import { parseOFX } from "@/lib/ofx-parser";
import {
  loadData,
  addAccount,
  updateAccount,
  addTransactions,
  generateId,
  autoCategorize,
} from "@/lib/store-db";
import type {
  OFXAccount,
  Account,
  Transaction,
  Folder,
  BankingData,
} from "@/lib/types";
import { cn } from "@/lib/utils";

interface OFXImportDialogProps {
  children: React.ReactNode;
  onImportComplete?: () => void;
}

type ImportStep = "upload" | "configure" | "importing" | "success" | "error";

interface ImportResult {
  fileName: string;
  accountName: string;
  transactionsImported: number;
  isNew: boolean;
  error?: string;
}

export function OFXImportDialog({
  children,
  onImportComplete,
}: OFXImportDialogProps) {
  const [open, setOpen] = useState(false);
  const [step, setStep] = useState<ImportStep>("upload");

  // Single file mode
  const [parsedData, setParsedData] = useState<OFXAccount | null>(null);
  const [accountName, setAccountName] = useState("");
  const [selectedFolder, setSelectedFolder] = useState<string>("folder-root");
  const [folders, setFolders] = useState<Folder[]>([]);
  const [existingAccountId, setExistingAccountId] = useState<string | null>(
    null,
  );

  // Multi-file mode
  const [importResults, setImportResults] = useState<ImportResult[]>([]);
  const [importProgress, setImportProgress] = useState(0);
  const [totalFiles, setTotalFiles] = useState(0);

  const [error, setError] = useState<string | null>(null);

  // Import a single OFX file directly (for multi-file mode)
  const importOFXDirect = async (
    parsed: OFXAccount,
    fileName: string,
    data: BankingData,
  ): Promise<ImportResult> => {
    try {
      // Check if account already exists
      const existing = data.accounts.find(
        (a) =>
          a.accountNumber === parsed.accountId && a.bankId === parsed.bankId,
      );

      let accountId: string;
      let accountName: string;
      let isNew = false;

      if (existing) {
        accountId = existing.id;
        accountName = existing.name;
        await updateAccount({
          ...existing,
          balance: parsed.balance,
          lastImport: new Date().toISOString(),
        });
      } else {
        isNew = true;
        accountName = `Compte ${parsed.accountId.slice(-4)}`;
        const newAccount = await addAccount({
          name: accountName,
          bankId: parsed.bankId,
          accountNumber: parsed.accountId,
          type: parsed.accountType as Account["type"],
          folderId: "folder-root",
          balance: parsed.balance,
          currency: parsed.currency,
          lastImport: new Date().toISOString(),
          externalUrl: null,
        });
        accountId = newAccount.id;
      }

      // Add transactions with auto-categorization
      const existingFitIds = new Set(
        data.transactions
          .filter((t) => t.accountId === accountId)
          .map((t) => t.fitId),
      );

      const newTransactions: Transaction[] = parsed.transactions
        .filter((t) => !existingFitIds.has(t.fitId))
        .map((t) => ({
          id: generateId(),
          accountId,
          date: t.date,
          amount: t.amount,
          description: t.name,
          type: t.amount >= 0 ? "CREDIT" : "DEBIT",
          categoryId: autoCategorize(
            t.name + " " + (t.memo || ""),
            data.categories,
          ),
          isReconciled: false,
          fitId: t.fitId,
          memo: t.memo,
          checkNum: t.checkNum,
        }));

      if (newTransactions.length > 0) {
        await addTransactions(newTransactions);
      }

      return {
        fileName,
        accountName,
        transactionsImported: newTransactions.length,
        isNew,
      };
    } catch (err) {
      return {
        fileName,
        accountName: "Erreur",
        transactionsImported: 0,
        isNew: false,
        error: err instanceof Error ? err.message : "Erreur inconnue",
      };
    }
  };

  const onDrop = useCallback(
    async (acceptedFiles: File[]) => {
      if (acceptedFiles.length === 0) return;

      // Multi-file mode: import directly
      if (acceptedFiles.length > 1) {
        setStep("importing");
        setTotalFiles(acceptedFiles.length);
        setImportProgress(0);
        setImportResults([]);

        const data = await loadData();
        const results: ImportResult[] = [];

        for (let i = 0; i < acceptedFiles.length; i++) {
          const file = acceptedFiles[i];
          const content = await file.text();
          const parsed = parseOFX(content);

          if (parsed) {
            // Reload data after each import to get updated accounts/transactions
            const freshData = i === 0 ? data : await loadData();
            const result = await importOFXDirect(parsed, file.name, freshData);
            results.push(result);
          } else {
            results.push({
              fileName: file.name,
              accountName: "Erreur",
              transactionsImported: 0,
              isNew: false,
              error: "Format OFX invalide",
            });
          }

          setImportProgress(((i + 1) / acceptedFiles.length) * 100);
          setImportResults([...results]);
        }

        setStep("success");
        onImportComplete?.();
        return;
      }

      // Single file mode: show configuration
      const file = acceptedFiles[0];
      const content = await file.text();
      const parsed = parseOFX(content);

      if (parsed) {
        setParsedData(parsed);
        setAccountName(`Compte ${parsed.accountId.slice(-4)}`);

        try {
          const data = await loadData();
          setFolders(data.folders);

          const existing = data.accounts.find(
            (a) =>
              a.accountNumber === parsed.accountId &&
              a.bankId === parsed.bankId,
          );
          if (existing) {
            setExistingAccountId(existing.id);
            setAccountName(existing.name);
            setSelectedFolder(existing.folderId || "folder-root");
          }

          setStep("configure");
        } catch (err) {
          console.error("Error loading data:", err);
          setError("Erreur lors du chargement des données");
          setStep("error");
        }
      } else {
        setError("Impossible de lire le fichier OFX. Vérifiez le format.");
        setStep("error");
      }
    },
    [onImportComplete],
  );

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    accept: {
      "application/x-ofx": [".ofx"],
      "application/vnd.intu.qfx": [".qfx"],
      "text/plain": [".ofx", ".qfx"],
    },
    // No maxFiles limit - accept multiple files
  });

  const handleImport = async () => {
    if (!parsedData) return;

    try {
      setStep("importing");
      const data = await loadData();

      let accountId: string;

      if (existingAccountId) {
        accountId = existingAccountId;
        const existingAccount = data.accounts.find(
          (a) => a.id === existingAccountId,
        );
        if (existingAccount) {
          await updateAccount({
            ...existingAccount,
            name: accountName,
            folderId: selectedFolder,
            balance: parsedData.balance,
            lastImport: new Date().toISOString(),
          });
        }
      } else {
        const newAccount = await addAccount({
          name: accountName,
          bankId: parsedData.bankId,
          accountNumber: parsedData.accountId,
          type: parsedData.accountType as Account["type"],
          folderId: selectedFolder,
          balance: parsedData.balance,
          currency: parsedData.currency,
          lastImport: new Date().toISOString(),
          externalUrl: null,
        });
        accountId = newAccount.id;
      }

      const existingFitIds = new Set(
        data.transactions
          .filter((t) => t.accountId === accountId)
          .map((t) => t.fitId),
      );

      const newTransactions: Transaction[] = parsedData.transactions
        .filter((t) => !existingFitIds.has(t.fitId))
        .map((t) => ({
          id: generateId(),
          accountId,
          date: t.date,
          amount: t.amount,
          description: t.name,
          type: t.amount >= 0 ? "CREDIT" : "DEBIT",
          categoryId: autoCategorize(
            t.name + " " + (t.memo || ""),
            data.categories,
          ),
          isReconciled: false,
          fitId: t.fitId,
          memo: t.memo,
          checkNum: t.checkNum,
        }));

      if (newTransactions.length > 0) {
        await addTransactions(newTransactions);
      }

      setImportResults([
        {
          fileName: "Import",
          accountName,
          transactionsImported: newTransactions.length,
          isNew: !existingAccountId,
        },
      ]);
      setStep("success");
      onImportComplete?.();
    } catch (err) {
      console.error("Error importing:", err);
      setError("Erreur lors de l'import");
      setStep("error");
    }
  };

  const handleClose = () => {
    setOpen(false);
    setTimeout(() => {
      setStep("upload");
      setParsedData(null);
      setAccountName("");
      setSelectedFolder("folder-root");
      setExistingAccountId(null);
      setError(null);
      setImportResults([]);
      setImportProgress(0);
      setTotalFiles(0);
    }, 200);
  };

  const totalTransactions = importResults.reduce(
    (sum, r) => sum + r.transactionsImported,
    0,
  );
  const successCount = importResults.filter((r) => !r.error).length;
  const errorCount = importResults.filter((r) => r.error).length;

  return (
    <Dialog
      open={open}
      onOpenChange={(o) => {
        if (!o) handleClose();
        else setOpen(true);
      }}
    >
      <DialogTrigger asChild>{children}</DialogTrigger>
      <DialogContent className="sm:max-w-md">
        <DialogHeader>
          <DialogTitle>
            {step === "upload" && "Importer des fichiers OFX"}
            {step === "configure" && "Configurer le compte"}
            {step === "importing" && "Import en cours..."}
            {step === "success" && "Import terminé"}
            {step === "error" && "Erreur d'import"}
          </DialogTitle>
          <DialogDescription>
            {step === "upload" &&
              "Glissez-déposez vos fichiers OFX ou cliquez pour sélectionner"}
            {step === "configure" &&
              "Vérifiez les informations du compte avant l'import"}
            {step === "importing" &&
              `Import de ${totalFiles} fichier${totalFiles > 1 ? "s" : ""}...`}
            {step === "success" &&
              (importResults.length > 1
                ? `${successCount} fichier${successCount > 1 ? "s" : ""} importé${successCount > 1 ? "s" : ""}, ${totalTransactions} transactions`
                : `${totalTransactions} nouvelles transactions importées`)}
            {step === "error" && error}
          </DialogDescription>
        </DialogHeader>

        {step === "upload" && (
          <div
            {...getRootProps()}
            className={cn(
              "border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors",
              isDragActive
                ? "border-primary bg-primary/5"
                : "border-muted-foreground/25 hover:border-primary/50",
            )}
          >
            <input {...getInputProps()} />
            <Upload className="w-10 h-10 mx-auto mb-4 text-muted-foreground" />
            <p className="text-sm text-muted-foreground">
              {isDragActive
                ? "Déposez les fichiers ici..."
                : "Fichiers .ofx ou .qfx acceptés"}
            </p>
            <p className="text-xs text-muted-foreground mt-2">
              Un fichier = configuration manuelle • Plusieurs fichiers = import
              direct
            </p>
          </div>
        )}

        {step === "configure" && parsedData && (
          <div className="space-y-4">
            <div className="flex items-center gap-3 p-3 bg-muted rounded-lg">
              <FileText className="w-8 h-8 text-primary" />
              <div>
                <p className="font-medium">
                  {parsedData.transactions.length} transactions
                </p>
                <p className="text-sm text-muted-foreground">
                  Solde:{" "}
                  {new Intl.NumberFormat("fr-FR", {
                    style: "currency",
                    currency: parsedData.currency,
                  }).format(parsedData.balance)}
                </p>
              </div>
            </div>

            <div className="space-y-2">
              <Label htmlFor="accountName">Nom du compte</Label>
              <Input
                id="accountName"
                value={accountName}
                onChange={(e) => setAccountName(e.target.value)}
                placeholder="Ex: Compte courant BNP"
              />
            </div>

            <div className="space-y-2">
              <Label>Dossier</Label>
              <Select value={selectedFolder} onValueChange={setSelectedFolder}>
                <SelectTrigger>
                  <SelectValue placeholder="Sélectionner un dossier" />
                </SelectTrigger>
                <SelectContent>
                  {folders.map((folder) => (
                    <SelectItem key={folder.id} value={folder.id}>
                      {folder.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            {existingAccountId && (
              <p className="text-sm text-amber-600 bg-amber-50 p-2 rounded">
                Ce compte existe déjà. Les nouvelles transactions seront
                ajoutées.
              </p>
            )}

            <div className="flex gap-2 justify-end">
              <Button variant="outline" onClick={() => setStep("upload")}>
                Retour
              </Button>
              <Button onClick={handleImport}>Importer</Button>
            </div>
          </div>
        )}

        {step === "importing" && (
          <div className="space-y-4 py-4">
            <div className="flex items-center justify-center gap-3">
              <Loader2 className="w-6 h-6 animate-spin text-primary" />
              <span>Import en cours...</span>
            </div>
            {totalFiles > 1 && (
              <Progress value={importProgress} className="w-full" />
            )}
            {importResults.length > 0 && (
              <div className="max-h-40 overflow-auto space-y-1 text-sm">
                {importResults.map((result, i) => (
                  <div key={i} className="flex items-center gap-2">
                    {result.error ? (
                      <AlertCircle className="w-4 h-4 text-red-500 flex-shrink-0" />
                    ) : (
                      <CheckCircle2 className="w-4 h-4 text-emerald-500 flex-shrink-0" />
                    )}
                    <span className="truncate">{result.fileName}</span>
                    {!result.error && (
                      <span className="text-muted-foreground ml-auto flex-shrink-0">
                        +{result.transactionsImported}
                      </span>
                    )}
                  </div>
                ))}
              </div>
            )}
          </div>
        )}

        {step === "success" && (
          <div className="py-4">
            <CheckCircle2 className="w-16 h-16 mx-auto mb-4 text-emerald-600" />

            {importResults.length > 1 && (
              <div className="max-h-48 overflow-auto space-y-1 text-sm mb-4 border rounded-lg p-2">
                {importResults.map((result, i) => (
                  <div key={i} className="flex items-center gap-2 py-1">
                    {result.error ? (
                      <AlertCircle className="w-4 h-4 text-red-500 flex-shrink-0" />
                    ) : (
                      <CheckCircle2 className="w-4 h-4 text-emerald-500 flex-shrink-0" />
                    )}
                    <div className="flex-1 min-w-0">
                      <p className="truncate font-medium">
                        {result.accountName}
                      </p>
                      <p className="text-xs text-muted-foreground truncate">
                        {result.fileName}
                      </p>
                    </div>
                    {result.error ? (
                      <span className="text-xs text-red-500 flex-shrink-0">
                        {result.error}
                      </span>
                    ) : (
                      <span className="text-xs text-muted-foreground flex-shrink-0">
                        {result.isNew ? "Nouveau" : "Mis à jour"} • +
                        {result.transactionsImported}
                      </span>
                    )}
                  </div>
                ))}
              </div>
            )}

            {errorCount > 0 && (
              <p className="text-sm text-red-600 mb-4 text-center">
                {errorCount} fichier{errorCount > 1 ? "s" : ""} en erreur
              </p>
            )}

            <div className="text-center">
              <Button onClick={handleClose}>Fermer</Button>
            </div>
          </div>
        )}

        {step === "error" && (
          <div className="text-center py-4">
            <AlertCircle className="w-16 h-16 mx-auto mb-4 text-red-600" />
            <Button onClick={() => setStep("upload")}>Réessayer</Button>
          </div>
        )}
      </DialogContent>
    </Dialog>
  );
}
