/**
 * Hooks spécialisés pour les transferts Banking - COOP-CA AMIFOND
 */

import { useCallback, useMemo } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";

import { BankingService } from "@/services/banking.service";
import { useBankingStore } from "@/stores/banking";
import type { TransferFilters, TransferCreateData, Transfer } from "@/types/banking";

// ========================
// QUERIES - LECTURE
// ========================

/**
 * Hook pour récupérer la liste des transferts avec filtres
 */
export function useTransfersQuery(filters?: TransferFilters) {
  return useQuery({
    queryKey: ["banking", "transfers", "list", filters],
    queryFn: () => BankingService.getTransfers(filters),
    staleTime: 30000,
    gcTime: 300000,
  });
}

/**
 * Hook pour récupérer un transfert spécifique
 */
export function useTransferQuery(transferId: number) {
  return useQuery({
    queryKey: ["banking", "transfers", "detail", transferId],
    queryFn: () => BankingService.getTransfer(transferId),
    enabled: !!transferId,
    staleTime: 60000,
  });
}

/**
 * Hook pour récupérer les transferts sortants d'un compte
 */
export function useOutgoingTransfersQuery(accountId: number, filters?: Omit<TransferFilters, "from_account_id">) {
  const transferFilters = { ...filters, from_account_id: accountId };

  return useQuery({
    queryKey: ["banking", "transfers", "outgoing", accountId, filters],
    queryFn: () => BankingService.getTransfers(transferFilters),
    enabled: !!accountId,
    staleTime: 30000,
  });
}

/**
 * Hook pour récupérer les transferts entrants d'un compte
 */
export function useIncomingTransfersQuery(accountId: number, filters?: Omit<TransferFilters, "to_account_id">) {
  const transferFilters = { ...filters, to_account_id: accountId };

  return useQuery({
    queryKey: ["banking", "transfers", "incoming", accountId, filters],
    queryFn: () => BankingService.getTransfers(transferFilters),
    enabled: !!accountId,
    staleTime: 30000,
  });
}

/**
 * Hook pour récupérer tous les transferts liés à un compte (entrants + sortants)
 */
export function useAccountTransfersQuery(accountId: number, filters?: TransferFilters) {
  const outgoingQuery = useOutgoingTransfersQuery(accountId, filters);
  const incomingQuery = useIncomingTransfersQuery(accountId, filters);

  return useMemo(
    () => ({
      data: {
        outgoing: outgoingQuery.data?.results || [],
        incoming: incomingQuery.data?.results || [],
        all: [...(outgoingQuery.data?.results || []), ...(incomingQuery.data?.results || [])].sort(
          (a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
        ),
      },
      isLoading: outgoingQuery.isLoading || incomingQuery.isLoading,
      error: outgoingQuery.error || incomingQuery.error,
      refetch: () => {
        outgoingQuery.refetch();
        incomingQuery.refetch();
      },
    }),
    [outgoingQuery, incomingQuery],
  );
}

// ========================
// MUTATIONS - ÉCRITURE
// ========================

/**
 * Hook pour créer un transfert
 */
export function useCreateTransferMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (data: TransferCreateData) => BankingService.createTransfer(data),
    onSuccess: (newTransfer: Transfer) => {
      // Invalider toutes les listes de transferts
      queryClient.invalidateQueries({ queryKey: ["banking", "transfers", "list"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "transfers", "outgoing"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "transfers", "incoming"] });

      // Invalider les comptes concernés pour mise à jour des soldes
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "detail", newTransfer.from_account.id],
      });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "balance", newTransfer.from_account.id],
      });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "detail", newTransfer.to_account.id],
      });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "balance", newTransfer.to_account.id],
      });

      // Invalider les stats
      queryClient.invalidateQueries({ queryKey: ["banking", "stats"] });

      // Ajouter le nouveau transfert au cache
      queryClient.setQueryData(["banking", "transfers", "detail", newTransfer.id], newTransfer);

      toast.success(`Transfert ${newTransfer.transfer_id} créé avec succès`);
    },
    onError: (error) => {
      console.error("Erreur création transfert:", error);
      toast.error("Erreur lors de la création du transfert");
    },
  });
}

