/**
 * Hooks spécialisés pour les comptes 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 {
  AccountFilters,
  AccountCreateData,
  AccountUpdateData,
  Account,
  BalanceDetails,
  AccountStatement,
} from "@/types/banking";

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

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

/**
 * Hook pour récupérer un compte spécifique
 */
export function useAccountQuery(accountId: number) {
  return useQuery({
    queryKey: ["banking", "accounts", "detail", accountId],
    queryFn: () => BankingService.getAccount(accountId),
    enabled: !!accountId,
    staleTime: 60000,
  });
}

/**
 * Hook pour récupérer le solde d'un compte
 */
export function useAccountBalanceQuery(accountId: number) {
  return useQuery({
    queryKey: ["banking", "accounts", "balance", accountId],
    queryFn: () => BankingService.getAccountBalance(accountId),
    enabled: !!accountId,
    staleTime: 10000, // Plus fréquent pour les soldes
  });
}

/**
 * Hook pour récupérer le relevé d'un compte
 */
export function useAccountStatementQuery(accountId: number, fromDate: string, toDate: string, enabled = true) {
  return useQuery({
    queryKey: ["banking", "accounts", "statement", accountId, fromDate, toDate],
    queryFn: () => BankingService.getAccountStatement(accountId, fromDate, toDate),
    enabled: enabled && !!accountId && !!fromDate && !!toDate,
    staleTime: 300000, // 5 minutes pour les relevés
  });
}

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

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

  return useMutation({
    mutationFn: (data: AccountCreateData) => BankingService.createAccount(data),
    onSuccess: (newAccount: Account) => {
      // Invalider les listes de comptes
      queryClient.invalidateQueries({ queryKey: ["banking", "accounts", "list"] });

      // Ajouter le nouveau compte au cache
      queryClient.setQueryData(["banking", "accounts", "detail", newAccount.id], newAccount);

      toast.success(`Compte ${newAccount.account_number} créé avec succès`);
    },
    onError: (error) => {
      console.error("Erreur création compte:", error);
      toast.error("Erreur lors de la création du compte");
    },
  });
}

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

  return useMutation({
    mutationFn: (data: AccountCreateData) => BankingService.createAccountForClient(data),
    onSuccess: (newAccount: Account) => {
      queryClient.invalidateQueries({ queryKey: ["banking", "accounts", "list"] });
      queryClient.setQueryData(["banking", "accounts", "detail", newAccount.id], newAccount);
      toast.success(`Compte client ${newAccount.account_number} créé avec succès`);
    },
    onError: (error) => {
      console.error("Erreur création compte client:", error);
      toast.error("Erreur lors de la création du compte client");
    },
  });
}

/**
 * Hook pour mettre à jour un compte
 */
export function useUpdateAccountMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({ id, data }: { id: number; data: AccountUpdateData }) => BankingService.updateAccount(id, data),
    onSuccess: (updatedAccount: Account) => {
      // Mettre à jour le cache du compte spécifique
      queryClient.setQueryData(["banking", "accounts", "detail", updatedAccount.id], updatedAccount);

      // Invalider les listes pour refléter les changements
      queryClient.invalidateQueries({ queryKey: ["banking", "accounts", "list"] });

      toast.success("Compte mis à jour avec succès");
    },
    onError: (error) => {
      console.error("Erreur mise à jour compte:", error);
      toast.error("Erreur lors de la mise à jour du compte");
    },
  });
}

/**
 * Hook pour supprimer un compte
 */
export function useDeleteAccountMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (accountId: number) => BankingService.deleteAccount(accountId),
    onSuccess: (_, accountId) => {
      // Supprimer du cache
      queryClient.removeQueries({ queryKey: ["banking", "accounts", "detail", accountId] });
      queryClient.removeQueries({ queryKey: ["banking", "accounts", "balance", accountId] });

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

      toast.success("Compte supprimé avec succès");
    },
    onError: (error) => {
      console.error("Erreur suppression compte:", error);
      toast.error("Erreur lors de la suppression du compte");
    },
  });
}

/**
 * Hook pour geler un compte
 */
