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

import { useMemo } from "react";
import { useQuery } from "@tanstack/react-query";

import { BankingService } from "@/services/banking.service";
import type {
  BankingStats,
  Account,
  Transaction,
  Transfer,
  AccountFilters,
  TransactionFilters,
  TransferFilters,
} from "@/types/banking";

// Hooks pour récupérer les données nécessaires aux statistiques
import { useAccountsQuery } from "./use-accounts-queries";
import { useTransactionsQuery } from "./use-transactions-queries";
import { useTransfersQuery } from "./use-transfers-queries";

// ========================
// STATISTIQUES PRINCIPALES
// ========================

/**
 * Hook pour récupérer les statistiques Banking du serveur
 */
export function useBankingStatsQuery() {
  return useQuery({
    queryKey: ["banking", "stats"],
    queryFn: () => BankingService.getBankingStats(),
    staleTime: 60000, // 1 minute
    gcTime: 300000, // 5 minutes
  });
}

/**
 * Hook pour les statistiques calculées côté client
 */
export function useBankingStatsCalculated() {
  const accountsQuery = useAccountsQuery();
  const transactionsQuery = useTransactionsQuery();
  const transfersQuery = useTransfersQuery();

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

    // Statistiques des comptes
    const totalAccounts = accounts.length;
    const activeAccounts = accounts.filter((account) => account.status === "active").length;
    const frozenAccounts = accounts.filter((account) => account.status === "frozen").length;
    const closedAccounts = accounts.filter((account) => account.status === "closed").length;

    const totalBalance = accounts.reduce((sum, account) => {
      return sum + parseFloat(account.balance);
    }, 0);

    const accountsByType = accounts.reduce(
      (acc, account) => {
        acc[account.account_type] = (acc[account.account_type] || 0) + 1;
        return acc;
      },
      {} as Record<string, number>,
    );

    // Statistiques des transactions
    const totalTransactions = transactions.length;
    const todayTransactions = transactions.filter((transaction) => {
      const today = new Date().toISOString().split("T")[0];
      return transaction.created_at.startsWith(today);
    }).length;

    const transactionsByType = transactions.reduce(
      (acc, transaction) => {
        acc[transaction.type] = (acc[transaction.type] || 0) + 1;
        return acc;
      },
      {} as Record<string, number>,
    );

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

    const transactionVolume = transactions
      .filter((t) => t.status === "completed")
      .reduce((sum, transaction) => sum + Math.abs(parseFloat(transaction.amount)), 0);

    // Transactions des 30 derniers jours
    const thirtyDaysAgo = new Date();
    thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

    const recentTransactions = transactions.filter((transaction) => new Date(transaction.created_at) >= thirtyDaysAgo);

    const monthlyVolume = recentTransactions
      .filter((t) => t.status === "completed")
      .reduce((sum, transaction) => sum + Math.abs(parseFloat(transaction.amount)), 0);

    // Statistiques des transferts
    const totalTransfers = transfers.length;
    const pendingTransfers = transfers.filter((transfer) => transfer.status === "pending").length;
    const completedTransfers = transfers.filter((transfer) => transfer.status === "completed").length;
    const failedTransfers = transfers.filter((transfer) => transfer.status === "failed").length;

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

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

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

    return {
      accounts: {
        total: totalAccounts,
        active: activeAccounts,
        frozen: frozenAccounts,
        closed: closedAccounts,
        totalBalance: totalBalance.toString(),
        byType: accountsByType,
      },
      transactions: {
        total: totalTransactions,
        today: todayTransactions,
        volume: transactionVolume.toString(),
        monthlyVolume: monthlyVolume.toString(),
        byType: transactionsByType,
        byStatus: transactionsByStatus,
      },
      transfers: {
        total: totalTransfers,
        pending: pendingTransfers,
        completed: completedTransfers,
        failed: failedTransfers,
        volume: transferVolume.toString(),
        totalFees: totalFees.toString(),
        byStatus: transfersByStatus,
      },
    };
  }, [accountsQuery.data, transactionsQuery.data, transfersQuery.data]);

  const isLoading = accountsQuery.isLoading || transactionsQuery.isLoading || transfersQuery.isLoading;
  const error = accountsQuery.error || transactionsQuery.error || transfersQuery.error;

  return {
    stats,
    isLoading,
    error,
    refetch: () => {
      accountsQuery.refetch();
      transactionsQuery.refetch();
      transfersQuery.refetch();
    },
  };
}