/**
 * Hook pour traiter un transfert en attente
 */
export function useProcessTransferMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (transferId: number) => BankingService.processTransfer(transferId),
    onSuccess: (processedTransfer: Transfer) => {
      // Mettre à jour le transfert spécifique dans le cache
      queryClient.setQueryData(["banking", "transfers", "detail", processedTransfer.id], processedTransfer);

      // Invalider les listes
      queryClient.invalidateQueries({ queryKey: ["banking", "transfers", "list"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "transfers", "outgoing"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "transfers", "incoming"] });

      // Invalider les comptes concernés
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "detail", processedTransfer.from_account.id],
      });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "balance", processedTransfer.from_account.id],
      });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "detail", processedTransfer.to_account.id],
      });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "balance", processedTransfer.to_account.id],
      });

      // Invalider les transactions si le transfert a généré une transaction
      if (processedTransfer.transaction) {
        queryClient.invalidateQueries({ queryKey: ["banking", "transactions"] });
      }

      toast.success(`Transfert ${processedTransfer.transfer_id} traité avec succès`);
    },
    onError: (error) => {
      console.error("Erreur traitement transfert:", error);
      toast.error("Erreur lors du traitement du transfert");
    },
  });
}

/**
 * Hook pour annuler un transfert
 */
export function useCancelTransferMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({ id, reason }: { id: number; reason?: string }) => BankingService.cancelTransfer(id, reason),
    onSuccess: (cancelledTransfer: Transfer) => {
      // Mettre à jour le transfert dans le cache
      queryClient.setQueryData(["banking", "transfers", "detail", cancelledTransfer.id], cancelledTransfer);

      // Invalider les listes
      queryClient.invalidateQueries({ queryKey: ["banking", "transfers", "list"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "transfers", "outgoing"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "transfers", "incoming"] });

      // Invalider les comptes si nécessaire (en cas de remboursement de frais)
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "detail", cancelledTransfer.from_account.id],
      });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "balance", cancelledTransfer.from_account.id],
      });

      toast.success(`Transfert ${cancelledTransfer.transfer_id} annulé`);
    },
    onError: (error) => {
      console.error("Erreur annulation transfert:", error);
      toast.error("Erreur lors de l'annulation du transfert");
    },
  });
}

// ========================
// HOOKS COMPOSITES
// ========================

/**
 * Hook composite pour la gestion complète des transferts
 */
export function useTransferManagement() {
  const createMutation = useCreateTransferMutation();
  const processMutation = useProcessTransferMutation();
  const cancelMutation = useCancelTransferMutation();

  const isLoading = useMemo(
    () => createMutation.isPending || processMutation.isPending || cancelMutation.isPending,
    [createMutation.isPending, processMutation.isPending, cancelMutation.isPending],
  );

  // Actions avec validation
  const createTransfer = useCallback(
    (data: TransferCreateData) => {
      // Validation côté client
      if (data.from_account_id === data.to_account_id) {
        toast.error("Le compte source et destination doivent être différents");
        return;
      }

      const amount = parseFloat(data.amount);
      if (isNaN(amount) || amount <= 0) {
        toast.error("Le montant doit être un nombre positif");
        return;
      }

      createMutation.mutate(data);
    },
    [createMutation],
  );

  const processTransfer = useCallback(
    (transferId: number) => {
      if (!transferId) {
        toast.error("ID transfert manquant");
        return;
      }
      processMutation.mutate(transferId);
    },
    [processMutation],
  );

  const cancelTransfer = useCallback(
    (id: number, reason?: string) => {
      if (!id) {
        toast.error("ID transfert manquant");
        return;
      }
      cancelMutation.mutate({ id, reason });
    },
    [cancelMutation],
  );

  return {
    // Actions
    createTransfer,
    processTransfer,
    cancelTransfer,

    // États généraux
    isLoading,

    // États spécifiques
    isCreating: createMutation.isPending,
    isProcessing: processMutation.isPending,
    isCancelling: cancelMutation.isPending,

    // Mutations pour accès direct
    mutations: {
      create: createMutation,
      process: processMutation,
      cancel: cancelMutation,
    },
  };
}

