/**
 * Hooks spécialisés pour les transactions 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 {
  TransactionFilters,
  TransactionCreateData,
  DepositData,
  WithdrawalData,
  Transaction,
} from "@/types/banking";

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

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

/**
 * Hook pour récupérer une transaction spécifique
 */
export function useTransactionQuery(transactionId: number) {
  return useQuery({
    queryKey: ["banking", "transactions", "detail", transactionId],
    queryFn: () => BankingService.getTransaction(transactionId),
    enabled: !!transactionId,
    staleTime: 60000,
  });
}

/**
 * Hook pour récupérer les transactions d'un compte spécifique
 */
export function useAccountTransactionsQuery(accountId: number, filters?: Omit<TransactionFilters, "account_id">) {
  const transactionFilters = { ...filters, account_id: accountId };

  return useQuery({
    queryKey: ["banking", "transactions", "by-account", accountId, filters],
    queryFn: () => BankingService.getTransactions(transactionFilters),
    enabled: !!accountId,
    staleTime: 30000,
  });
}

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

/**
 * Hook pour créer une transaction générique
 */
export function useCreateTransactionMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (data: TransactionCreateData) => BankingService.createTransaction(data),
    onSuccess: (newTransaction: Transaction) => {
      // Invalider les listes de transactions
      queryClient.invalidateQueries({ queryKey: ["banking", "transactions", "list"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "transactions", "by-account"] });

      // Invalider les comptes concernés pour mettre à jour les soldes
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "detail", newTransaction.account.id],
      });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "balance", newTransaction.account.id],
      });

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

      toast.success(`Transaction ${newTransaction.transaction_id} créée avec succès`);
    },
    onError: (error) => {
      console.error("Erreur création transaction:", error);
      toast.error("Erreur lors de la création de la transaction");
    },
  });
}

/**
 * Hook pour créer une transaction pour un client spécifique
 */
export function useCreateTransactionForClientMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (data: TransactionCreateData) => BankingService.createTransactionForClient(data),
    onSuccess: (newTransaction: Transaction) => {
      queryClient.invalidateQueries({ queryKey: ["banking", "transactions"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "accounts"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "stats"] });

      toast.success(`Transaction client ${newTransaction.transaction_id} créée avec succès`);
    },
    onError: (error) => {
      console.error("Erreur création transaction client:", error);
      toast.error("Erreur lors de la création de la transaction client");
    },
  });
}

/**
 * Hook pour effectuer un dépôt
 */
export function useDepositMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (data: DepositData) => BankingService.deposit(data),
    onSuccess: (transaction: Transaction) => {
      // Mise à jour ciblée du cache
      queryClient.invalidateQueries({ queryKey: ["banking", "transactions"] });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "detail", transaction.account.id],
      });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "balance", transaction.account.id],
      });
      queryClient.invalidateQueries({ queryKey: ["banking", "stats"] });

      toast.success(`Dépôt de ${transaction.amount}€ effectué avec succès`);
    },
    onError: (error) => {
      console.error("Erreur dépôt:", error);
      toast.error("Erreur lors du dépôt");
    },
  });
}

/**
 * Hook pour effectuer un retrait
 */
export function useWithdrawalMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (data: WithdrawalData) => BankingService.withdrawal(data),
    onSuccess: (transaction: Transaction) => {
      queryClient.invalidateQueries({ queryKey: ["banking", "transactions"] });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "detail", transaction.account.id],
      });
      queryClient.invalidateQueries({
        queryKey: ["banking", "accounts", "balance", transaction.account.id],
      });
      queryClient.invalidateQueries({ queryKey: ["banking", "stats"] });

      toast.success(`Retrait de ${transaction.amount}€ effectué avec succès`);
    },
    onError: (error) => {
      console.error("Erreur retrait:", error);
      toast.error("Erreur lors du retrait");
    },
  });
}

/**
 * Hook pour annuler une transaction
 */
export function useCancelTransactionMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({ id, reason }: { id: number; reason?: string }) => BankingService.cancelTransaction(id, reason),
    onSuccess: (cancelledTransaction: Transaction) => {
      // Mettre à jour le cache de la transaction spécifique
      queryClient.setQueryData(["banking", "transactions", "detail", cancelledTransaction.id], cancelledTransaction);

      // Invalider les listes
      queryClient.invalidateQueries({ queryKey: ["banking", "transactions", "list"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "transactions", "by-account"] });

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

      toast.success(`Transaction ${cancelledTransaction.transaction_id} annulée`);
    },
    onError: (error) => {
      console.error("Erreur annulation transaction:", error);
      toast.error("Erreur lors de l'annulation de la transaction");
    },
  });
}