// ========================
// STATISTIQUES SPÉCIALISÉES
// ========================

/**
 * Hook pour les statistiques par période
 */
export function usePeriodStats(fromDate: string, toDate: string) {
  const transactionFilters: TransactionFilters = {
    from_date: fromDate,
    to_date: toDate,
  };

  const transferFilters: TransferFilters = {
    from_date: fromDate,
    to_date: toDate,
  };

  const transactionsQuery = useTransactionsQuery(transactionFilters);
  const transfersQuery = useTransfersQuery(transferFilters);

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

    const deposits = transactions.filter((t) => t.type === "deposit" && t.status === "completed");
    const withdrawals = transactions.filter((t) => t.type === "withdrawal" && t.status === "completed");

    const totalDeposits = deposits.reduce((sum, t) => sum + parseFloat(t.amount), 0);
    const totalWithdrawals = withdrawals.reduce((sum, t) => sum + Math.abs(parseFloat(t.amount)), 0);
    const netFlow = totalDeposits - totalWithdrawals;

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

    return {
      period: { from: fromDate, to: toDate },
      deposits: {
        count: deposits.length,
        amount: totalDeposits.toString(),
      },
      withdrawals: {
        count: withdrawals.length,
        amount: totalWithdrawals.toString(),
      },
      netFlow: netFlow.toString(),
      transfers: {
        count: completedTransfers.length,
        volume: transferVolume.toString(),
        fees: transferFees.toString(),
      },
    };
  }, [fromDate, toDate, transactionsQuery.data, transfersQuery.data]);

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

/**
 * Hook pour les statistiques d'un compte spécifique
 */
export function useAccountStats(accountId: number) {
  const transactionFilters: TransactionFilters = {
    account_id: accountId,
  };

  const transferFilters: TransferFilters = {
    from_account_id: accountId,
  };

  const incomingTransferFilters: TransferFilters = {
    to_account_id: accountId,
  };

  const transactionsQuery = useTransactionsQuery(transactionFilters);
  const outgoingTransfersQuery = useTransfersQuery(transferFilters);
  const incomingTransfersQuery = useTransfersQuery(incomingTransferFilters);

  const stats = useMemo(() => {
    const transactions = transactionsQuery.data?.results || [];
    const outgoingTransfers = outgoingTransfersQuery.data?.results || [];
    const incomingTransfers = incomingTransfersQuery.data?.results || [];

    // Analyse des transactions
    const deposits = transactions.filter((t) => t.type === "deposit" && t.status === "completed");
    const withdrawals = transactions.filter((t) => t.type === "withdrawal" && t.status === "completed");

    const totalDeposits = deposits.reduce((sum, t) => sum + parseFloat(t.amount), 0);
    const totalWithdrawals = withdrawals.reduce((sum, t) => sum + Math.abs(parseFloat(t.amount)), 0);

    // Analyse des transferts
    const completedOutgoing = outgoingTransfers.filter((t) => t.status === "completed");
    const completedIncoming = incomingTransfers.filter((t) => t.status === "completed");

    const totalSent = completedOutgoing.reduce((sum, t) => sum + parseFloat(t.amount), 0);
    const totalReceived = completedIncoming.reduce((sum, t) => sum + parseFloat(t.amount), 0);
    const transferFeesPaid = completedOutgoing.reduce((sum, t) => sum + parseFloat(t.fee_amount), 0);

    // Activité récente (7 derniers jours)
    const sevenDaysAgo = new Date();
    sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);

    const recentTransactions = transactions.filter((t) => new Date(t.created_at) >= sevenDaysAgo).length;

    const recentTransfers = [...outgoingTransfers, ...incomingTransfers].filter(
      (t) => new Date(t.created_at) >= sevenDaysAgo,
    ).length;

    return {
      accountId,
      transactions: {
        total: transactions.length,
        deposits: {
          count: deposits.length,
          amount: totalDeposits.toString(),
        },
        withdrawals: {
          count: withdrawals.length,
          amount: totalWithdrawals.toString(),
        },
      },
      transfers: {
        sent: {
          count: completedOutgoing.length,
          amount: totalSent.toString(),
        },
        received: {
          count: completedIncoming.length,
          amount: totalReceived.toString(),
        },
        feesPaid: transferFeesPaid.toString(),
        netTransfer: (totalReceived - totalSent).toString(),
      },
      recentActivity: {
        transactions: recentTransactions,
        transfers: recentTransfers,
      },
    };
  }, [accountId, transactionsQuery.data, outgoingTransfersQuery.data, incomingTransfersQuery.data]);

  return {
    stats,
    isLoading: transactionsQuery.isLoading || outgoingTransfersQuery.isLoading || incomingTransfersQuery.isLoading,
    error: transactionsQuery.error || outgoingTransfersQuery.error || incomingTransfersQuery.error,
  };
}

