"use client";

import { useState } from "react";
import {
  DndContext,
  DragEndEvent,
  DragOverlay,
  DragStartEvent,
  PointerSensor,
  useSensor,
  useSensors,
  closestCenter,
  useDroppable,
} from "@dnd-kit/core";
import { PageLayout, LoadingState, PageHeader } from "@/components/layout";
import {
  AccountCard,
  AccountEditDialog,
  AccountMergeSelectDialog,
  AccountBulkActions,
} from "@/components/accounts";
import { FolderEditDialog } from "@/components/folders";
import { useBankingMetadata, useAccountsWithStats } from "@/lib/hooks";
import { useQueryClient } from "@tanstack/react-query";
import {
  updateAccount,
  deleteAccount,
  addFolder,
  updateFolder,
  deleteFolder,
} from "@/lib/store-db";
import { invalidateAllAccountQueries } from "@/lib/cache-utils";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import {
  Building2,
  Folder,
  Plus,
  List,
  LayoutGrid,
  MoreVertical,
  Pencil,
  Trash2,
} from "lucide-react";
import type { Account, Folder as FolderType } from "@/lib/types";
import { cn } from "@/lib/utils";
import { getAccountBalance } from "@/lib/account-utils";
import { useIsMobile } from "@/hooks/use-mobile";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

// Composant wrapper pour les zones de drop des dossiers
function FolderDropZone({
  folderId,
  children,
}: {
  folderId: string;
  children: React.ReactNode;
}) {
  const { setNodeRef, isOver } = useDroppable({
    id: `folder-${folderId}`,
  });

  return (
    <div
      ref={setNodeRef}
      className={cn(
        isOver && "ring-2 ring-primary ring-offset-2 rounded-lg p-2",
      )}
    >
      {children}
    </div>
  );
}

