import { useEffect, useMemo } from "react"
import { useConnectModal } from "@rainbow-me/rainbowkit"
import styled from "styled-components"
import { useAccount } from "wagmi"
import { switchChain } from "@wagmi/core"

import {
  FlexContainer,
  LogoViewer,
  TooltipBox,
  Typography,
} from "@/components/shared/components"
import Tabs from "@/components/shared/components/Tabs"
import { MIN_DEPOSIT_AMOUNT } from "@/components/shared/constants"
import { defaultTheme } from "@/lib"
import { useThemeContext } from "@/providers/themeProvider"
import {
  formatUnits,
  isNotZero,
  minifyCurrencyValue,
  sliceDecimalString,
} from "@/utils"
import { baseWagmiConfig as wagmiConfig } from "@/wagmi"

import { frequencyOptions } from "../constants"
import DepositModal from "../DepositModal"
import useMorphoPositions from "../hooks/useMorphoPositions"
import useMorphoStrategy from "../hooks/useMorphoStrategy"
import useMorphoVaults from "../hooks/useMorphoVaults"
import TransactionHistory from "../TransactionHistory"
import { MorphoTokensOptions } from "../types"
import WithdrawModal from "../WithdrawModal"
import AiLayout from "../ai-components/AiLayout"
import MinimalDepositView from "../ai-components/MinimalDepositView"
import MinimalWithdrawView from "../ai-components/MinimalWithdrawView"
import useAiChat from "../hooks/useAiChat"
import { clearChatSession } from "@/components/shared/api"
import { BASE_CHAIN_ID } from "@/constants"

type TokenPageProps = {
  token: string
}