/**
 * Hook pour les statistiques mensuelles
 */
export function useMonthlyStats(year: number, month: number) {
  const fromDate = `${year}-${month.toString().padStart(2, "0")}-01`;
  const toDate = new Date(year, month, 0).toISOString().split("T")[0]; // Dernier jour du mois

  return usePeriodStats(fromDate, toDate);
}

/**
 * Hook pour les statistiques quotidiennes
 */
export function useDailyStats(date: string) {
  return usePeriodStats(date, date);
}

/**
 * Hook pour le tableau de bord Banking avec métriques principales
 */
export function useBankingDashboard() {
  const serverStats = useBankingStatsQuery();
  const calculatedStats = useBankingStatsCalculated();

  // Stats du jour
  const today = new Date().toISOString().split("T")[0];
  const todayStats = useDailyStats(today);

  // Stats du mois
  const now = new Date();
  const monthlyStats = useMonthlyStats(now.getFullYear(), now.getMonth() + 1);

  const dashboard = useMemo(() => {
    const server = serverStats.data;
    const calculated = calculatedStats.stats;
    const todayData = todayStats.stats;
    const monthlyData = monthlyStats.stats;

    return {
      overview: {
        totalAccounts: server?.total_accounts || calculated.accounts.total,
        activeAccounts: server?.active_accounts || calculated.accounts.active,
        totalBalance: server?.total_balance || calculated.accounts.totalBalance,
        monthlyVolume: server?.monthly_transaction_volume || calculated.transactions.monthlyVolume,
      },
      today: {
        transactions: todayData.deposits.count + todayData.withdrawals.count,
        deposits: todayData.deposits.amount,
        withdrawals: todayData.withdrawals.amount,
        transfers: todayData.transfers.count,
      },
      month: {
        netFlow: monthlyData.netFlow,
        transferVolume: monthlyData.transfers.volume,
        transferFees: monthlyData.transfers.fees,
      },
      distribution: {
        accountsByStatus: {
          active: calculated.accounts.active,
          frozen: calculated.accounts.frozen,
          closed: calculated.accounts.closed,
        },
        transactionsByType: calculated.transactions.byType,
        transfersByStatus: calculated.transfers.byStatus,
      },
    };
  }, [serverStats.data, calculatedStats.stats, todayStats.stats, monthlyStats.stats]);

  const isLoading =
    serverStats.isLoading || calculatedStats.isLoading || todayStats.isLoading || monthlyStats.isLoading;

  return {
    dashboard,
    isLoading,
    error: serverStats.error || calculatedStats.error || todayStats.error || monthlyStats.error,
    refetch: () => {
      serverStats.refetch();
      calculatedStats.refetch();
    },
  };
}