export default function AccountsPage() {
  const queryClient = useQueryClient();
  const isMobile = useIsMobile();
  const { data: metadata, isLoading: isLoadingMetadata } = useBankingMetadata();
  const { data: accountsWithStats, isLoading: isLoadingAccounts } =
    useAccountsWithStats();

  // refresh function is not used directly, invalidations are done inline

  const refreshSilent = async () => {
    invalidateAllAccountQueries(queryClient);
  };
  const [editingAccount, setEditingAccount] = useState<Account | null>(null);
  const [isDialogOpen, setIsDialogOpen] = useState(false);
  const [selectedAccounts, setSelectedAccounts] = useState<Set<string>>(
    new Set(),
  );
  const [formData, setFormData] = useState({
    name: "",
    type: "CHECKING" as Account["type"],
    folderId: "folder-root",
    externalUrl: "",
    initialBalance: 0,
    totalBalance: 0,
  });

  // Folder management state
  const [isFolderDialogOpen, setIsFolderDialogOpen] = useState(false);
  const [editingFolder, setEditingFolder] = useState<FolderType | null>(null);
  const [folderFormData, setFolderFormData] = useState({
    name: "",
    parentId: "folder-root" as string | null,
    color: "#6366f1",
  });
  const [activeId, setActiveId] = useState<string | null>(null);
  const [isCompactView, setIsCompactView] = useState(false);
  const [isMergeDialogOpen, setIsMergeDialogOpen] = useState(false);

  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 8,
      },
    }),
  );

  if (
    isLoadingMetadata ||
    !metadata ||
    isLoadingAccounts ||
    !accountsWithStats
  ) {
    return <LoadingState />;
  }

  // Convert accountsWithStats to regular accounts for compatibility
  const accounts = accountsWithStats.map(
    ({
      transactionCount: _transactionCount,
      calculatedBalance: _calculatedBalance,
      ...account
    }) => account,
  );

  const formatCurrency = (amount: number) => {
    return new Intl.NumberFormat("fr-FR", {
      style: "currency",
      currency: "EUR",
    }).format(amount);
  };

  const handleEdit = (account: Account) => {
    setEditingAccount(account);
    const totalBalance = getAccountBalance(account);
    setFormData({
      name: account.name,
      type: account.type,
      folderId: account.folderId || "folder-root",
      externalUrl: account.externalUrl || "",
      initialBalance: account.initialBalance || 0,
      totalBalance: totalBalance,
    });
    setIsDialogOpen(true);
  };

  const handleSave = async () => {
    if (!editingAccount) return;

    try {
      // Calculer le balance à partir du solde total et du solde initial
      // balance = totalBalance - initialBalance
      const balance = formData.totalBalance - formData.initialBalance;

      // Convertir "folder-root" en null
      const folderId =
        formData.folderId === "folder-root" ? null : formData.folderId;

      const updatedAccount = {
        ...editingAccount,
        name: formData.name,
        type: formData.type,
        folderId: folderId,
        externalUrl: formData.externalUrl || null,
        initialBalance: formData.initialBalance,
        balance: balance,
      };
      await updateAccount(updatedAccount);
      invalidateAllAccountQueries(queryClient);
      setIsDialogOpen(false);
      setEditingAccount(null);
    } catch (error) {
      console.error("Error updating account:", error);
      alert("Erreur lors de la mise à jour du compte");
    }
  };

  const handleDelete = async (accountId: string) => {
    if (!confirm("Supprimer ce compte et toutes ses transactions ?")) return;

    try {
      await deleteAccount(accountId);
      invalidateAllAccountQueries(queryClient);
    } catch (error) {
      console.error("Error deleting account:", error);
      alert("Erreur lors de la suppression du compte");
    }
  };

  const handleBulkDelete = async () => {
    const count = selectedAccounts.size;
    if (
      !confirm(
        `Supprimer ${count} compte${count > 1 ? "s" : ""} et toutes leurs transactions ?`,
      )
    )
      return;

    try {
      const ids = Array.from(selectedAccounts);
      const response = await fetch(
        `/api/banking/accounts?ids=${ids.join(",")}`,
        {
          method: "DELETE",
        },
      );
      if (!response.ok) {
        throw new Error("Failed to delete accounts");
      }
      setSelectedAccounts(new Set());
      invalidateAllAccountQueries(queryClient);
    } catch (error) {
      console.error("Error deleting accounts:", error);
      alert("Erreur lors de la suppression des comptes");
    }
  };

  const toggleSelectAccount = (accountId: string, selected: boolean) => {
    const newSelected = new Set(selectedAccounts);
    if (selected) {
      newSelected.add(accountId);
    } else {
      newSelected.delete(accountId);
    }
    setSelectedAccounts(newSelected);
  };

  // Folder management handlers
  const handleNewFolder = () => {
    setEditingFolder(null);
    setFolderFormData({ name: "", parentId: "folder-root", color: "#6366f1" });
    setIsFolderDialogOpen(true);
  };

  const handleEditFolder = (folder: FolderType) => {
    setEditingFolder(folder);
    setFolderFormData({
      name: folder.name,
      parentId: folder.parentId || "folder-root",
      color: folder.color,
    });
    setIsFolderDialogOpen(true);
  };

  const handleSaveFolder = async () => {
    const parentId =
      folderFormData.parentId === "folder-root"
        ? null
        : folderFormData.parentId;

    try {
      if (editingFolder) {
        await updateFolder({
          ...editingFolder,
          name: folderFormData.name,
          parentId,
          color: folderFormData.color,
        });
      } else {
        await addFolder({
          name: folderFormData.name,
          parentId,
          color: folderFormData.color,
          icon: "folder",
        });
      }
      invalidateAllAccountQueries(queryClient);
      setIsFolderDialogOpen(false);
    } catch (error) {
      console.error("Error saving folder:", error);
      alert("Erreur lors de la sauvegarde du dossier");
    }
  };

  const handleDeleteFolder = async (folderId: string) => {
    if (
      !confirm(
        "Supprimer ce dossier ? Les comptes seront déplacés à la racine.",
      )
    )
      return;

    try {
      await deleteFolder(folderId);
      invalidateAllAccountQueries(queryClient);
    } catch (error) {
      console.error("Error deleting folder:", error);
      alert("Erreur lors de la suppression du dossier");
    }
  };

  const handleMergeAccounts = async (
    sourceAccountId: string,
    targetAccountId: string,
  ) => {
    try {
      const response = await fetch("/api/banking/accounts/merge", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          sourceAccountId,
          targetAccountId,
        }),
      });

      if (!response.ok) {
        const error = await response.json();
        throw new Error(error.error || "Failed to merge accounts");
      }

      const result = await response.json();
      invalidateAllAccountQueries(queryClient);

      // Réinitialiser la sélection
      setSelectedAccounts(new Set());

      // Afficher un message de succès
      alert(
        `Fusion réussie ! ${result.transactionCount} transactions déplacées vers le compte de destination.`,
      );
    } catch (error) {
      console.error("Error merging accounts:", error);
      throw error;
    }
  };

  // Drag and drop handlers
  const handleDragStart = (event: DragStartEvent) => {
    setActiveId(event.active.id as string);
  };

  const handleDragEnd = async (event: DragEndEvent) => {
    const { active, over } = event;
    setActiveId(null);

    if (!over || active.id === over.id || !accountsWithStats) return;

    const activeId = active.id as string;
    const overId = over.id as string;

    // Déplacer un compte vers un dossier
    if (activeId.startsWith("account-")) {
      const accountId = activeId.replace("account-", "");
      let targetFolderId: string | null = null;

      if (overId.startsWith("folder-")) {
        const folderId = overId.replace("folder-", "");
        targetFolderId = folderId === "root" ? null : folderId;
      } else if (overId.startsWith("account-")) {
        // Déplacer vers le dossier du compte cible
        const targetAccountId = overId.replace("account-", "");
        const targetAccount = accountsWithStats.find(
          (a) => a.id === targetAccountId,
        );
        if (targetAccount) {
          targetFolderId = targetAccount.folderId;
        }
      }

      if (targetFolderId !== undefined) {
        const account = accountsWithStats.find((a) => a.id === accountId);
        if (!account) return;

        // Optimistic update : mettre à jour immédiatement l'interface
        const updatedAccount = {
          ...account,
          folderId: targetFolderId,
        };
        // Update cache directly
        queryClient.setQueryData(
          ["accounts-with-stats"],
          (
            old:
              | Array<
                  Account & {
                    transactionCount: number;
                    calculatedBalance: number;
                  }
                >
              | undefined,
          ) => {
            if (!old) return old;
            return old.map((a) => (a.id === accountId ? updatedAccount : a));
          },
        );

        // Faire la requête en arrière-plan
        try {
          await updateAccount(updatedAccount);
          // Refresh silencieux pour synchroniser avec le serveur sans loader
          await refreshSilent();
        } catch (error) {
          console.error("Error moving account:", error);
          // Rollback en cas d'erreur - refresh data
          invalidateAllAccountQueries(queryClient);
          alert("Erreur lors du déplacement du compte");
        }
      }
    }
  };

  const getTransactionCount = (accountId: string) => {
    const account = accountsWithStats.find((a) => a.id === accountId);
    return account?.transactionCount || 0;
  };

  const totalBalance = accounts.reduce(
    (sum, a) => sum + getAccountBalance(a),
    0,
  );

  // Grouper les comptes par folder
  const accountsByFolder = accounts.reduce(
    (acc, account) => {
      const folderId = account.folderId || "no-folder";
      if (!acc[folderId]) {
        acc[folderId] = [];
      }
      acc[folderId].push(account);
      return acc;
    },
    {} as Record<string, Account[]>,
  );

  // Obtenir les folders racine (sans parent) et les trier par nom
  const rootFolders = metadata.folders
    .filter((f: FolderType) => !f.parentId)
    .sort((a: FolderType, b: FolderType) => a.name.localeCompare(b.name));

  return (
    <PageLayout>
      <PageHeader
        title="Comptes"
        description={
          isMobile
            ? undefined
            : "Gérez vos comptes bancaires et leur organisation"
        }
        actions={
          <div className="flex items-center gap-2">
            <Button
              variant="outline"
              size={isMobile ? "icon" : "default"}
              onClick={() => setIsCompactView(!isCompactView)}
              title={isCompactView ? "Vue détaillée" : "Vue compacte"}
            >
              {isCompactView ? (
                <LayoutGrid className="w-4 h-4" />
              ) : (
                <List className="w-4 h-4" />
              )}
              {!isMobile && (
                <span className="ml-2">
                  {isCompactView ? "Détaillée" : "Compacte"}
                </span>
              )}
            </Button>
            <Button
              onClick={handleNewFolder}
              size={isMobile ? "icon" : "default"}
            >
              <Plus className="w-4 h-4" />
              {!isMobile && <span className="ml-2">Nouveau dossier</span>}
            </Button>
          </div>
        }
        rightContent={
          <div className={cn("text-right", isMobile && "text-left")}>
            {!isMobile && (
              <p className="text-sm text-muted-foreground">Solde total</p>
            )}
            <p
              className={cn(
                isMobile ? "text-xl" : "text-2xl",
                "font-bold",
                totalBalance >= 0 ? "text-emerald-600" : "text-red-600",
              )}
            >
              {isMobile && (
                <span className="text-xs text-muted-foreground mr-2">
                  Total:
                </span>
              )}
              {formatCurrency(totalBalance)}
            </p>
          </div>
        }
      />

      {accounts.length === 0 ? (
        <Card>
          <CardContent className="flex flex-col items-center justify-center py-12">
            <Building2 className="w-16 h-16 text-muted-foreground mb-4" />
            <h3 className="text-lg font-semibold mb-2">Aucun compte</h3>
            <p className="text-muted-foreground text-center mb-4">
              Importez un fichier OFX depuis le tableau de bord pour ajouter
              votre premier compte.
            </p>
          </CardContent>
        </Card>
      ) : (
        <>
          <AccountBulkActions
            selectedCount={selectedAccounts.size}
            selectedAccountIds={Array.from(selectedAccounts)}
            onDelete={handleBulkDelete}
            onMerge={
              selectedAccounts.size === 2
                ? () => setIsMergeDialogOpen(true)
                : undefined
            }
          />
          <DndContext
            sensors={sensors}
            collisionDetection={closestCenter}
            onDragStart={handleDragStart}
            onDragEnd={handleDragEnd}
          >
            <div className="space-y-6">
              {/* Afficher d'abord les comptes sans dossier */}
              {accountsByFolder["no-folder"] &&
                accountsByFolder["no-folder"].length > 0 && (
                  <FolderDropZone folderId="root">
                    <div className="flex items-center gap-2 mb-3 sm:mb-4">
                      <Folder className="w-5 h-5 text-muted-foreground shrink-0" />
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center gap-2 flex-wrap">
                          <h2 className="text-base sm:text-lg font-semibold">
                            Sans dossier
                          </h2>
                          <span className="text-xs sm:text-sm text-muted-foreground shrink-0">
                            ({accountsByFolder["no-folder"].length})
                          </span>
                          <span
                            className={cn(
                              "text-xs sm:text-sm font-semibold tabular-nums shrink-0",
                              accountsByFolder["no-folder"].reduce(
                                (sum, a) => sum + getAccountBalance(a),
                                0,
                              ) >= 0
                                ? "text-emerald-600"
                                : "text-red-600",
                            )}
                          >
                            {formatCurrency(
                              accountsByFolder["no-folder"].reduce(
                                (sum, a) => sum + getAccountBalance(a),
                                0,
                              ),
                            )}
                          </span>
                        </div>
                      </div>
                    </div>
                    <div className="grid gap-2 sm:gap-3 md:gap-4 grid-cols-2 sm:grid-cols-2 lg:grid-cols-3">
                      {accountsByFolder["no-folder"].map((account) => {
                        const folder = metadata.folders.find(
                          (f: FolderType) => f.id === account.folderId,
                        );

                        const accountWithStats = accountsWithStats.find(
                          (a) => a.id === account.id,
                        );
                        return (
                          <AccountCard
                            key={account.id}
                            account={account}
                            folder={folder}
                            transactionCount={getTransactionCount(account.id)}
                            calculatedBalance={
                              accountWithStats?.calculatedBalance
                            }
                            onEdit={handleEdit}
                            onDelete={handleDelete}
                            formatCurrency={formatCurrency}
                            isSelected={selectedAccounts.has(account.id)}
                            onSelect={toggleSelectAccount}
                            draggableId={`account-${account.id}`}
                            compact={isCompactView}
                          />
                        );
                      })}
                    </div>
                  </FolderDropZone>
                )}

              {/* Afficher les comptes groupés par folder */}
              {rootFolders.map((folder: FolderType) => {
                const folderAccounts = accountsByFolder[folder.id] || [];
                const folderBalance = folderAccounts.reduce(
                  (sum, a) => sum + getAccountBalance(a),
                  0,
                );

                return (
                  <FolderDropZone key={folder.id} folderId={folder.id}>
                    <div className="flex items-center gap-2 mb-3 sm:mb-4">
                      <div
                        className="w-5 h-5 rounded flex items-center justify-center shrink-0"
                        style={{ backgroundColor: `${folder.color}20` }}
                      >
                        <Folder
                          className="w-4 h-4"
                          style={{ color: folder.color }}
                        />
                      </div>
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center gap-2 flex-wrap">
                          <h2 className="text-base sm:text-lg font-semibold truncate">
                            {folder.name}
                          </h2>
                          <span className="text-xs sm:text-sm text-muted-foreground shrink-0">
                            ({folderAccounts.length})
                          </span>
                          {folderAccounts.length > 0 && (
                            <span
                              className={cn(
                                "text-xs sm:text-sm font-semibold tabular-nums shrink-0",
                                folderBalance >= 0
                                  ? "text-emerald-600"
                                  : "text-red-600",
                              )}
                            >
                              {formatCurrency(folderBalance)}
                            </span>
                          )}
                        </div>
                      </div>
                      {isMobile ? (
                        <DropdownMenu>
                          <DropdownMenuTrigger asChild>
                            <Button
                              variant="ghost"
                              size="icon"
                              className="h-8 w-8 shrink-0"
                            >
                              <MoreVertical className="w-4 h-4" />
                            </Button>
                          </DropdownMenuTrigger>
                          <DropdownMenuContent align="end">
                            <DropdownMenuItem
                              onClick={() => handleEditFolder(folder)}
                            >
                              <Pencil className="w-4 h-4 mr-2" />
                              Modifier
                            </DropdownMenuItem>
                            <DropdownMenuItem
                              onClick={() => handleDeleteFolder(folder.id)}
                              variant="destructive"
                            >
                              <Trash2 className="w-4 h-4 mr-2" />
                              Supprimer
                            </DropdownMenuItem>
                          </DropdownMenuContent>
                        </DropdownMenu>
                      ) : (
                        <>
                          <Button
                            variant="ghost"
                            size="sm"
                            onClick={() => handleEditFolder(folder)}
                            className="ml-auto shrink-0"
                          >
                            Modifier
                          </Button>
                          <Button
                            variant="ghost"
                            size="sm"
                            onClick={() => handleDeleteFolder(folder.id)}
                            className="text-destructive hover:text-destructive shrink-0"
                          >
                            Supprimer
                          </Button>
                        </>
                      )}
                    </div>
                    {folderAccounts.length > 0 ? (
                      <div className="grid gap-2 sm:gap-3 md:gap-4 grid-cols-2 sm:grid-cols-2 lg:grid-cols-3">
                        {folderAccounts.map((account) => {
                          const accountFolder = metadata.folders.find(
                            (f: FolderType) => f.id === account.folderId,
                          );

                          const accountWithStats = accountsWithStats.find(
                            (a) => a.id === account.id,
                          );
                          return (
                            <AccountCard
                              key={account.id}
                              account={account}
                              folder={accountFolder}
                              transactionCount={getTransactionCount(account.id)}
                              calculatedBalance={
                                accountWithStats?.calculatedBalance
                              }
                              onEdit={handleEdit}
                              onDelete={handleDelete}
                              formatCurrency={formatCurrency}
                              isSelected={selectedAccounts.has(account.id)}
                              onSelect={toggleSelectAccount}
                              draggableId={`account-${account.id}`}
                              compact={isCompactView}
                            />
                          );
                        })}
                      </div>
                    ) : (
                      <Card>
                        <CardContent className="flex flex-col items-center justify-center py-8">
                          <Folder className="w-12 h-12 text-muted-foreground mb-2" />
                          <p className="text-sm text-muted-foreground">
                            Aucun compte dans ce dossier
                          </p>
                          <p className="text-xs text-muted-foreground mt-1">
                            Glissez-déposez un compte ici pour l'ajouter
                          </p>
                        </CardContent>
                      </Card>
                    )}
                  </FolderDropZone>
                );
              })}
            </div>
            <DragOverlay>
              {activeId ? (
                <div className="opacity-50">
                  {activeId.startsWith("account-") ? (
                    <Card>
                      <CardContent className="p-4">
                        {accounts.find(
                          (a) => a.id === activeId.replace("account-", ""),
                        )?.name || ""}
                      </CardContent>
                    </Card>
                  ) : null}
                </div>
              ) : null}
            </DragOverlay>
          </DndContext>
        </>
      )}

      <AccountEditDialog
        open={isDialogOpen}
        onOpenChange={setIsDialogOpen}
        formData={formData}
        onFormDataChange={setFormData}
        folders={metadata.folders}
        onSave={handleSave}
      />

      <FolderEditDialog
        open={isFolderDialogOpen}
        onOpenChange={setIsFolderDialogOpen}
        editingFolder={editingFolder}
        formData={folderFormData}
        onFormDataChange={setFolderFormData}
        folders={metadata.folders}
        onSave={handleSaveFolder}
      />

      <AccountMergeSelectDialog
        open={isMergeDialogOpen}
        onOpenChange={(open) => {
          setIsMergeDialogOpen(open);
          if (!open) {
            // Réinitialiser la sélection après fusion
            setSelectedAccounts(new Set());
          }
        }}
        accounts={accounts}
        selectedAccountIds={Array.from(selectedAccounts)}
        onMerge={handleMergeAccounts}
        formatCurrency={formatCurrency}
      />
    </PageLayout>
  );
}