export default function TokenPage({ token }: TokenPageProps) {
  const { theme } = useThemeContext()
  const { openConnectModal } = useConnectModal()

  const {
    chainId,
    closeDepositModal,
    eoaAddress,
    isDepositModalOpen,
    openDepositModal,
    selectedFrequency,
    setTokenAmount,
    tokenAmount,
    tokenConfig,
    getMaxTokenBalanceAvailable,
    feeEstimate,
    handleDepositFunds,
    accountAssets,
    alreadyDepositedValue,
    handleDeployConsole,
    isFeeGreaterThanDeposit,
    consoleDeployedLoading,
    fundsDepositedLoading,
    waitForDepositLoading,
    withdrawAmount,
    isWithdrawModalOpen,
    closeWithdrawModal,
    openWithdrawModal,
    withdrawModalState,
    withdrawModalSuccessData,
    preferredVaults,
    isAiPromptValueSet,
    isTokenAlreadyDeposited,
  } = useMorphoStrategy(token as MorphoTokensOptions)

  const { currentVault } = useMorphoVaults(preferredVaults)

  const { userPositionData, userPositionVault, consoleAddress } =
    useMorphoPositions(token as MorphoTokensOptions)

  const {
    handleSubmit: handleAiMessageSubmit,
    messages: aiMessages,
    input: aiInput,
    isLoading: isAiMessageLoading,
    setInput: setAiInput,
    resetChat,
  } = useAiChat({
    tokenAmount: tokenAmount,
    tokenBalance: formatUnits(
      getMaxTokenBalanceAvailable.toString(),
      tokenConfig?.decimals,
    ),
    tokenName: tokenConfig?.name,
    token: token as MorphoTokensOptions,
    isTokenAlreadyDeposited,
  })

  useEffect(() => {
    eoaAddress && clearChatSession(eoaAddress)
    resetChat()
  }, [eoaAddress, token, resetChat])

  const minDepositAmount = MIN_DEPOSIT_AMOUNT[token as MorphoTokensOptions]

  const tokenBalance = Number(
    formatUnits(getMaxTokenBalanceAvailable, tokenConfig?.decimals) || "0",
  )

  const showMinAmountWarning =
    tokenBalance < minDepositAmount || Number(tokenAmount) < minDepositAmount

  const wrongChainId = chainId !== BASE_CHAIN_ID

  const isDepositButtonDisabled = useMemo(() => {
    if (!eoaAddress || wrongChainId) return false

    if (
      fundsDepositedLoading ||
      consoleDeployedLoading ||
      waitForDepositLoading
    )
      return true

    if (isTokenAlreadyDeposited) return false

    if (
      aiMessages.length < 2 ||
      parseFloat(tokenAmount) < minDepositAmount ||
      !isNotZero(tokenAmount)
    )
      return true
  }, [
    aiMessages.length,
    consoleDeployedLoading,
    eoaAddress,
    fundsDepositedLoading,
    isTokenAlreadyDeposited,
    minDepositAmount,
    tokenAmount,
    waitForDepositLoading,
    wrongChainId,
  ])

  if (!tokenConfig) return <></>

  const { name, logo, decimals } = tokenConfig

  const {
    apy,
    supply,
    name: vaultName,
  } = currentVault(token as MorphoTokensOptions)

  const feeEstimateFormatted = feeEstimate
    ? `${sliceDecimalString(formatUnits(feeEstimate, decimals), 8)} ${name}`
    : "--"

  const depositButtonText = !eoaAddress
    ? "Connect Wallet"
    : wrongChainId
      ? "Switch to Base"
      : isTokenAlreadyDeposited
        ? "Start Agent"
        : tokenAmount === "" || tokenAmount === "0"
          ? "Please enter amount"
          : "Start Agent"

  const depositButtonTooltip =
    !eoaAddress || tokenAmount === "" || tokenAmount === "0" || wrongChainId
      ? undefined
      : parseFloat(tokenAmount) < minDepositAmount
        ? `Minimum Deposit Amount: ${minDepositAmount} ${name}`
        : aiMessages.length === 1
          ? "Click “I want to deposit” to set up your agent."
          : isAiPromptValueSet
            ? "Your chosen vaults and settings from chat have been applied to the agent."
            : "The agent is set to default vault selection. To personalize your strategy, continue chatting until you’ve locked in your vault choices."

  function handleButtonAction() {
    if (!eoaAddress) {
      openConnectModal?.()
      return
    }

    if (wrongChainId) {
      switchChain(wagmiConfig, {
        chainId: BASE_CHAIN_ID,
      })
      return
    }

    openDepositModal()
  }

  const chatHasUserMessage = aiMessages.some((msg) => msg.role === "user")

  const showDepositSection = userPositionData.length === 0

  return (
    <>
      {showDepositSection && (
        <DepositModal
          currentVaultName={vaultName}
          isDepositInProgress={fundsDepositedLoading}
          isDeploymentInProgress={consoleDeployedLoading}
          isWaitingForFunds={waitForDepositLoading}
          apy={apy}
          isFeeGreaterThanDeposit={isFeeGreaterThanDeposit}
          onDepositClick={handleDepositFunds}
          isDepositDone={accountAssets.data.length !== 0}
          isOpen={isDepositModalOpen}
          onClose={closeDepositModal}
          isTokenAlreadyDeposited={isTokenAlreadyDeposited}
          amount={
            isTokenAlreadyDeposited
              ? formatUnits(alreadyDepositedValue.toString(), decimals)
              : tokenAmount
          }
          logo={logo}
          fees={feeEstimateFormatted}
          onDeployClick={handleDeployConsole}
          rebalanceValue={
            frequencyOptions.find(
              (option) => option.value === selectedFrequency,
            )?.label || ""
          }
        />
      )}
      <WithdrawModal
        withdrawModalSuccessData={withdrawModalSuccessData}
        state={withdrawModalState}
        isOpen={isWithdrawModalOpen}
        onClose={closeWithdrawModal}
        userPositionData={userPositionData[0]}
        onWithdrawClick={withdrawAmount}
      />

      <FlexContainer
        padding="10rem"
        width={100}
        gap={10}
        justifyContent="center"
        style={{
          position: "relative",
        }}
      >
        <FlexContainer
          style={{ maxWidth: "69.2rem", minWidth: "69.2rem" }}
          gap={4.4}
          flexDirection="column"
          width={100}
        >
          <FlexContainer flexDirection="column" alignItems="center" width={100}>
            <StyledTitle>Deploy your Morpho Yield Agent </StyledTitle>
            <FlexContainer alignItems="center" gap={1.2}>
              <StyledTitle>to maximize returns on your</StyledTitle>
              <FlexContainer alignItems="center" gap={0.8}>
                <LogoViewer size={32} logo={logo} />
                <StyledTitle>{name}</StyledTitle>
              </FlexContainer>
            </FlexContainer>
          </FlexContainer>

          <FlexContainer justifyContent="space-between" width={100}>
            {!showDepositSection && (
              <InfoGridItem
                title="Deposited"
                value={
                  sliceDecimalString(userPositionData[0].tokenData.amount, 8) +
                  " " +
                  userPositionData[0].tokenData.asset.name
                }
              />
            )}
            <InfoGridItem
              valueColor={theme.colors.success}
              title="Current Max APY"
              value={userPositionVault?.apy || apy}
            />
            {userPositionVault?.supply && (
              <InfoGridItem
                title="Current Vault TVL"
                value={minifyCurrencyValue(userPositionVault?.supply)}
                tooltip={userPositionVault?.supply || supply}
              />
            )}
            <InfoGridItem title="Rebalancing" value="Auto" />
            {showDepositSection && (
              <InfoGridItem
                valueColor={theme.colors.success}
                title="Transactions"
                value="Gasless"
              />
            )}
          </FlexContainer>
          {showDepositSection ? (
            <AiLayout
              tokenAmount={tokenAmount}
              actionButtonInfo={
                isNotZero(tokenAmount)
                  ? "Guide the agent with clear prompts. Customize Curators, Rebalancing, Liquidity, and APY to fit your strategy."
                  : `Min. ${minDepositAmount} ${name} deposit required for Morpho Agent interaction.`
              }
              isChatDisabled={
                isAiMessageLoading ||
                !isNotZero(tokenAmount) ||
                !chatHasUserMessage
              }
              buttonText={depositButtonText}
              buttonTooltip={depositButtonTooltip}
              loading={isAiMessageLoading}
              buttonAction={handleButtonAction}
              buttonDisabled={!!isDepositButtonDisabled}
              handleSubmit={handleAiMessageSubmit}
              messages={aiMessages}
              input={aiInput}
              setInput={setAiInput}
              topSlot={
                <MinimalDepositView
                  alreadyDepositedValue={alreadyDepositedValue}
                  isTokenAlreadyDeposited={isTokenAlreadyDeposited}
                  setTokenAmount={setTokenAmount}
                  tokenAmount={tokenAmount}
                  tokenConfig={tokenConfig}
                  minDepositAmount={minDepositAmount}
                  maxAvailableValue={getMaxTokenBalanceAvailable}
                  showMinAmountWarning={
                    !isTokenAlreadyDeposited && showMinAmountWarning
                  }
                />
              }
            />
          ) : (
            <FlexContainer justifyContent="center" width={100}>
              <div style={{ width: "40.8rem" }}>
                <Tabs
                  size="FULL"
                  tabsTitle={[
                    { title: "Position" },
                    { title: "Transaction History" },
                  ]}
                >
                  <AiLayout
                    consoleAddress={consoleAddress}
                    hideChat={true}
                    tokenAmount={tokenAmount}
                    isChatDisabled={isAiMessageLoading}
                    buttonText={"Withdraw"}
                    buttonTooltip={
                      userPositionData[0].vaultPositionData
                        ? ""
                        : "Agent setup in progress. Withdrawal will be available once the setup is completed (typically 2-5 minutes)"
                    }
                    buttonAction={openWithdrawModal}
                    buttonDisabled={!userPositionData[0].vaultPositionData}
                    handleSubmit={handleAiMessageSubmit}
                    messages={aiMessages}
                    input={aiInput}
                    setInput={setAiInput}
                    topSlot={
                      <MinimalWithdrawView
                        onWithdrawClick={openWithdrawModal}
                        userPositionData={userPositionData[0]}
                      />
                    }
                  />
                  <FlexContainer>
                    <TransactionHistory
                      history={userPositionData[0]?.history || []}
                    />
                  </FlexContainer>
                </Tabs>
              </div>
            </FlexContainer>
          )}
        </FlexContainer>
      </FlexContainer>
    </>
  )
}

function InfoGridItem({
  title,
  value,
  tooltip,
  valueColor = defaultTheme.colors.white,
}: {
  title: string
  value: string
  tooltip?: string
  valueColor?: string
}) {
  const { theme } = useThemeContext()
  return (
    <FlexContainer flex={false} flexDirection="column" gap={0.8}>
      <TooltipBox content={tooltip}>
        <Typography type="TITLE_XL" color={valueColor}>
          {value}
        </Typography>
      </TooltipBox>
      <Typography type="BODY_M" color={theme.colors.gray300}>
        {title}
      </Typography>
    </FlexContainer>
  )
}

const StyledTitle = styled(Typography)`
  color: white;
  font-size: 36px;
  font-style: normal;
  font-weight: 500;
  line-height: 44px;
`