/**
 * Hook pour la gestion spécifique d'un transfert
 */
export function useTransferDetails(transferId: number) {
  const transferQuery = useTransferQuery(transferId);
  const transferManagement = useTransferManagement();

  const canProcess = useMemo(() => {
    const transfer = transferQuery.data;
    return transfer && transfer.status === "pending";
  }, [transferQuery.data]);

  const canCancel = useMemo(() => {
    const transfer = transferQuery.data;
    return transfer && ["pending", "scheduled"].includes(transfer.status);
  }, [transferQuery.data]);

  const processThisTransfer = useCallback(() => {
    if (transferId && canProcess) {
      transferManagement.processTransfer(transferId);
    }
  }, [transferId, canProcess, transferManagement]);

  const cancelThisTransfer = useCallback(
    (reason?: string) => {
      if (transferId && canCancel) {
        transferManagement.cancelTransfer(transferId, reason);
      }
    },
    [transferId, canCancel, transferManagement],
  );

  return {
    // Données
    transfer: transferQuery.data,

    // États
    isLoading: transferQuery.isLoading,
    error: transferQuery.error,

    // Capacités d'action
    canProcess,
    canCancel,

    // Actions spécifiques
    processThisTransfer,
    cancelThisTransfer,

    // États des actions
    isProcessing: transferManagement.isProcessing,
    isCancelling: transferManagement.isCancelling,

    // Fonction de refresh
    refetch: transferQuery.refetch,
  };
}

/**
 * Hook pour les filtres de transferts avec store Zustand
 */
export function useTransferFilters() {
  const { transferFilters, setTransferFilters } = useBankingStore();

  const updateFilters = useCallback(
    (newFilters: Partial<TransferFilters>) => {
      setTransferFilters({ ...transferFilters, ...newFilters });
    },
    [transferFilters, setTransferFilters],
  );

  const clearFilters = useCallback(() => {
    setTransferFilters({});
  }, [setTransferFilters]);

  const hasActiveFilters = useMemo(() => Object.keys(transferFilters).length > 0, [transferFilters]);

  return {
    filters: transferFilters,
    updateFilters,
    clearFilters,
    hasActiveFilters,
  };
}

/**
 * Hook pour les statistiques des transferts
 */
export function useTransferStats(filters?: TransferFilters) {
  const transfersQuery = useTransfersQuery(filters);

  const stats = useMemo(() => {
    const transfers = transfersQuery.data?.results || [];

    const byStatus = transfers.reduce(
      (acc, transfer) => {
        acc[transfer.status] = (acc[transfer.status] || 0) + 1;
        return acc;
      },
      {} as Record<string, number>,
    );

    const totalAmount = transfers
      .filter((t) => t.status === "completed")
      .reduce((sum, t) => sum + parseFloat(t.amount), 0);

    const totalFees = transfers
      .filter((t) => t.status === "completed")
      .reduce((sum, t) => sum + parseFloat(t.fee_amount), 0);

    return {
      total: transfers.length,
      byStatus,
      totalAmount: totalAmount.toString(),
      totalFees: totalFees.toString(),
      averageAmount: transfers.length > 0 ? (totalAmount / transfers.length).toString() : "0",
    };
  }, [transfersQuery.data]);

  return {
    stats,
    isLoading: transfersQuery.isLoading,
    error: transfersQuery.error,
  };
}
