import {
  useRef,
  useState,
  useEffect,
  LegacyRef,
  useContext,
  useCallback,
} from "react"
import ReactMarkdown from "react-markdown"
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
import { prism } from "react-syntax-highlighter/dist/esm/styles/prism"
import remarkGfm from "remark-gfm"
import { SidebarContext } from "../../side-bar-provider/side-bar.context"
import useWindowDimensions from "../../../hooks/use-window-dimensions.hook"
import { useAccountUser } from "../../../hooks/use-user.hook"
import { DashboardInput } from "../dashboard-input/dashboard-input.component"
import { Icon } from "../../../ui-component/icon/icon.component"
import { Config } from "../../../utils/config"
import styles from "./dashboard-message.module.css"
import { useParams } from "react-router-dom"
import { RoomType } from "../../../types/room.type"
import { MessageType } from "../../../types/message.type"

export function DashboardMessageRoom() {
  // ---------------------------------------------------------------------------
  // variables
  // ---------------------------------------------------------------------------

  const { width: screenWidth } = useWindowDimensions()
  const { isSideBarOpen, setIsSideBarOpen } = useContext(SidebarContext)
  const accountUser = useAccountUser()
  const { roomId } = useParams()

  const [messages, setMessages] = useState<MessageType[]>([])
  const [text, setText] = useState("")
  const [typingMessage, setTypingMessage] = useState<string | null>(null)

  const messagesEndRef = useRef<HTMLDivElement | null>(null)

  // ---------------------------------------------------------------------------
  // effects
  // ---------------------------------------------------------------------------

  useEffect(() => {
    if (screenWidth <= 900) {
      if (isSideBarOpen) setIsSideBarOpen(false)
    } else {
      if (!isSideBarOpen) setIsSideBarOpen(true)
    }
  }, [screenWidth])

  useEffect(() => {
    if (messagesEndRef.current) {
      messagesEndRef.current.scrollIntoView({ behavior: "smooth" })
    }
  }, [messages, typingMessage])

  // Fetch messages for the specific room when the component mounts or roomId changes
  useEffect(() => {
    const localRoom = localStorage.getItem("newRoom")
    if (localRoom) {
      const newRoom: RoomType | null = localRoom ? JSON.parse(localRoom) : null
      if (!newRoom) return
      addRoom(newRoom)
    }
  }, [roomId])

  // ---------------------------------------------------------------------------
  // functions
  // ---------------------------------------------------------------------------

  async function addRoom(newRoom: RoomType) {
    const response = await fetch(`${Config.url}/api/room/add`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(newRoom),
      credentials: "include",
    })
    const addNewRoom: RoomType = await response.json()
    const getstoredRooms = localStorage.getItem("rooms")
    const storedRooms: RoomType[] = getstoredRooms
      ? JSON.parse(getstoredRooms)
      : []
    const storedRoomFiltred = storedRooms.filter(
      (room) => room.id !== newRoom.id,
    )
    const updatedRooms = [...storedRoomFiltred, addNewRoom]
    localStorage.setItem("rooms", JSON.stringify(updatedRooms))

    localStorage.removeItem("newRoom")
    sendMessage()
  }

  const sendVoiceMessage = useCallback(async (file: File) => {
    if (!accountUser || !roomId || !file) return

    const formData = new FormData()
    formData.append("file", file)
    formData.append("senderId", accountUser.id)

    const response = await fetch(`${Config.url}/api/gptTeacher/voiceMessage`, {
      method: "POST",
      body: formData,
      credentials: "include",
    })

    const reader = response.body?.getReader()
    if (reader) {
      const decoder = new TextDecoder("utf-8")
      let botMessage = ""

      while (true) {
        const { value, done } = await reader.read()
        if (done) break
        botMessage += decoder.decode(value)
        setTypingMessage(botMessage)
      }

      setMessages((prevMessages) => [
        ...prevMessages,
        {
          senderId: "bot",
          text: botMessage,
          roomId: roomId!,
          id: String(Date.now()),
          created_at: Date.now(),
        },
      ])

      setTypingMessage(null)
    }
  }, [])

  const sendMessage = useCallback(async () => {
    // if (!accountUser || !roomId) return
    console.log("====================================")
    console.log("11111111111111")
    console.log("====================================")
    let newMessage: MessageType
    const localMessage = localStorage.getItem("newMessage")
    if (localMessage) {
      const newLocalMessage: MessageType | null = localMessage
        ? JSON.parse(localMessage)
        : null
      if (!newLocalMessage) return

      newMessage = {
        id: newLocalMessage.id,
        created_at: newLocalMessage.created_at,
        text: newLocalMessage.text,
        roomId: newLocalMessage.roomId,
        senderId: accountUser ? accountUser.id : "",
      }
    } else {
      newMessage = {
        id: String(Date.now()),
        created_at: Date.now(),
        text: text,
        roomId: roomId ? roomId : "",
        senderId: accountUser ? accountUser.id : "",
      }
    }

    const updatedMessages = [...messages, newMessage]
    setMessages(updatedMessages)

    const response = await fetch(`${Config.url}/api/gptTeacher/message`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(newMessage),
      credentials: "include",
    })

    const reader = response.body && response.body.getReader()
    if (reader) {
      const decoder = new TextDecoder("utf-8")
      let botMessage = ""

      while (true) {
        const { value, done } = await reader.read()
        if (done) break

        botMessage += decoder.decode(value)

        setTypingMessage(botMessage)
      }

      const finalUpdatedMessages: MessageType[] = [
        ...updatedMessages,
        {
          id: "hostMessage",
          created_at: newMessage.created_at,
          text: botMessage,
          roomId: newMessage.roomId,
          senderId: "bot",
        },
      ]
      localStorage.removeItem("newMessage")
      setMessages(finalUpdatedMessages)
      setTypingMessage(null)
    }

    setText("")
  }, [text, messages, roomId])

  function renderMessage(message: MessageType, index: number, key: string) {
    console.log("====================================")
    console.log("key", key)
    console.log("====================================")
    const isBot = message.senderId !== (accountUser && accountUser.id)

    return (
      <div
        key={index}
        style={{
          width: "100%",
          display: "flex",
          justifyContent: isBot ? "flex-start" : "flex-end",
          gap: "1.3rem",
        }}
      >
        {isBot && (
          <div className={styles.botIcon}>
            <img src="../../../public/bot-logo.svg" alt="logo" />
          </div>
        )}
        <div className={`${styles.chatMessage} ${styles.user}`}>
          <ReactMarkdown
            className={styles.messageText}
            remarkPlugins={[remarkGfm]}
            children={message.text}
            components={{
              code(props) {
                const { children, className, node, ref, ...rest } = props
                const match = /language-(\w+)/.exec(className || "")
                return match ? (
                  <SyntaxHighlighter
                    {...rest}
                    ref={ref as LegacyRef<SyntaxHighlighter> | undefined}
                    PreTag="div"
                    children={String(children).replace(/\n$/, "")}
                    language={match[1]}
                    style={prism}
                  />
                ) : (
                  <code {...rest} className={className}>
                    {children}
                  </code>
                )
              },
            }}
          />
        </div>
        {!isBot && (
          <div className={styles.userIcon}>
            {accountUser && accountUser.photo ? (
              <img src={accountUser.photo} className={styles.userPhoto} />
            ) : (
              <Icon name="fa-solid fa-circle-user" size="2.4" />
            )}
          </div>
        )}
      </div>
    )
  }

  // ---------------------------------------------------------------------------
  return (
    <div className={styles.rightContentContainer}>
      <div className={styles.listWrapper}>
        {messages.map((message, index) =>
          renderMessage(message, index, "mess"),
        )}

        {roomId &&
          accountUser &&
          typingMessage &&
          renderMessage(
            {
              id: "",
              created_at: 0,
              roomId: roomId,
              senderId: "bot",
              text: typingMessage,
            },
            -1,
            "type",
          )}
      </div>

      <div ref={messagesEndRef} />

      <DashboardInput
        value={text}
        onValueChange={setText}
        onSend={() => {
          sendMessage()
          setText("")
        }}
        onEnter={() => {
          sendMessage()
          setText("")
        }}
        onSendVoice={sendVoiceMessage}
      />
    </div>
  )
}
messagesEndRef not working