import {
  chakra,
  Modal,
  ModalBody,
  ModalContent,
  ModalOverlay,
  useDisclosure,
  useToast,
} from '@chakra-ui/react'
import { TypebotViewer } from 'bot-engine'
import { useUser } from 'contexts/UserContext'
import { Answer, Typebot } from 'models'
import React, { useEffect, useRef, useState } from 'react'
import { parseTypebotToPublicTypebot } from 'services/publicTypebot'
import { sendRequest } from 'utils'
import confetti from 'canvas-confetti'

type Props = { totalTypebots: number }

export const OnboardingModal = ({ totalTypebots }: Props) => {
  const { user, saveUser } = useUser()
  const { isOpen, onOpen, onClose } = useDisclosure()
  const [typebot, setTypebot] = useState<Typebot>()
  const confettiCanvaContainer = useRef<HTMLCanvasElement | null>(null)
  const confettiCanon = useRef<confetti.CreateTypes>()
  const [chosenCategories, setChosenCategories] = useState<string[]>([])

  const toast = useToast({
    position: 'top-right',
    status: 'error',
  })

  useEffect(() => {
    fetchTemplate()

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  useEffect(() => {
    const isNewUser =
      user &&
      new Date(user?.createdAt as unknown as string).toDateString() ===
        new Date().toDateString() &&
      totalTypebots === 0
    if (isNewUser) onOpen()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [user])

  useEffect(() => {
    initConfettis()
    return () => {
      window.removeEventListener('message', handleIncomingMessage)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [confettiCanvaContainer.current])

  const initConfettis = () => {
    if (!confettiCanvaContainer.current || confettiCanon.current) return
    confettiCanon.current = confetti.create(confettiCanvaContainer.current, {
      resize: true,
      useWorker: true,
    })
    window.addEventListener('message', handleIncomingMessage)
  }

  const handleIncomingMessage = (message: MessageEvent) => {
    if (message.data.from === 'typebot') {
      if (message.data.action === 'shootConfettis' && confettiCanon.current)
        shootConfettis(confettiCanon.current)
    }
  }

  const fetchTemplate = async () => {
    const { data, error } = await sendRequest(`/bots/onboarding.json`)
    if (error) return toast({ title: error.name, description: error.message })
    setTypebot(data as Typebot)
  }

  const handleNewAnswer = (answer: Answer) => {
    const isName = answer.variableId === 'cl126f4hf000i2e6d8zvzc3t1'
    const isCompany = answer.variableId === 'cl126jqww000w2e6dq9yv4ifq'
    const isCategories = answer.variableId === 'cl126mo3t001b2e6dvyi16bkd'
    const isOtherCategories = answer.variableId === 'cl126q38p001q2e6d0hj23f6b'
    if (isName) saveUser({ name: answer.content })
    if (isCompany) saveUser({ company: answer.content })
    if (isCategories) {
      const onboardingCategories = answer.content.split(', ')
      saveUser({ onboardingCategories })
      setChosenCategories(onboardingCategories)
    }
    if (isOtherCategories)
      saveUser({
        onboardingCategories: [...chosenCategories, answer.content],
      })
  }

  return (
    <Modal
      size="3xl"
      isOpen={isOpen}
      onClose={onClose}
      blockScrollOnMount={false}
    >
      <chakra.canvas
        ref={confettiCanvaContainer}
        pos="fixed"
        top="0"
        left="0"
        w="full"
        h="full"
        zIndex={9999}
        pointerEvents="none"
      />
      <ModalOverlay />
      <ModalContent h="85vh">
        <ModalBody>
          {typebot && (
            <TypebotViewer
              typebot={parseTypebotToPublicTypebot(typebot)}
              predefinedVariables={{
                Name: user?.name?.split(' ')[0] ?? undefined,
              }}
              onNewAnswer={handleNewAnswer}
            />
          )}
        </ModalBody>
      </ModalContent>
    </Modal>
  )
}

const shootConfettis = (confettiCanon: confetti.CreateTypes) => {
  const count = 200
  const defaults = {
    origin: { y: 0.7 },
  }

  const fire = (
    particleRatio: number,
    opts: {
      spread: number
      startVelocity?: number
      decay?: number
      scalar?: number
    }
  ) => {
    confettiCanon(
      Object.assign({}, defaults, opts, {
        particleCount: Math.floor(count * particleRatio),
      })
    )
  }

  fire(0.25, {
    spread: 26,
    startVelocity: 55,
  })
  fire(0.2, {
    spread: 60,
  })
  fire(0.35, {
    spread: 100,
    decay: 0.91,
    scalar: 0.8,
  })
  fire(0.1, {
    spread: 120,
    startVelocity: 25,
    decay: 0.92,
    scalar: 1.2,
  })
  fire(0.1, {
    spread: 120,
    startVelocity: 45,
  })
}
