/**
 * Investment Store
 * Zustand store for investment accounts, products, transactions, and withdrawals
 */

import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import {
  getProducts,
  getProductById,
  getProductPerformance,
  getUserAccounts,
  getAccountSummary,
  getAccountById,
  createAccount,
  closeAccount,
  getTransactions,
  createDeposit,
  createWithdrawal,
  getDistributions,
  getWithdrawals,
  type Product,
  type ProductPerformance,
  type InvestmentAccount,
  type AccountSummary,
  type AccountDetail,
  type Transaction,
  type Withdrawal,
  type Distribution,
} from '../services/investment.service';

// ============================================================================
// State Interface
// ============================================================================

interface InvestmentState {
  // Products
  products: Product[];
  selectedProduct: Product | null;
  productPerformance: ProductPerformance[];
  loadingProducts: boolean;
  loadingPerformance: boolean;

  // Accounts
  accounts: InvestmentAccount[];
  accountSummary: AccountSummary | null;
  selectedAccount: AccountDetail | null;
  loadingAccounts: boolean;
  loadingSummary: boolean;
  loadingAccountDetail: boolean;

  // Transactions
  transactions: Transaction[];
  transactionsTotal: number;
  loadingTransactions: boolean;

  // Distributions
  distributions: Distribution[];
  loadingDistributions: boolean;

  // Withdrawals
  withdrawals: Withdrawal[];
  loadingWithdrawals: boolean;

  // Operations
  creatingAccount: boolean;
  creatingDeposit: boolean;
  creatingWithdrawal: boolean;
  closingAccount: boolean;

  // Error state
  error: string | null;

  // Product Actions
  fetchProducts: (riskProfile?: string) => Promise<void>;
  selectProduct: (product: Product) => void;
  fetchProductById: (productId: string) => Promise<void>;
  fetchProductPerformance: (productId: string, period?: 'week' | 'month' | '3months' | 'year') => Promise<void>;

  // Account Actions
  fetchAccounts: () => Promise<void>;
  fetchAccountSummary: () => Promise<void>;
  selectAccountById: (accountId: string) => Promise<void>;
  createAccount: (productId: string, initialDeposit: number) => Promise<InvestmentAccount>;
  closeAccount: (accountId: string) => Promise<void>;

  // Transaction Actions
  fetchTransactions: (accountId: string, options?: { type?: string; status?: string; limit?: number; offset?: number }) => Promise<void>;
  createDeposit: (accountId: string, amount: number) => Promise<Transaction>;

  // Distribution Actions
  fetchDistributions: (accountId: string) => Promise<void>;

  // Withdrawal Actions
  fetchWithdrawals: (status?: string) => Promise<void>;
  createWithdrawal: (
    accountId: string,
    amount: number,
    destination: {
      bankInfo?: { bankName: string; accountNumber: string; routingNumber: string };
      cryptoInfo?: { network: string; address: string };
    }
  ) => Promise<Withdrawal>;

  // Utility Actions
  clearError: () => void;
  reset: () => void;
}

// ============================================================================
// Initial State
// ============================================================================

const initialState = {
  // Products
  products: [],
  selectedProduct: null,
  productPerformance: [],
  loadingProducts: false,
  loadingPerformance: false,

  // Accounts
  accounts: [],
  accountSummary: null,
  selectedAccount: null,
  loadingAccounts: false,
  loadingSummary: false,
  loadingAccountDetail: false,

  // Transactions
  transactions: [],
  transactionsTotal: 0,
  loadingTransactions: false,

  // Distributions
  distributions: [],
  loadingDistributions: false,

  // Withdrawals
  withdrawals: [],
  loadingWithdrawals: false,

  // Operations
  creatingAccount: false,
  creatingDeposit: false,
  creatingWithdrawal: false,
  closingAccount: false,

  // Error
  error: null,
};

// ============================================================================
// Store
// ============================================================================

