// @ts-check
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { match } from 'ts-pattern';
import {
  HMSRoomState,
  selectLocalPeer,
  selectLocalPeerRoleName,
  selectRoomState,
  useHMSActions,
  useHMSStore,
} from '@100mslive/react-sdk';
import { CheckCircleIcon, ChevronDownIcon, CrossCircleIcon } from '@100mslive/react-icons';
import { Box, Button, Flex, Text } from '../../../../';
import { checkCorrectAnswer } from '../../../common/utils';
import { MultipleChoiceOptions } from '../common/MultipleChoiceOptions';
import { SingleChoiceOptions } from '../common/SingleChoiceOptions';
import { QUESTION_TYPE } from '../../../common/constants';

export const QuestionCard = ({
  pollID,
  isQuiz,
  startedBy,
  pollState,
  index,
  totalQuestions,
  result,
  type,
  text,
  options = [],
  answer,
  localPeerResponse,
  updateSavedResponses,
  rolesThatCanViewResponses,
}) => {
  const actions = useHMSActions();
  const localPeer = useHMSStore(selectLocalPeer);
  const roomState = useHMSStore(selectRoomState);
  const isLocalPeerCreator = localPeer?.id === startedBy;
  const localPeerRoleName = useHMSStore(selectLocalPeerRoleName);
  const roleCanViewResponse =
    !rolesThatCanViewResponses ||
    rolesThatCanViewResponses.length === 0 ||
    rolesThatCanViewResponses.includes(localPeerRoleName || '');
  const [localPeerChoice, setLocalPeerChoice] = useState(localPeerResponse);

  useEffect(() => {
    setLocalPeerChoice(localPeerResponse);
  }, [localPeerResponse]);

  const showVoteCount =
    roleCanViewResponse && (localPeerChoice || (isLocalPeerCreator && pollState === 'stopped')) && !isQuiz;

  const isLive = pollState === 'started';
  const pollEnded = pollState === 'stopped';
  const canRespond = isLive && !localPeerChoice;
  const startTime = useRef(Date.now());
  const isCorrectAnswer = checkCorrectAnswer(answer, localPeerChoice, type);

  const [singleOptionAnswer, setSingleOptionAnswer] = useState();
  const [multipleOptionAnswer, setMultipleOptionAnswer] = useState(new Set());
  const [showOptions, setShowOptions] = useState(true);

  const respondedToQuiz = isQuiz && localPeerChoice && !localPeerChoice.skipped;

  const isValidVote = useMemo(() => {
    if (type === QUESTION_TYPE.SINGLE_CHOICE) {
      return singleOptionAnswer !== undefined;
    } else if (type === QUESTION_TYPE.MULTIPLE_CHOICE) {
      return multipleOptionAnswer.size > 0;
    }
  }, [singleOptionAnswer, multipleOptionAnswer, type]);

  const handleVote = useCallback(async () => {
    if (!isValidVote) {
      return;
    }
    const submittedResponse = {
      questionIndex: index,
      option: singleOptionAnswer,
      options: Array.from(multipleOptionAnswer),
      duration: Date.now() - startTime.current,
    };
    await actions.interactivityCenter.addResponsesToPoll(pollID, [submittedResponse]);
    updateSavedResponses(prev => {
      const prevCopy = { ...prev };
      prevCopy[index] = { option: singleOptionAnswer, options: Array.from(multipleOptionAnswer) };
      return prevCopy;
    });
    startTime.current = Date.now();
  }, [
    isValidVote,
    index,
    singleOptionAnswer,
    multipleOptionAnswer,
    actions.interactivityCenter,
    pollID,
    updateSavedResponses,
  ]);

  return (
    <Box
      css={{
        backgroundColor: '$surface_bright',
        borderRadius: '$1',
        p: '$md',
        mt: '$md',
        border:
          respondedToQuiz && !isLive
            ? `1px solid ${isCorrectAnswer ? '$alert_success' : '$alert_error_default'}`
            : 'none',
      }}
    >
      <Flex align="center" justify="between">
        <Text
          variant="caption"
          css={{
            color: match({ respondedToQuiz, isLive, isCorrectAnswer })
              .when(
                ({ respondedToQuiz, isLive }) => respondedToQuiz && !isLive,
                ({ isCorrectAnswer }) => (isCorrectAnswer ? '$alert_success' : '$alert_error_default'),
              )
              .otherwise(() => '$on_surface_low'),
            fontWeight: '$semiBold',
            display: 'flex',
            alignItems: 'center',
            gap: '$4',
          }}
        >
          {match({ respondedToQuiz, pollEnded, isCorrectAnswer })
            .when(
              ({ respondedToQuiz, pollEnded }) => respondedToQuiz && pollEnded,
              ({ isCorrectAnswer }) => {
                return isCorrectAnswer ? (
                  <CheckCircleIcon height={16} width={16} />
                ) : (
                  <CrossCircleIcon height={16} width={16} />
                );
              },
            )
            .otherwise(() => null)}
          QUESTION {index} OF {totalQuestions}: {type.toUpperCase()}
        </Text>
      </Flex>

      <Flex justify="between" css={{ my: '$md' }}>
        <Text css={{ color: '$on_surface_high' }}>{text}</Text>
        <Box
          css={{ color: '$on_surface_medium', '&:hover': { color: '$on_surface_high', cursor: 'pointer' } }}
          onClick={() => setShowOptions(prev => !prev)}
        >
          <ChevronDownIcon
            style={{ transform: showOptions ? 'rotate(180deg)' : 'rotate(0deg)', transition: 'transform 0.3s ease' }}
          />
        </Box>
      </Flex>

      <Box
        css={{ maxHeight: showOptions ? '$80' : '0', transition: 'max-height 0.3s ease', overflowY: 'auto', mb: '$4' }}
      >
        {type === QUESTION_TYPE.SINGLE_CHOICE ? (
          <SingleChoiceOptions
            key={index}
            questionIndex={index}
            isQuiz={isQuiz}
            canRespond={canRespond}
            correctOptionIndex={answer?.option}
            options={options}
            setAnswer={setSingleOptionAnswer}
            totalResponses={result?.totalResponses}
            showVoteCount={showVoteCount}
            localPeerResponse={localPeerChoice}
            isStopped={pollState === 'stopped'}
          />
        ) : null}

        {type === QUESTION_TYPE.MULTIPLE_CHOICE ? (
          <MultipleChoiceOptions
            questionIndex={index}
            isQuiz={isQuiz}
            canRespond={canRespond}
            correctOptionIndexes={answer?.options}
            options={options}
            selectedOptions={multipleOptionAnswer}
            setSelectedOptions={setMultipleOptionAnswer}
            totalResponses={result?.totalResponses}
            showVoteCount={showVoteCount}
            localPeerResponse={localPeerChoice}
            isStopped={pollState === 'stopped'}
          />
        ) : null}
      </Box>
      {isLive && (
        <QuestionActions
          disableVote={roomState !== HMSRoomState.Connected}
          isValidVote={isValidVote}
          onVote={handleVote}
          response={localPeerChoice}
          isQuiz={isQuiz}
        />
      )}
    </Box>
  );
};

const QuestionActions = ({ isValidVote, response, isQuiz, onVote, disableVote }) => {
  return (
    <Flex align="center" justify="end" css={{ gap: '$4', w: '100%' }}>
      {response ? (
        <Text css={{ fontWeight: '$semiBold', color: '$on_surface_medium' }}>
          {response.skipped ? 'Skipped' : null}
          {isQuiz && !response.skipped ? 'Answered' : null}
          {!isQuiz && !response.skipped ? 'Voted' : null}
        </Text>
      ) : (
        <Button css={{ p: '$xs $10', fontWeight: '$semiBold' }} disabled={!isValidVote || disableVote} onClick={onVote}>
          {isQuiz ? 'Answer' : 'Vote'}
        </Button>
      )}
    </Flex>
  );
};
