import React, {
  Context,
  createContext,
  Dispatch,
  useCallback,
  useContext,
  useMemo,
  useState,
} from "react";
import { useAccount, useConnect, useDisconnect } from "wagmi";
import { useWallet as useSolanaWallet } from "@solana/wallet-adapter-react";
import { SolanaWeb3Network } from "@src/models";

import { useCurrentAccount, useDisconnectWallet } from "@mysten/dapp-kit";

interface WalletInfo {
  address: string | undefined;
  isConnected: boolean;
  chainId: string | undefined;
  connectWallet: () => Promise<void>;
  disconnectWallet: () => Promise<void>;
}

export interface WalletState {
  openEVMWalletModal: boolean;
  setOpenEVMWalletModal: Dispatch<React.SetStateAction<boolean>>;
  openSolanaWalletModal: boolean;
  setOpenSolanaWalletModal: Dispatch<React.SetStateAction<boolean>>;
  openSuiWalletModal: boolean;
  setOpenSuiWalletModal: Dispatch<React.SetStateAction<boolean>>;
  evm: WalletInfo;
  solana: WalletInfo;
  sui: WalletInfo;
}

// Wallet Context
const WalletContext: Context<WalletState> = createContext<WalletState>(
  {} as WalletState,
);

export const WalletProvider = ({ children }: { children: React.ReactNode }) => {
  const [openEVMWalletModal, setOpenEVMWalletModal] = useState(false);
  const [openSolanaWalletModal, setOpenSolanaWalletModal] = useState(false);
  const [openSuiWalletModal, setOpenSuiWalletModal] = useState(false);

  // -------- EVM --------
  const {
    address: evmAddress,
    isConnected: isEvmConnected,
    chainId: evmChainId,
  } = useAccount();
  const { connect, connectors } = useConnect();
  const { disconnect: evmDisconnect } = useDisconnect();

  const connectEvmWallet = useCallback(async () => {
    connect({ connector: connectors[0]! }); // Default connector
  }, [connect, connectors]);

  const disconnectEvmWallet = useCallback(
    () => new Promise<void>((resolve) => resolve(evmDisconnect())),
    [evmDisconnect],
  );

  // -------- SOLANA --------
  const solanaWallet = useSolanaWallet();

  const connectSolanaWallet = useCallback(async () => {
    await solanaWallet.connect();
  }, [solanaWallet]);

  const disconnectSolanaWallet = useCallback(
    () => solanaWallet.disconnect(),
    [solanaWallet],
  );

  // -------- SUI --------
  const suiAccount = useCurrentAccount();
  const { mutateAsync: disconnectSui } = useDisconnectWallet();

  const connectSuiWallet = useCallback(async () => {
    setOpenSuiWalletModal(true);
  }, []);

  const disconnectSuiWallet = useCallback(async () => {
    await disconnectSui();
  }, [disconnectSui]);

  const state = useMemo(() => {
    return {
      evm: {
        address: evmAddress?.toString(),
        isConnected: isEvmConnected,
        chainId: evmChainId?.toString(),
        connectWallet: connectEvmWallet,
        disconnectWallet: disconnectEvmWallet,
      },
      solana: {
        address: solanaWallet.publicKey?.toBase58(),
        isConnected: !!solanaWallet.publicKey,
        chainId: SolanaWeb3Network.MAINNET,
        connectWallet: connectSolanaWallet,
        disconnectWallet: disconnectSolanaWallet,
      },
      sui: {
        address: suiAccount?.address,
        isConnected: !!suiAccount?.address,
        chainId: "sui-mainnet",
        connectWallet: connectSuiWallet,
        disconnectWallet: disconnectSuiWallet,
      },
    };
  }, [
    // evm
    evmAddress,
    isEvmConnected,
    evmChainId,
    connectEvmWallet,
    disconnectEvmWallet,
    // sol
    solanaWallet.publicKey,
    connectSolanaWallet,
    disconnectSolanaWallet,
    // sui
    suiAccount?.address,
    connectSuiWallet,
    disconnectSuiWallet,
  ]);

  return (
    <WalletContext.Provider
      value={{
        openEVMWalletModal,
        setOpenEVMWalletModal,
        openSolanaWalletModal,
        setOpenSolanaWalletModal,
        openSuiWalletModal,
        setOpenSuiWalletModal,
        ...state,
      }}
    >
      {children}
    </WalletContext.Provider>
  );
};

// Custom Hook
export const useWallet = () => useContext(WalletContext);
