import { SolanaMobileWalletAdapter } from '@solana-mobile/wallet-adapter-mobile'
import { WalletName, WalletReadyState } from '@solana/wallet-adapter-base'
import { useWallet, Wallet } from '@solana/wallet-adapter-react'
import { StandardWalletAdapter } from '@solana/wallet-standard-wallet-adapter-base'
import { useTranslation } from 'next-i18next'
import React, {
  createContext,
  ReactNode,
  useCallback,
  useContext,
  useEffect,
  useMemo,
} from 'react'
import mangoStore from '@store/mangoStore'
import { notify } from 'utils/notifications'
import { useLocalStorageStringState } from 'hooks/useLocalStorageState'

interface EnhancedWalletContextState {
  displayedWallets: Wallet[]
  preselectedWalletName: string | null
  handleSelect: (name: WalletName | null) => void
  handleConnect: () => Promise<void>
  handleDisconnect: () => Promise<void>
}

const EnhancedWalletContext = createContext<EnhancedWalletContextState>(
  {} as EnhancedWalletContextState
)

export function useEnhancedWallet(): EnhancedWalletContextState {
  return useContext(EnhancedWalletContext)
}

export default function EnhancedWalletProvider({
  children,
}: {
  children: ReactNode
}) {
  const { wallets, select, wallet, connect, disconnect } = useWallet()
  const { t } = useTranslation(['common', 'profile'])
  const set = mangoStore((s) => s.set)

  const displayedWallets = useMemo(
    () =>
      wallets.slice().sort(({ adapter: a }, { adapter: b }) => {
        if (a instanceof SolanaMobileWalletAdapter) {
          if (b instanceof SolanaMobileWalletAdapter) return 0
          return -1
        } else if (b instanceof SolanaMobileWalletAdapter) {
          return 1
        }

        if (a instanceof StandardWalletAdapter) {
          if (b instanceof StandardWalletAdapter) return 0
          return -1
        } else if (b instanceof StandardWalletAdapter) {
          return 1
        }

        if (a.readyState === b.readyState) return 0
        if (a.readyState === WalletReadyState.Installed) return -1
        if (b.readyState === WalletReadyState.Installed) return 1
        return 0
      }),
    [wallets]
  )

  const [preselectedWalletName, setPreselectedWalletName] =
    useLocalStorageStringState(
      'preselectedWalletName',
      wallet?.adapter.name || null
    )

  useEffect(() => {
    const adapter = wallets.find(
      ({ adapter }) => adapter.name === preselectedWalletName
    )?.adapter

    if (adapter) {
      select(adapter.name)
    }
  }, [preselectedWalletName, select, wallets])

  useEffect(() => {
    if (wallet) {
      setPreselectedWalletName(wallet.adapter.name)
      return
    }

    if (preselectedWalletName) return

    for (const { adapter } of displayedWallets) {
      if (
        adapter.readyState === WalletReadyState.Installed ||
        adapter.readyState === WalletReadyState.Loadable
      ) {
        setPreselectedWalletName(adapter.name)
        return
      }
    }
  }, [
    wallet,
    setPreselectedWalletName,
    select,
    preselectedWalletName,
    displayedWallets,
  ])

  const handleSelect = useCallback(
    (name: WalletName | null) => {
      setPreselectedWalletName(name)
      select(name)
    },
    [setPreselectedWalletName, select]
  )

  // const handleConnect = useCallback(async () => {
  //   setConnecting(true)
  //   const group = mangoStore.getState().group
  //   try {
  //     if (wallet && group) {
  //       await handleWalletConnect(wallet)
  //     }
  //   } catch (e) {
  //     console.error(e)
  //   } finally {
  //     setConnecting(false)
  //   }
  // }, [wallet])

  const handleConnect = useCallback(async () => {
    if (wallet) {
      try {
        console.log('connecting')
        await connect()
      } catch (e) {
        // Error will be handled by WalletProvider#onError
        select(null)
      }
    } else if (preselectedWalletName) {
      const adapter = wallets.find(
        ({ adapter }) => adapter.name === preselectedWalletName
      )?.adapter

      if (!adapter) {
        setPreselectedWalletName(null)
        return
      }

      if (
        adapter.readyState === WalletReadyState.Installed ||
        adapter.readyState === WalletReadyState.Loadable
      ) {
        select(adapter.name)
      } else {
        notify({
          title: `${adapter.name} Error`,
          type: 'error',
          description: `Please install ${adapter.name} and then reload this page.`,
        })
        if (typeof window !== 'undefined') {
          window.open(adapter.url, '_blank')
        }
      }
    }
  }, [
    wallets,
    select,
    wallet,
    connect,
    preselectedWalletName,
    setPreselectedWalletName,
  ])

  const handleDisconnect = useCallback(async () => {
    set((state) => {
      state.mangoAccounts = []
      state.mangoAccount.current = undefined
    })
    notify({
      type: 'info',
      title: t('wallet-disconnected'),
    })
    await disconnect()
  }, [set, t, disconnect])

  return (
    <EnhancedWalletContext.Provider
      value={{
        displayedWallets,
        preselectedWalletName,
        handleSelect,
        handleConnect,
        handleDisconnect,
      }}
    >
      {children}
    </EnhancedWalletContext.Provider>
  )
}