export const useInvestmentStore = create<InvestmentState>()(
  devtools(
    (set, get) => ({
      ...initialState,

      // ========================================================================
      // Product Actions
      // ========================================================================

      fetchProducts: async (riskProfile?: string) => {
        set({ loadingProducts: true, error: null });

        try {
          const products = await getProducts(riskProfile);
          set({ products, loadingProducts: false });
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to fetch products';
          set({ error: message, loadingProducts: false });
          console.error('Error fetching products:', error);
        }
      },

      selectProduct: (product: Product) => {
        set({ selectedProduct: product });
      },

      fetchProductById: async (productId: string) => {
        set({ loadingProducts: true, error: null });

        try {
          const product = await getProductById(productId);
          set({ selectedProduct: product, loadingProducts: false });
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to fetch product';
          set({ error: message, loadingProducts: false });
          console.error('Error fetching product:', error);
        }
      },

      fetchProductPerformance: async (productId: string, period: 'week' | 'month' | '3months' | 'year' = 'month') => {
        set({ loadingPerformance: true, error: null });

        try {
          const performance = await getProductPerformance(productId, period);
          set({ productPerformance: performance, loadingPerformance: false });
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to fetch product performance';
          set({ error: message, loadingPerformance: false });
          console.error('Error fetching product performance:', error);
        }
      },

      // ========================================================================
      // Account Actions
      // ========================================================================

      fetchAccounts: async () => {
        set({ loadingAccounts: true, error: null });

        try {
          const accounts = await getUserAccounts();
          set({ accounts, loadingAccounts: false });
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to fetch accounts';
          set({ error: message, loadingAccounts: false });
          console.error('Error fetching accounts:', error);
        }
      },

      fetchAccountSummary: async () => {
        set({ loadingSummary: true, error: null });

        try {
          const summary = await getAccountSummary();
          set({ accountSummary: summary, loadingSummary: false });
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to fetch account summary';
          set({ error: message, loadingSummary: false });
          console.error('Error fetching account summary:', error);
        }
      },

      selectAccountById: async (accountId: string) => {
        set({ loadingAccountDetail: true, error: null });

        try {
          const account = await getAccountById(accountId);
          set({ selectedAccount: account, loadingAccountDetail: false });
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to fetch account detail';
          set({ error: message, loadingAccountDetail: false });
          console.error('Error fetching account detail:', error);
        }
      },

      createAccount: async (productId: string, initialDeposit: number) => {
        set({ creatingAccount: true, error: null });

        try {
          const newAccount = await createAccount(productId, initialDeposit);
          set((state) => ({
            accounts: [...state.accounts, newAccount],
            creatingAccount: false,
          }));

          // Refresh summary after creating account
          await get().fetchAccountSummary();

          return newAccount;
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to create account';
          set({ error: message, creatingAccount: false });
          console.error('Error creating account:', error);
          throw error;
        }
      },

      closeAccount: async (accountId: string) => {
        set({ closingAccount: true, error: null });

        try {
          await closeAccount(accountId);
          set((state) => ({
            accounts: state.accounts.filter((a) => a.id !== accountId),
            selectedAccount: state.selectedAccount?.id === accountId ? null : state.selectedAccount,
            closingAccount: false,
          }));

          // Refresh summary after closing account
          await get().fetchAccountSummary();
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to close account';
          set({ error: message, closingAccount: false });
          console.error('Error closing account:', error);
          throw error;
        }
      },

      // ========================================================================
      // Transaction Actions
      // ========================================================================

      fetchTransactions: async (accountId: string, options?: { type?: string; status?: string; limit?: number; offset?: number }) => {
        set({ loadingTransactions: true, error: null });

        try {
          const result = await getTransactions(accountId, options);
          set({
            transactions: result.transactions,
            transactionsTotal: result.total,
            loadingTransactions: false,
          });
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to fetch transactions';
          set({ error: message, loadingTransactions: false });
          console.error('Error fetching transactions:', error);
        }
      },

      createDeposit: async (accountId: string, amount: number) => {
        set({ creatingDeposit: true, error: null });

        try {
          const transaction = await createDeposit(accountId, amount);
          set({ creatingDeposit: false });

          // Refresh account data after deposit
          await get().fetchAccounts();
          await get().fetchAccountSummary();

          return transaction;
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to create deposit';
          set({ error: message, creatingDeposit: false });
          console.error('Error creating deposit:', error);
          throw error;
        }
      },

      // ========================================================================
      // Distribution Actions
      // ========================================================================

      fetchDistributions: async (accountId: string) => {
        set({ loadingDistributions: true, error: null });

        try {
          const distributions = await getDistributions(accountId);
          set({ distributions, loadingDistributions: false });
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to fetch distributions';
          set({ error: message, loadingDistributions: false });
          console.error('Error fetching distributions:', error);
        }
      },

      // ========================================================================
      // Withdrawal Actions
      // ========================================================================

      fetchWithdrawals: async (status?: string) => {
        set({ loadingWithdrawals: true, error: null });

        try {
          const withdrawals = await getWithdrawals(status);
          set({ withdrawals, loadingWithdrawals: false });
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to fetch withdrawals';
          set({ error: message, loadingWithdrawals: false });
          console.error('Error fetching withdrawals:', error);
        }
      },

      createWithdrawal: async (
        accountId: string,
        amount: number,
        destination: {
          bankInfo?: { bankName: string; accountNumber: string; routingNumber: string };
          cryptoInfo?: { network: string; address: string };
        }
      ) => {
        set({ creatingWithdrawal: true, error: null });

        try {
          const withdrawal = await createWithdrawal(accountId, amount, destination);
          set((state) => ({
            withdrawals: [withdrawal, ...state.withdrawals],
            creatingWithdrawal: false,
          }));

          // Refresh account data after withdrawal request
          await get().fetchAccounts();
          await get().fetchAccountSummary();

          return withdrawal;
        } catch (error) {
          const message = error instanceof Error ? error.message : 'Failed to create withdrawal';
          set({ error: message, creatingWithdrawal: false });
          console.error('Error creating withdrawal:', error);
          throw error;
        }
      },

      // ========================================================================
      // Utility Actions
      // ========================================================================

      clearError: () => {
        set({ error: null });
      },

      reset: () => {
        set(initialState);
      },
    }),
    {
      name: 'investment-store',
    }
  )
);

