import React, { useState, useEffect } from "react"
import { useShallow } from "zustand/react/shallow"
import useStore from "../../utils/store"
import { publicInteractiveCreation } from "../../utils/rigo"
import {
  parseLesson,
  // useConsumableCall,
  validateTokens,
  checkParams,
  loginWithToken,
  createCourse,
  isSlugAvailable,
  // reWriteTitle,
  useConsumableCall,
  isValidRigoToken,
} from "../../utils/lib"

import Loader from "../Loader"
import { TMessage } from "../Message"
import { Lesson } from "../LessonItem"
import { ConsumablesManager } from "../ConsumablesManager"
import toast from "react-hot-toast"
import { ContentIndex } from "./ContentIndex"
import { Sidebar } from "./Sidebar"
import Login from "../Login"
import { useNavigate } from "react-router"
import { ParamsChecker } from "../ParamsChecker"
import { randomUUID } from "../../utils/creatorUtils"
import { RIGO_FLOAT_GIF } from "../../utils/constants"
import { useTranslation } from "react-i18next"
import NotificationListener from "../NotificationListener"

const SyllabusEditor: React.FC = () => {
  const navigate = useNavigate()
  const { i18n } = useTranslation()

  const {
    history,
    auth,
    setAuth,
    push,
    cleanAll,
    messages,
    setMessages,
    technologies,
  } = useStore(
    useShallow((state) => ({
      history: state.history,
      auth: state.auth,
      setAuth: state.setAuth,
      push: state.push,
      cleanAll: state.cleanAll,
      messages: state.messages,
      // formState: state.formState,
      setMessages: state.setMessages,
      technologies: state.technologies,
    }))
  )

  const [isGenerating, setIsGenerating] = useState(false)
  const [showLoginModal, setShowLoginModal] = useState(false)
  const [isThinking, setIsThinking] = useState(false)
  const [notificationId, setNotificationId] = useState<string>("")

  const syllabus = history[history.length - 1]

  useEffect(() => {
    if (!syllabus) {
      navigate("/creator", { replace: true })
    }
  }, [syllabus, navigate])

  useEffect(() => {
    ;(async () => {
      const { token } = checkParams(["token"])
      if (token) {
        const user = await loginWithToken(token)
        if (user) {
          setAuth({
            bcToken: token,
            userId: user.id,
            rigoToken: user.rigobot.key,
            user,
            publicToken: "",
          })
        }
      }
    })()
    checkSlug()
  }, [])

  const checkSlug = async () => {
    if (!syllabus.courseInfo.title) {
      toast.error("Please provide a title for the course")
      return
    }

    let newSlug = syllabus.courseInfo.slug
    let isAvailable = await isSlugAvailable(syllabus.courseInfo.slug)

    while (!isAvailable) {
      if (newSlug.length > 50) {
        newSlug = newSlug.slice(0, 44)
      }
      newSlug = newSlug + "-" + randomUUID()
      newSlug = newSlug.slice(0, 50)
      isAvailable = await isSlugAvailable(newSlug)
    }

    push({
      ...syllabus,
      courseInfo: {
        ...syllabus.courseInfo,
        slug: newSlug,
      },
    })
  }

  const sendPrompt = async (prompt: string) => {
    setIsThinking(true)

    try {
      setMessages([
        ...messages,
        { type: "user", content: prompt },
        { type: "assistant", content: "" },
      ])
      let isAuthenticated = false
      if (auth.rigoToken) {
        isAuthenticated = await isValidRigoToken(auth.rigoToken)
      }

      if (!isAuthenticated && auth.rigoToken) {
        setAuth({
          ...auth,
          rigoToken: "",
          bcToken: "",
          userId: "",
          user: null,
        })
      }

      const res = await publicInteractiveCreation(
        {
          courseInfo:
            JSON.stringify(syllabus.courseInfo) +
            `\nThe following technologies are available, choose up to 3 from the following list: <techs>${technologies
              .filter((t) => t.lang === syllabus.courseInfo.language)
              .map((t) => t.slug)
              .join(", ")}</techs>`,
          prevInteractions:
            messages
              .map((message) => `${message.type}: ${message.content}`)
              .join("\n") + `\nUSER: ${prompt}`,
        },
        auth.rigoToken && isAuthenticated ? auth.rigoToken : auth.publicToken,
        syllabus?.courseInfo?.purpose || "learnpack-lesson-writer",
        auth.rigoToken && isAuthenticated ? false : true
      )

      setNotificationId(res.notificationId)
    } catch (error) {
      console.error(error)
      const newMessages = [...messages]
      newMessages.pop()
      setMessages(newMessages as TMessage[])
      setIsThinking(false)
    }
  }

  const handleSubmit = async () => {
    if (!auth.bcToken || !auth.rigoToken) {
      setShowLoginModal(true)
      return
    }

    if (!syllabus.courseInfo.title) {
      toast.error("Please provide a title for the course")
      return
    }

    let tokenToUse = auth.rigoToken
    const onValidRigoToken = (rigotoken: string) => {
      setAuth({
        ...auth,
        rigoToken: rigotoken,
      })
      tokenToUse = rigotoken
    }
    const isValid = await validateTokens(auth.bcToken, onValidRigoToken)
    if (!isValid) {
      setShowLoginModal(true)
      return
    }
    const success = await useConsumableCall(
      auth.bcToken,
      "ai-course-generation"
    )
    if (!success) {
      toast.error(
        "You don't have enough credits to generate a course! Please add more credits to your account."
      )
      toast.loading("You will be redirected to the settings page in 5 seconds.")
      setTimeout(() => {
        window.location.href =
          "https://learnpack.co/settings?token=" + auth.bcToken
      }, 5000)
      return
    }

    setIsGenerating(true)

    const timeout = setTimeout(() => {
      cleanAll()
      window.location.href = `/preview/${syllabus.courseInfo.slug}?token=${auth.bcToken}&language=${syllabus.courseInfo.language}`
    }, 8000)
    try {
      await createCourse(syllabus, tokenToUse, auth.bcToken)
    } catch (error) {
      console.error("Failed to create course:", error)
      clearTimeout(timeout)
      setIsGenerating(false)
    }
  }

  if (!syllabus) return null

  console.log(syllabus.courseInfo)

  return isGenerating ? (
    <>
      <Loader
        listeningTo="course-generation"
        icon={<img src={RIGO_FLOAT_GIF} alt="rigo" className="w-20 h-20" />}
        initialBuffer="🚀 Starting course generation..."
        text="Learnpack is setting up your tutorial.
It may take a moment..."
      />
    </>
  ) : (
    <div className="flex w-full bg-white rounded-md shadow-md overflow-hidden h-screen ">
      <ParamsChecker />
      <NotificationListener
        onNotification={(res) => {
          const lessons: Lesson[] = res.parsed.listOfSteps.map((step: any) =>
            parseLesson(step, syllabus.lessons)
          )
          push({
            ...syllabus,
            lessons: lessons,
            courseInfo: {
              ...syllabus.courseInfo,
              title: res.parsed.title || syllabus.courseInfo.title,
              description:
                res.parsed.description || syllabus.courseInfo.description,
              language:
                res.parsed.languageCode || syllabus.courseInfo.language || "en",
              technologies:
                res.parsed.technologies.length > 0
                  ? res.parsed.technologies
                  : syllabus.courseInfo.technologies || [],
            },
          })

          if (res.parsed.languageCode) {
            i18n.changeLanguage(res.parsed.languageCode)
          }

          setMessages((prev) => [
            ...prev.filter((m) => Boolean(m.content)),
            {
              type: "assistant",
              content: res.parsed.aiMessage,
            },
          ])
          setIsThinking(false)
          setNotificationId("")
        }}
        notificationId={notificationId}
      />
      {showLoginModal && (
        <Login
          onFinish={() => {
            setShowLoginModal(false)
          }}
        />
      )}

      <ConsumablesManager />

      <Sidebar
        // messages={messages}
        sendPrompt={sendPrompt}
        handleSubmit={handleSubmit}
      />

      <ContentIndex
        handleSubmit={handleSubmit}
        messages={messages}
        isThinking={isThinking}
        openLogin={() => {
          setShowLoginModal(true)
        }}
      />
    </div>
  )
}

export default SyllabusEditor