export function useFreezeAccountMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({ id, reason }: { id: number; reason?: string }) => BankingService.freezeAccount(id, reason),
    onSuccess: (updatedAccount: Account) => {
      queryClient.setQueryData(["banking", "accounts", "detail", updatedAccount.id], updatedAccount);
      queryClient.invalidateQueries({ queryKey: ["banking", "accounts", "list"] });

      toast.success(`Compte ${updatedAccount.account_number} gelé avec succès`);
    },
    onError: (error) => {
      console.error("Erreur gel compte:", error);
      toast.error("Erreur lors du gel du compte");
    },
  });
}

/**
 * Hook pour dégeler un compte
 */
export function useUnfreezeAccountMutation() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({ id, reason }: { id: number; reason?: string }) => BankingService.unfreezeAccount(id, reason),
    onSuccess: (updatedAccount: Account) => {
      queryClient.setQueryData(["banking", "accounts", "detail", updatedAccount.id], updatedAccount);
      queryClient.invalidateQueries({ queryKey: ["banking", "accounts", "list"] });

      toast.success(`Compte ${updatedAccount.account_number} dégelé avec succès`);
    },
    onError: (error) => {
      console.error("Erreur dégel compte:", error);
      toast.error("Erreur lors du dégel du compte");
    },
  });
}

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

/**
 * Hook composite pour la gestion complète d'un compte
 */
export function useAccountManagement(accountId?: number) {
  const accountQuery = useAccountQuery(accountId!);
  const balanceQuery = useAccountBalanceQuery(accountId!);

  const createMutation = useCreateAccountMutation();
  const updateMutation = useUpdateAccountMutation();
  const deleteMutation = useDeleteAccountMutation();
  const freezeMutation = useFreezeAccountMutation();
  const unfreezeMutation = useUnfreezeAccountMutation();

  const isLoading = useMemo(
    () =>
      createMutation.isPending ||
      updateMutation.isPending ||
      deleteMutation.isPending ||
      freezeMutation.isPending ||
      unfreezeMutation.isPending,
    [createMutation, updateMutation, deleteMutation, freezeMutation, unfreezeMutation],
  );

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

  const updateAccount = useCallback(
    (data: AccountUpdateData) => {
      if (!accountId) {
        toast.error("Aucun compte sélectionné");
        return;
      }
      updateMutation.mutate({ id: accountId, data });
    },
    [accountId, updateMutation],
  );

  const deleteAccount = useCallback(() => {
    if (!accountId) {
      toast.error("Aucun compte sélectionné");
      return;
    }
    deleteMutation.mutate(accountId);
  }, [accountId, deleteMutation]);

  const freezeAccount = useCallback(
    (reason?: string) => {
      if (!accountId) {
        toast.error("Aucun compte sélectionné");
        return;
      }
      freezeMutation.mutate({ id: accountId, reason });
    },
    [accountId, freezeMutation],
  );

  const unfreezeAccount = useCallback(
    (reason?: string) => {
      if (!accountId) {
        toast.error("Aucun compte sélectionné");
        return;
      }
      unfreezeMutation.mutate({ id: accountId, reason });
    },
    [accountId, unfreezeMutation],
  );

  return {
    // Données
    account: accountQuery.data,
    balance: balanceQuery.data,

    // États des requêtes
    isLoadingAccount: accountQuery.isLoading,
    isLoadingBalance: balanceQuery.isLoading,
    isLoading,

    // Erreurs
    accountError: accountQuery.error,
    balanceError: balanceQuery.error,

    // Actions
    createAccount,
    updateAccount,
    deleteAccount,
    freezeAccount,
    unfreezeAccount,

    // Mutations pour accès direct
    mutations: {
      create: createMutation,
      update: updateMutation,
      delete: deleteMutation,
      freeze: freezeMutation,
      unfreeze: unfreezeMutation,
    },

    // Fonctions de refresh
    refetchAccount: accountQuery.refetch,
    refetchBalance: balanceQuery.refetch,
  };
}

/**
 * Hook pour les filtres de comptes avec store Zustand
 */
export function useAccountFilters() {
  const { accountFilters, setAccountFilters } = useBankingStore();

  const updateFilters = useCallback(
    (newFilters: Partial<AccountFilters>) => {
      setAccountFilters({ ...accountFilters, ...newFilters });
    },
    [accountFilters, setAccountFilters],
  );

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

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

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