// ============================================================================
// Selectors
// ============================================================================

export const useProducts = () => useInvestmentStore((state) => state.products);
export const useSelectedProduct = () => useInvestmentStore((state) => state.selectedProduct);
export const useProductPerformance = () => useInvestmentStore((state) => state.productPerformance);
export const useAccounts = () => useInvestmentStore((state) => state.accounts);
export const useAccountSummary = () => useInvestmentStore((state) => state.accountSummary);
export const useSelectedAccount = () => useInvestmentStore((state) => state.selectedAccount);
export const useTransactions = () => useInvestmentStore((state) => state.transactions);
export const useTransactionsTotal = () => useInvestmentStore((state) => state.transactionsTotal);
export const useDistributions = () => useInvestmentStore((state) => state.distributions);
export const useWithdrawals = () => useInvestmentStore((state) => state.withdrawals);
export const useInvestmentError = () => useInvestmentStore((state) => state.error);
export const useLoadingProducts = () => useInvestmentStore((state) => state.loadingProducts);
export const useLoadingAccounts = () => useInvestmentStore((state) => state.loadingAccounts);
export const useLoadingSummary = () => useInvestmentStore((state) => state.loadingSummary);
export const useLoadingTransactions = () => useInvestmentStore((state) => state.loadingTransactions);
export const useLoadingWithdrawals = () => useInvestmentStore((state) => state.loadingWithdrawals);
export const useCreatingAccount = () => useInvestmentStore((state) => state.creatingAccount);
export const useCreatingDeposit = () => useInvestmentStore((state) => state.creatingDeposit);
export const useCreatingWithdrawal = () => useInvestmentStore((state) => state.creatingWithdrawal);

export default useInvestmentStore;
