// type useAiChatProps = {}

import { useCallback, useMemo, useState } from "react"
import { useAccount } from "wagmi"

import { extractObjectFromAiResponse, sliceDecimalString } from "@/utils"

import useStore from "../store"
import { AiResponseToDetect, MorphoTokensOptions } from "../types"
import { generateDefaultMessage } from "../utils"
import {
  MIN_DEPOSIT_AMOUNT,
  MORPHO_STRATEGY_TOKENS,
} from "@/components/shared/constants"
import { sendUserPrompt } from "@/components/shared/api"

export const mockMessage = `
"You've selected the Seamless USDC Vault. Here are the details:

| Vault Name         | Current APY ↓ | 7-Day APY | Supply       | Exit Liquidity | Markets                                                                                     | Curator               |
|--------------------|----------------|------------|--------------|----------------|---------------------------------------------------------------------------------------------|-----------------------|
| Seamless USDC Vault | 14.354%        | 18.122%    | 15,799,881.44| 13,733,732.37  | Coinbase Wrapped BTC (9,978,764.00 USD), Wrapped liquid staked Ether 2.0 (120,193.40 USD) | Gauntlet              |

### Investment Strategy:

| Parameter      | Value            |
|----------------|------------------|
| Asset          | USDC             |
| Amount         | 17.812872 USDC   |
| Rebalancing    | Weekly           |

### Technical Details:
{
  "preferredVaults": [
    "0x616a4E1db48e22028f6bbf20444Cd3b8e3273738"
  ],
  "every": 604800,
  "baseToken": "USDC",
  "chainId": 8453,
  "amount": 17.812872
}

{
  "choicePrompts":["Deposit and Start Agent"]
} 

Your strategy is now set. Your deposit of 17.812872 USDC will be distributed among the Seamless USDC Vault and automatically rebalanced to maintain the highest APY. 

If you have any further questions or need assistance, feel free to ask!"  

`

// const BASE_BACKEND_URL = "https://api.console.fi"

const KEYS_TO_DETECT_IN_AI_RES = [
  "preferredVaults",
  "every",
  "baseToken",
  "chainId",
  "amount",
]

export const OPEN_DEPOSIT_MODAL_PROMPT = "Deposit and Start Agent"

const OPEN_DEPOSIT_MODAL_PROMPT_JSON = `
{
  "choicePrompts":["${OPEN_DEPOSIT_MODAL_PROMPT}"]
} 
`

export type ChatMessage = {
  role: "user" | "assistant"
  content: string
}

export default function useAiChat({
  tokenName,
  tokenAmount,
  tokenBalance,
  token,
  isTokenAlreadyDeposited,
}: {
  tokenName: string
  tokenAmount: string
  tokenBalance: string
  token: MorphoTokensOptions
  isTokenAlreadyDeposited: boolean
}) {
  const { userPositions } = useStore()

  const [input, setInput] = useState("")
  const [isLoading, setIsLoading] = useState(false)
  const [messages, setMessages] = useState<ChatMessage[]>([])
  const { address } = useAccount()

  const tokenConfig = MORPHO_STRATEGY_TOKENS[token]
  const userPositionData = useMemo(() => {
    return tokenConfig
      ? (userPositions[token]?.data || []).filter(
          (pos) =>
            (pos?.metadata?.baseToken || "").toLowerCase() ===
              tokenConfig.address.toLowerCase() &&
            pos?.metadata?.type === "EARN",
        )
      : []
  }, [token, tokenConfig, userPositions])
  const userHasPosition = userPositionData.length !== 0
  const minDepositAmount = MIN_DEPOSIT_AMOUNT[token as MorphoTokensOptions]

  const { setParamsDetectedInAiRes, openDepositModal } = useStore()

  const handleSendMessage = async (content: string, isUser: boolean) => {
    if (!address) return

    const sessionId = address
    const isFirstMessage = messages.length === 0

    // check if user wants to deposit

    if (content === OPEN_DEPOSIT_MODAL_PROMPT) {
      openDepositModal()
      setIsLoading(false)
      return
    }

    // Add the user's message to the chat
    setMessages((prev) => [
      ...prev,
      ...(isFirstMessage
        ? [
            generateDefaultMessage(
              sliceDecimalString(tokenAmount, 8),
              tokenName,
              userHasPosition,
              isTokenAlreadyDeposited,
              minDepositAmount,
            ),
          ]
        : []),
      {
        role: "user",
        content,
      } as ChatMessage,
    ])

    setIsLoading(true)

    const userPrompt = isFirstMessage
      ? ` ${content}` //, Context on user's status: ${generateUserContent({ tokenName, tokenAmount, tokenBalance, eoa: address, userPosition: userHasPosition ? userPositionData[0] : null })}`
      : content

    console.log("User prompt", userPrompt)
    try {
      const response = await sendUserPrompt(sessionId, userPrompt)

      if (response?.error || !response?.data) {
        throw new Error(
          response?.error || "Something went wrong,please try again",
        )
      }
      console.log({ response })
      const reader = response.data.body?.getReader()
      const decoder = new TextDecoder("utf-8")
      let buffer = ""

      if (reader) {
        let done = false
        while (!done) {
          const { done: isDone, value } = await reader.read()
          done = isDone

          if (done) break

          buffer += decoder.decode(value, { stream: true })

          // Check if the buffer includes [DONE], indicating the end of the stream
          if (buffer.includes("[DONE]")) {
            const finalMessage = buffer.replace("[DONE]", "").trim()

            console.log({ assistentMessage: finalMessage })

            // find transaction details
            const targetObject = extractObjectFromAiResponse(
              finalMessage,
              KEYS_TO_DETECT_IN_AI_RES,
            ) as AiResponseToDetect | null

            if (targetObject) {
              setParamsDetectedInAiRes(targetObject)
            }

            setMessages((prev) => [
              ...prev,
              {
                role: "assistant",
                content: targetObject
                  ? ` ${finalMessage}  
                      ${OPEN_DEPOSIT_MODAL_PROMPT_JSON}
                   `
                  : finalMessage,
              } as ChatMessage,
            ])
            setIsLoading(false)
            break
          }
        }
      }
      setIsLoading(false)
    } catch (error) {
      console.error("Failed to send message:", error)
      setMessages((prev) => [
        ...prev,
        {
          role: "assistant",
          content: "Failed to get a response. Please try again.",
        } as ChatMessage,
      ])
      setIsLoading(false)
    }
  }

  const handleSubmit = async (customInput?: string) => {
    const userInput = customInput || input
    if (userInput.trim() && !isLoading) {
      setIsLoading(true)

      try {
        const userMessage = userInput.trim()
        handleSendMessage(userMessage, true)
        setInput("") // Clear the input field
      } catch (error) {
        console.error("Error during chat:", error)
      }
    }
  }

  const resetChat = useCallback(() => {
    setMessages([])
    setInput("")
    setIsLoading(false)
  }, [])

  return {
    messages:
      messages.length > 0
        ? messages
        : [
            generateDefaultMessage(
              sliceDecimalString(tokenAmount, 8),
              tokenName,
              userHasPosition,
              isTokenAlreadyDeposited,
              minDepositAmount,
            ),
          ],
    handleSubmit,
    input,
    setInput,
    isLoading,
    resetChat,
  }
}