/**
 * Hook pour inverser une transaction
 */
export function useReverseTransactionMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({ id, reason }: { id: number; reason?: string }) => BankingService.reverseTransaction(id, reason),
    onSuccess: (reversedTransaction: Transaction) => {
      queryClient.invalidateQueries({ queryKey: ["banking", "transactions"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "accounts"] });
      queryClient.invalidateQueries({ queryKey: ["banking", "stats"] });

      toast.success(`Transaction ${reversedTransaction.transaction_id} inversée`);
    },
    onError: (error) => {
      console.error("Erreur inversion transaction:", error);
      toast.error("Erreur lors de l'inversion de la transaction");
    },
  });
}

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

/**
 * Hook composite pour la gestion complète des transactions
 */
export function useTransactionManagement() {
  const createMutation = useCreateTransactionMutation();
  const createForClientMutation = useCreateTransactionForClientMutation();
  const depositMutation = useDepositMutation();
  const withdrawalMutation = useWithdrawalMutation();
  const cancelMutation = useCancelTransactionMutation();
  const reverseMutation = useReverseTransactionMutation();

  const isLoading = useMemo(
    () =>
      createMutation.isPending ||
      createForClientMutation.isPending ||
      depositMutation.isPending ||
      withdrawalMutation.isPending ||
      cancelMutation.isPending ||
      reverseMutation.isPending,
    [createMutation, createForClientMutation, depositMutation, withdrawalMutation, cancelMutation, reverseMutation],
  );

  // Actions avec validation
  const createTransaction = useCallback(
    (data: TransactionCreateData) => {
      createMutation.mutate(data);
    },
    [createMutation],
  );

  const createTransactionForClient = useCallback(
    (data: TransactionCreateData) => {
      createForClientMutation.mutate(data);
    },
    [createForClientMutation],
  );

  const deposit = useCallback(
    (data: DepositData) => {
      depositMutation.mutate(data);
    },
    [depositMutation],
  );

  const withdrawal = useCallback(
    (data: WithdrawalData) => {
      withdrawalMutation.mutate(data);
    },
    [withdrawalMutation],
  );

  const cancelTransaction = useCallback(
    (id: number, reason?: string) => {
      cancelMutation.mutate({ id, reason });
    },
    [cancelMutation],
  );

  const reverseTransaction = useCallback(
    (id: number, reason?: string) => {
      reverseMutation.mutate({ id, reason });
    },
    [reverseMutation],
  );

  return {
    // Actions
    createTransaction,
    createTransactionForClient,
    deposit,
    withdrawal,
    cancelTransaction,
    reverseTransaction,

    // États généraux
    isLoading,

    // États spécifiques
    isCreating: createMutation.isPending,
    isCreatingForClient: createForClientMutation.isPending,
    isDepositing: depositMutation.isPending,
    isWithdrawing: withdrawalMutation.isPending,
    isCancelling: cancelMutation.isPending,
    isReversing: reverseMutation.isPending,

    // Mutations pour accès direct
    mutations: {
      create: createMutation,
      createForClient: createForClientMutation,
      deposit: depositMutation,
      withdrawal: withdrawalMutation,
      cancel: cancelMutation,
      reverse: reverseMutation,
    },
  };
}

/**
 * Hook pour la gestion des opérations de dépôt/retrait
 */
export function useDepositWithdrawalManagement() {
  const depositMutation = useDepositMutation();
  const withdrawalMutation = useWithdrawalMutation();

  const isLoading = useMemo(
    () => depositMutation.isPending || withdrawalMutation.isPending,
    [depositMutation.isPending, withdrawalMutation.isPending],
  );

  return {
    // Actions
    deposit: depositMutation.mutate,
    withdrawal: withdrawalMutation.mutate,

    // États
    isLoading,
    isDepositing: depositMutation.isPending,
    isWithdrawing: withdrawalMutation.isPending,

    // Mutations
    depositMutation,
    withdrawalMutation,
  };
}

/**
 * Hook pour les filtres de transactions avec store Zustand
 */
export function useTransactionFilters() {
  const { transactionFilters, setTransactionFilters } = useBankingStore();

  const updateFilters = useCallback(
    (newFilters: Partial<TransactionFilters>) => {
      setTransactionFilters({ ...transactionFilters, ...newFilters });
    },
    [transactionFilters, setTransactionFilters],
  );

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

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

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