import { NodeViewWrapper } from '@tiptap/react'
import { v4 as uuidv4 } from 'uuid'
import { twMerge } from 'tailwind-merge'
import React from 'react'
import { BadgeHelp, Check, Minus, Plus, RefreshCcw } from 'lucide-react'
import ReactConfetti from 'react-confetti'
import { useEditorProvider } from '@components/Contexts/Editor/EditorContext'

interface Answer {
  answer_id: string
  answer: string
  correct: boolean
}
interface Question {
  question_id: string
  question: string
  type: 'multiple_choice' | 'custom_answer'
  answers: Answer[]
}

function QuizBlockComponent(props: any) {
  const [questions, setQuestions] = React.useState(
    props.node.attrs.questions
  ) as [Question[], any]
  const [userAnswers, setUserAnswers] = React.useState([]) as [any[], any]
  const [submitted, setSubmitted] = React.useState(false) as [boolean, any]
  const [submissionMessage, setSubmissionMessage] = React.useState('') as [
    string,
    any,
  ]
  const editorState = useEditorProvider() as any
  const isEditable = editorState.isEditable

  const handleAnswerClick = (question_id: string, answer_id: string) => {
    // if the quiz is submitted, do nothing
    if (submitted) {
      return
    }

    const userAnswer = {
      question_id: question_id,
      answer_id: answer_id,
    }
    const newAnswers = [...userAnswers, userAnswer]

    // only accept one answer per question
    const filteredAnswers = newAnswers.filter(
      (answer: any) => answer.question_id !== question_id
    )

    setUserAnswers([...filteredAnswers, userAnswer])
  }

  const refreshUserSubmission = () => {
    setUserAnswers([])
    setSubmitted(false)
  }

  const handleUserSubmission = () => {
    if (userAnswers.length === 0) {
      setSubmissionMessage('Please answer at least one question!')
      return
    }

    setSubmitted(true)

    // check if all submitted answers are correct
    const correctAnswers = questions.map((question: Question) => {
      const correctAnswer: any = question.answers.find(
        (answer: Answer) => answer.correct
      )
      const userAnswer = userAnswers.find(
        (userAnswer: any) => userAnswer.question_id === question.question_id
      )
      if (correctAnswer.answer_id === userAnswer.answer_id) {
        return true
      } else {
        return false
      }
    })

    // check if all answers are correct
    const allCorrect = correctAnswers.every(
      (answer: boolean) => answer === true
    )

    if (allCorrect) {
      setSubmissionMessage('All answers are correct!')
      console.log('All answers are correct!')
    } else {
      setSubmissionMessage('Some answers are incorrect!')
      console.log('Some answers are incorrect!')
    }
  }

  const getAnswerID = (answerIndex: number, questionId: string) => {
    const alphabet = Array.from({ length: 26 }, (_, i) =>
      String.fromCharCode('A'.charCodeAt(0) + i)
    )
    let alphabetID = alphabet[answerIndex]

    // Get question index
    const questionIndex = questions.findIndex(
      (question: Question) => question.question_id === questionId
    )
    let questionID = questionIndex + 1

    return `${alphabetID}`
  }

  const saveQuestions = (questions: any) => {
    props.updateAttributes({
      questions: questions,
    })
    setQuestions(questions)
  }
  const addSampleQuestion = () => {
    const newQuestion = {
      question_id: uuidv4(),
      question: '',
      type: 'multiple_choice',
      answers: [
        {
          answer_id: uuidv4(),
          answer: '',
          correct: false,
        },
      ],
    }
    setQuestions([...questions, newQuestion])
  }

  const addAnswer = (question_id: string) => {
    const newAnswer = {
      answer_id: uuidv4(),
      answer: '',
      correct: false,
    }

    // check if there is already more thqn 5 answers
    const question: any = questions.find(
      (question: Question) => question.question_id === question_id
    )
    if (question.answers.length >= 5) {
      return
    }

    const newQuestions = questions.map((question: Question) => {
      if (question.question_id === question_id) {
        question.answers.push(newAnswer)
      }
      return question
    })

    saveQuestions(newQuestions)
  }

  const changeAnswerValue = (
    question_id: string,
    answer_id: string,
    value: string
  ) => {
    const newQuestions = questions.map((question: Question) => {
      if (question.question_id === question_id) {
        question.answers.map((answer: Answer) => {
          if (answer.answer_id === answer_id) {
            answer.answer = value
          }
          return answer
        })
      }
      return question
    })
    saveQuestions(newQuestions)
  }

  const changeQuestionValue = (question_id: string, value: string) => {
    const newQuestions = questions.map((question: Question) => {
      if (question.question_id === question_id) {
        question.question = value
      }
      return question
    })
    saveQuestions(newQuestions)
  }

  const deleteQuestion = (question_id: string) => {
    const newQuestions = questions.filter(
      (question: Question) => question.question_id !== question_id
    )
    saveQuestions(newQuestions)
  }

  const deleteAnswer = (question_id: string, answer_id: string) => {
    const newQuestions = questions.map((question: Question) => {
      if (question.question_id === question_id) {
        question.answers = question.answers.filter(
          (answer: Answer) => answer.answer_id !== answer_id
        )
      }
      return question
    })
    saveQuestions(newQuestions)
  }

  const markAnswerCorrect = (question_id: string, answer_id: string) => {
    const newQuestions = questions.map((question: Question) => {
      if (question.question_id === question_id) {
        question.answers.map((answer: Answer) => {
          if (answer.answer_id === answer_id) {
            answer.correct = true
          } else {
            answer.correct = false
          }

          return answer
        })
      }
      return question
    })
    saveQuestions(newQuestions)
  }

  return (
    <NodeViewWrapper className="block-quiz">
      <div
        //style={{ background: "radial-gradient(152.15% 150.08% at 56.45% -6.67%, rgba(180, 255, 250, 0.10) 5.53%, rgba(202, 201, 255, 0.10) 66.76%)" }}
        className="rounded-xl px-5 py-2 bg-slate-100 transition-all ease-linear"
      >
        <div className="flex space-x-2 pt-1 items-center text-sm overflow-hidden">
          {submitted && submissionMessage == 'All answers are correct!' && (
            <ReactConfetti
              numberOfPieces={submitted ? 1400 : 0}
              recycle={false}
              className="w-full h-screen"
            />
          )}
          <div className="flex space-x-2 items-center text-sm">
            <BadgeHelp className="text-slate-400" size={15} />
            <p className="uppercase tracking-widest text-xs font-bold py-1 text-slate-400">
              Quiz
            </p>
          </div>
          <div className="grow flex items-center justify-center"></div>
          {isEditable ? (
            <div>
              <button
                onClick={addSampleQuestion}
                className="bg-slate-200 hover:bg-slate-300 text-slate-800 font-bold py-1 px-2 rounded-lg text-xs"
              >
                Add Question
              </button>
            </div>
          ) : (
            <div className="flex space-x-1 items-center">
              <div
                onClick={() => refreshUserSubmission()}
                className="cursor-pointer px-2"
              >
                <RefreshCcw
                  className="text-slate-400 cursor-pointer"
                  size={15}
                />
              </div>
              <button
                onClick={() => handleUserSubmission()}
                className="bg-slate-200 hover:bg-slate-300 text-slate-800 font-bold py-1 px-2 rounded-lg text-xs"
              >
                Submit
              </button>
            </div>
          )}
        </div>

        {questions.map((question: Question) => (
          <div key={question.question_id} className="pt-1 space-y-2">
            <div className="question">
              <div className="flex space-x-2 items-center">
                <div className="flex-grow">
                  {isEditable ? (
                    <input
                      value={question.question}
                      placeholder="Your Question"
                      onChange={(e) =>
                        changeQuestionValue(
                          question.question_id,
                          e.target.value
                        )
                      }
                      className="text-slate-800 bg-[#00008b00] border-2 border-gray-200 rounded-md border-dotted text-md font-bold w-full"
                    ></input>
                  ) : (
                    <p className="text-slate-800 bg-[#00008b00] rounded-md text-md font-bold w-full">
                      {question.question}
                    </p>
                  )}
                </div>
                {isEditable && (
                  <div
                    onClick={() => deleteQuestion(question.question_id)}
                    className="w-[20px] flex-none flex items-center h-[20px] rounded-lg bg-slate-200 hover:bg-slate-300 text-sm transition-all ease-linear cursor-pointer"
                  >
                    <Minus className="mx-auto text-slate-400" size={12} />
                  </div>
                )}
              </div>
              <div className="answers flex py-2 space-x-3">
                {question.answers.map((answer: Answer) => (
                  <div
                    key={answer.answer_id}
                    className={twMerge(
                      'outline outline-3 pr-2 shadow w-full flex items-center space-x-2 h-[30px] bg-opacity-50 hover:bg-opacity-100 hover:shadow-md rounded-s rounded-lg bg-white text-sm hover:scale-105 active:scale-110 duration-150 cursor-pointer ease-linear',
                      answer.correct && isEditable
                        ? 'outline-lime-300'
                        : 'outline-white',
                      userAnswers.find(
                        (userAnswer: any) =>
                          userAnswer.question_id === question.question_id &&
                          userAnswer.answer_id === answer.answer_id &&
                          !isEditable
                      )
                        ? 'outline-slate-300'
                        : '',
                      submitted && answer.correct
                        ? 'outline-lime-300 text-lime'
                        : '',
                      submitted &&
                        !answer.correct &&
                        userAnswers.find(
                          (userAnswer: any) =>
                            userAnswer.question_id === question.question_id &&
                            userAnswer.answer_id === answer.answer_id
                        )
                        ? 'outline-red-400'
                        : ''
                    )}
                    onClick={() =>
                      handleAnswerClick(question.question_id, answer.answer_id)
                    }
                  >
                    <div
                      className={twMerge(
                        'bg-white font-bold  text-base flex items-center h-full w-[40px] rounded-l-md text-slate-800',
                        answer.correct && isEditable
                          ? 'bg-lime-300 text-lime-800 outline-none'
                          : 'bg-white',
                        submitted && answer.correct
                          ? 'bg-lime-300 text-lime-800 outline-none'
                          : '',
                        submitted &&
                          !answer.correct &&
                          userAnswers.find(
                            (userAnswer: any) =>
                              userAnswer.question_id === question.question_id &&
                              userAnswer.answer_id === answer.answer_id
                          )
                          ? 'bg-red-400 text-red-800 outline-none'
                          : ''
                      )}
                    >
                      <p className="mx-auto font-bold text-sm ">
                        {getAnswerID(
                          question.answers.indexOf(answer),
                          question.question_id
                        )}
                      </p>
                    </div>
                    {isEditable ? (
                      <input
                        value={answer.answer}
                        onChange={(e) =>
                          changeAnswerValue(
                            question.question_id,
                            answer.answer_id,
                            e.target.value
                          )
                        }
                        placeholder="Answer"
                        className="w-full mx-2 px-3 pr-6 text-neutral-600 bg-[#00008b00] border-2 border-gray-200 rounded-md border-dotted text-sm font-bold"
                      ></input>
                    ) : (
                      <p className="w-full mx-2 px-3 pr-6 text-neutral-600 bg-[#00008b00] rounded-md ext-sm font-bold">
                        {answer.answer}
                      </p>
                    )}
                    {isEditable && (
                      <div className="flex space-x-1 items-center">
                        <div
                          onClick={() =>
                            markAnswerCorrect(
                              question.question_id,
                              answer.answer_id
                            )
                          }
                          className="w-[20px] flex-none flex items-center h-[20px] rounded-lg bg-lime-300 hover:bg-lime-400 transition-all ease-linear text-sm cursor-pointer "
                        >
                          <Check className="mx-auto text-lime-800" size={12} />
                        </div>
                        <div
                          onClick={() =>
                            deleteAnswer(question.question_id, answer.answer_id)
                          }
                          className="w-[20px] flex-none flex items-center h-[20px] rounded-lg bg-slate-200 hover:bg-slate-300 text-sm transition-all ease-linear cursor-pointer"
                        >
                          <Minus className="mx-auto text-slate-400" size={12} />
                        </div>
                      </div>
                    )}
                  </div>
                ))}
                {isEditable && (
                  <div
                    onClick={() => addAnswer(question.question_id)}
                    className="outline outline-3 w-[30px] flex-none flex items-center h-[30px] outline-white hover:bg-opacity-100 hover:shadow-md rounded-lg bg-white text-sm hover:scale-105 active:scale-110 duration-150 cursor-pointer ease-linear"
                  >
                    <Plus className="mx-auto text-slate-800" size={15} />
                  </div>
                )}
              </div>
            </div>
          </div>
        ))}
      </div>
    </NodeViewWrapper>
  )
}

export default QuizBlockComponent
