import React, { useEffect, useState } from 'react';
import styles from './index.less';
import { answer, detail } from '@/services/paper';
import { history } from 'umi';
import questionBg from '../asset/question_bg.png';
import useTime from '../asset/ic_answer_use_time.png';
import questionCount from '../asset/ic_answer_count.png';
import dialogSuccessBg from '../asset/dialog_success_bg.png';
import dialogFailedBg from '../asset/dialog_failed_bg.png';
import { getPageQuery } from '@/utils/utils';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import { UnorderedListOutlined } from '@ant-design/icons';

import {
  QUESTION_TYPE_JUDGE,
  QUESTION_TYPE_MULTIPLE_CHOICE,
  QUESTION_TYPE_RATE,
  QUESTION_TYPE_SINGER_CHOICE,
  QUESTION_TYPE_TEXT,
} from '@/services/constants';
import { Button, message, Space } from 'antd';
import { Checkbox, Mask, Radio, TextArea } from 'antd-mobile/es';

type DialogInfo = {
  bg: any;
  title: string;
  message: string;
  btnTxt: string;
  click?: any;
};

const Question: React.FC = () => {
  const [paper, setPaper] = useState<API.Paper>();
  const [currentIndex, setCurrentIndex] = useState(0);
  const [answerList, setAnswerList] = useState<API.Answer[]>();
  const [showDialog, setShowDialog] = useState(false);
  const [showAnswerResult, setShowAnswerResult] = useState(false);
  const [dialogInfo, setDialogInfo] = useState<DialogInfo>();
  const [use, setUse] = useState(0);
  const paperId = parseInt(getPageQuery().id + '');
  const secret = getPageQuery().secret;
  const [draftTimeOutId, setDraftTimeOutId] = useState<NodeJS.Timeout>();

  if (!paperId) {
    return <>访问异常</>;
  }

  useEffect(() => {
    let timerId;
    detail(paperId, secret).then((response) => {
      let current = Date.now();
      if (response.code == 200) {
        let map = new Map<number, API.Answer>();
        if (
          response.data?.draftAnswerList &&
          response.data?.draftAnswerList.length > 0
        ) {
          response.data?.draftAnswerList.forEach((item) => {
            map[item.questionId!] = item;
          });
          current = Date.now() - response.data?.draftUseTime! * 1000;
        }
        timerId = setInterval(() => {
          const temp = parseInt(String((Date.now() - current) / 1000));
          setUse(temp);
        }, 1000);

        let tempList: API.Answer[] = [];
        response.data?.questionList!.forEach((item) => {
          const answer = map[item.id!];
          if (answer) {
            tempList.push(answer);
          } else {
            tempList.push({
              questionId: item.id,
            });
          }
        });
        setAnswerList(tempList);
        setPaper(response.data);
      } else if (response.code == 3008) {
        history.push(
          `/paper/login?redirect=${encodeURIComponent(window.location.href)}`,
        );
      } else if (response.code == 4000) {
        history.push('/paper/result?type=noAccess');
      } else if (response.code == 7001) {
        history.push('/paper/result?type=notExist');
      } else if (response.code == 7002) {
        history.push('/paper/result?type=success');
      }
    });

    return () => {
      clearInterval(timerId);
    };
  }, []);

  const secToTime = (s: number) => {
    let t = '';
    if (s > -1) {
      let min = Math.floor(s / 60) % 60;
      let sec = s % 60;
      if (min < 10) {
        t += '0';
      }
      t += min + ':';
      if (sec < 10) {
        t += '0';
      }
      t += sec.toFixed(0);
    }
    return t;
  };

  const draft = () => {
    if (draftTimeOutId) {
      clearTimeout(draftTimeOutId);
    }

    const tempId = setTimeout(() => {
      setAnswerList((prevState) => {
        const submitParam: API.SubmitAnswerParam = {
          paperId: paperId,
          status: 0,
          useTime: use,
          secret: secret,
          answerList: prevState,
        };

        answer(submitParam)
          .then(() => {})
          .catch(() => {});
        return prevState;
      });
    }, 1000);
    setDraftTimeOutId(tempId);
  };

  const submit = () => {
    for (let i = 0; i < answerList?.length!; i++) {
      let finish = isFinish(answerList![i]);
      if (!finish) {
        setDialogInfo({
          bg: dialogFailedBg,
          title: '答题未完成',
          message: `第${i + 1}题未完成作答\n` + '请继续作答！',
          btnTxt: '前往答题',
          click: () => {
            setShowDialog(false);
            setCurrentIndex(i);
          },
        });
        setShowDialog(true);
        return;
      }
    }

    const submitParam: API.SubmitAnswerParam = {
      paperId: paperId,
      useTime: use,
      status: 1,
      secret: secret,
      answerList: answerList,
    };

    answer(submitParam)
      .then((response) => {
        if (response.code == 200) {
          setDialogInfo({
            bg: dialogSuccessBg,
            title: '完成答题',
            message: '感谢您的参与！',
            btnTxt: '好的',
            click: () => {
              history.push('/paper/result?type=success');
            },
          });
          setShowDialog(true);
        } else {
          setDialogInfo({
            bg: dialogFailedBg,
            title: '答题未完成',
            message: response.message || '',
            btnTxt: '好的',
            click: () => {
              setShowDialog(false);
            },
          });
          setShowDialog(true);
        }
      })
      .catch(() => {
        setDialogInfo({
          bg: dialogFailedBg,
          title: '答题未完成',
          message: '未知异常，请稍后再试',
          btnTxt: '好的',
          click: () => {
            setShowDialog(false);
          },
        });
        setShowDialog(true);
      });
  };

  const getQuestionType = () => {
    const type = paper?.questionList![currentIndex]?.type;
    if (type == QUESTION_TYPE_RATE) {
      return '评分';
    } else if (type == QUESTION_TYPE_SINGER_CHOICE) {
      return '单选';
    } else if (type == QUESTION_TYPE_MULTIPLE_CHOICE) {
      return '多选';
    } else if (type == QUESTION_TYPE_JUDGE) {
      return '判断';
    } else if (type == QUESTION_TYPE_TEXT) {
      return '简答';
    } else {
      return '未知';
    }
  };

  const isFinish = (item?: API.Answer) => {
    if (!item) {
      return false;
    }
    let isFinish = false;

    if (item.score && item.score > 0) {
      isFinish = true;
    }

    if (item.judge && item.judge > 0) {
      isFinish = true;
    }

    if (item.optionId) {
      if (item.hasInput) {
        if (item.text && item.text != '') {
          isFinish = true;
        } else {
          isFinish = false;
        }
      } else {
        isFinish = true;
      }
    }

    if (item.optionIds && item.optionIds.length > 0) {
      if (item.hasInput) {
        if (item.text && item.text != '') {
          isFinish = true;
        } else {
          isFinish = false;
        }
      } else {
        isFinish = true;
      }
    }

    if (item.text && item.text != '') {
      isFinish = true;
    }

    return isFinish;
  };

  const getQuestionContent = () => {
    if (!paper) {
      return <></>;
    }
    const question = paper?.questionList![currentIndex];
    const answer = answerList![currentIndex];
    const type = question?.type;
    if (type == QUESTION_TYPE_RATE) {
      return rateQuestion(question, answer);
    } else if (type == QUESTION_TYPE_SINGER_CHOICE) {
      return singerChoiceQuestion(question, answer);
    } else if (type == QUESTION_TYPE_MULTIPLE_CHOICE) {
      return multipleChoiceQuestion(question, answer);
    } else if (type == QUESTION_TYPE_JUDGE) {
      return judgeQuestion(question, answer);
    } else if (type == QUESTION_TYPE_TEXT) {
      return textQuestion(question, answer);
    } else {
      return <></>;
    }
  };

  const textQuestion = (question?: API.Question, answer?: API.Answer) => {
    return (
      <>
        <TextArea
          className={styles.textArea}
          rows={4}
          placeholder="请输入..."
          maxLength={100}
          key={question?.id}
          defaultValue={answer?.text || ''}
          onChange={(value) => {
            const copy = [...(answerList || [])];
            copy![currentIndex] = {
              questionId: answer?.questionId,
              text: value,
            };
            setAnswerList(copy);
            draft();
          }}
        />
      </>
    );
  };

  const singerChoiceQuestion = (
    question?: API.Question,
    answer?: API.Answer,
  ) => {
    return (
      <>
        <Radio.Group
          key={question?.id}
          onChange={(value) => {
            const copy = [...(answerList || [])];
            let hasInput = false;
            question?.optionList?.map((item, index) => {
              if (item.id == value && item.needInput == 1) {
                hasInput = true;
              }
            });

            copy![currentIndex] = {
              questionId: answer?.questionId,
              optionId: value,
              hasInput: hasInput,
            };
            setAnswerList(copy);
            draft();
          }}
          value={answer?.optionId}
        >
          <Space direction="vertical">
            {question?.optionList?.map((item, index) => {
              return (
                <div>
                  <Radio value={item.id} key={index} className={styles.radio}>
                    {item.title}
                  </Radio>
                  {item.needInput == 1 && answer?.optionId == item.id && (
                    <div>
                      <TextArea
                        className={styles.optionInput}
                        rows={2}
                        placeholder="请输入..."
                        maxLength={100}
                        key={question?.id + ':' + item.id}
                        defaultValue={answer?.text || ''}
                        onBlur={(b) => {
                          draft();
                        }}
                        onChange={(value) => {
                          answer!.text = value;
                        }}
                      />
                    </div>
                  )}
                </div>
              );
            })}
          </Space>
        </Radio.Group>
      </>
    );
  };

  const judgeQuestion = (question?: API.Question, answer?: API.Answer) => {
    return (
      <>
        <Radio.Group
          key={question?.id}
          onChange={(value) => {
            const copy = [...(answerList || [])];
            copy![currentIndex] = {
              questionId: answer?.questionId,
              judge: value,
            };
            setAnswerList(copy);
            draft();
          }}
          value={answer?.judge}
        >
          <Space direction="vertical">
            <Radio value={1} className={styles.radio}>
              正确
            </Radio>
            <Radio value={2} className={styles.radio}>
              错误
            </Radio>
          </Space>
        </Radio.Group>
      </>
    );
  };

  function sortOptionAnswerList(optionAnswer, questionOption) {
    if (optionAnswer == null || optionAnswer.length == 0) {
      return optionAnswer;
    }

    const map = new Map();
    questionOption.forEach((num, index) => {
      map.set(num, index);
    });

    optionAnswer.sort((a, b) => {
      const indexA = map.get(a);
      const indexB = map.get(b);
      return indexA - indexB;
    });

    return optionAnswer;
  }

  const sortQuestionOptionList = (questionList, answerList) => {
    if (answerList == null || answerList.length == 0) {
      return questionList;
    }

    const map = new Map();
    answerList.forEach((num, index) => {
      map.set(num, index);
    });

    questionList.sort((a, b) => {
      if (map.has(a.id) && map.has(b.id)) {
        return map.get(a.id) - map.get(b.id);
      } else if (map.has(a.id) && !map.has(b.id)) {
        return -1;
      } else if (!map.has(a.id) && map.has(b.id)) {
        return 1;
      } else {
        return a.id - b.id;
      }
    });

    return questionList;
  };

  const multipleChoiceQuestion = (
    question?: API.Question,
    answer?: API.Answer,
  ) => {
    console.log(answer);
    return (
      <>
        <Checkbox.Group
          key={question?.id}
          onChange={(checkedValues) => {
            if (
              question?.optionLimit &&
              checkedValues.length > question?.optionLimit
            ) {
              message.error(`最多仅能选择${question?.optionLimit}项`);
              return;
            }

            const copy = [...(answerList || [])];
            let hasInput = false;
            question?.optionList?.map((item, index) => {
              if (checkedValues.indexOf(item.id) > -1 && item.needInput == 1) {
                hasInput = true;
              }
            });

            copy![currentIndex] = {
              questionId: answer?.questionId,
              optionIds: checkedValues,
              hasInput: hasInput,
            };
            setAnswerList(copy);
            draft();

            if (question?.needSort == 1) {
              let newOptions = sortQuestionOptionList(
                question?.optionList,
                checkedValues,
              );

              const updatedQuestionList = paper?.questionList?.map((item) => {
                if (question?.id === item.id) {
                  return { ...item, optionList: newOptions };
                }
                return item;
              });

              setPaper((prevState) => ({
                ...prevState,
                questionList: updatedQuestionList,
              }));
            }
          }}
          value={answer?.optionIds == null ? [] : answer?.optionIds}
        >
          <Space direction="vertical">
            <DragDropContext
              onDragEnd={(result) => {
                if (question?.needSort != 1) {
                  return;
                }

                if (!result.destination) {
                  return;
                }

                let newOptions = Array.from(question?.optionList);
                const [reorderedOption] = newOptions.splice(
                  result.source.index,
                  1,
                );
                newOptions.splice(result.destination.index, 0, reorderedOption);

                const newAnswerOptionIds = sortOptionAnswerList(
                  answerList[currentIndex].optionIds,
                  newOptions.map((obj) => obj.id),
                );
                const copy = [...(answerList || [])];

                copy![currentIndex] = {
                  ...answerList[currentIndex],
                  optionIds: newAnswerOptionIds,
                };
                setAnswerList(copy);
                draft();

                newOptions = sortQuestionOptionList(
                  question?.optionList,
                  answerList[currentIndex].optionIds,
                );

                const updatedQuestionList = paper?.questionList?.map((item) => {
                  if (question?.id === item.id) {
                    return { ...item, optionList: newOptions };
                  }
                  return item;
                });

                setPaper((prevState) => ({
                  ...prevState,
                  questionList: updatedQuestionList,
                }));
              }}
            >
              <Droppable droppableId={question?.id + ''}>
                {(provided) => (
                  <div ref={provided.innerRef} {...provided.droppableProps}>
                    {question?.optionList?.map((item, index) => {
                      return (
                        <Draggable
                          key={item.id}
                          draggableId={item.id + ''}
                          index={index}
                          isDragDisabled={
                            question?.needSort != 1 ||
                            answer?.optionIds == null ||
                            answer?.optionIds?.indexOf(item.id) < 0
                          }
                        >
                          {(provided) => (
                            <div
                              ref={provided.innerRef}
                              {...provided.draggableProps}
                              {...provided.dragHandleProps}
                              className={styles.checkWrapper}
                            >
                              <div className={styles.checkGroup}>
                                <div>
                                  <Checkbox
                                    value={item.id}
                                    key={index}
                                    className={styles.radio}
                                  >
                                    {item.title}{' '}
                                  </Checkbox>
                                  {item.needInput == 1 &&
                                    answer?.optionIds?.indexOf(item.id) >
                                      -1 && (
                                      <div>
                                        <TextArea
                                          className={styles.optionInput}
                                          rows={2}
                                          placeholder="请输入..."
                                          maxLength={100}
                                          key={question?.id + ':' + item.id}
                                          defaultValue={answer?.text || ''}
                                          onBlur={(b) => {
                                            draft();
                                          }}
                                          onChange={(value) => {
                                            answer!.text = value;
                                          }}
                                        />
                                      </div>
                                    )}
                                </div>
                              </div>
                              <div
                                className={styles.dragHandler}
                                hidden={
                                  question?.needSort != 1 ||
                                  answer?.optionIds == null ||
                                  answer?.optionIds?.indexOf(item.id) < 0
                                }
                              >
                                <UnorderedListOutlined />
                              </div>
                            </div>
                          )}
                        </Draggable>
                      );
                    })}
                  </div>
                )}
              </Droppable>
            </DragDropContext>
          </Space>
        </Checkbox.Group>
      </>
    );
  };

  const rateQuestion = (question?: API.Question, answer?: API.Answer) => {
    return (
      <>
        {' '}
        {[...new Array(question?.score)].map((item, index) => {
          return (
            <div
              key={index}
              className={
                index + 1 == answer?.score ? styles.rateSelected : styles.rate
              }
              onClick={() => {
                const copy = [...(answerList || [])];
                copy![currentIndex] = {
                  questionId: answer?.questionId,
                  score: index + 1,
                };
                setAnswerList(copy);
                draft();
              }}
            >
              {index + 1}
            </div>
          );
        })}{' '}
      </>
    );
  };

  return (
    <div className={styles.container}>
      <Mask visible={showDialog} onMaskClick={() => {}}>
        <div className={styles.dialog}>
          <img src={dialogInfo?.bg} />
          <div className={styles.title}>{dialogInfo?.title}</div>
          <div className={styles.message}>{dialogInfo?.message}</div>
          <Button
            type="primary"
            shape="round"
            className={styles.submit}
            onClick={dialogInfo?.click}
          >
            {dialogInfo?.btnTxt}
          </Button>
        </div>
      </Mask>

      <Mask
        visible={showAnswerResult}
        onMaskClick={() => setShowAnswerResult(false)}
      >
        <div className={styles.answerResult}>
          {answerList?.map((item, index) => {
            let finish = isFinish(item);

            return (
              <div
                key={index}
                className={finish ? styles.itemFinish : styles.item}
                onClick={() => {
                  setCurrentIndex(index);
                  setShowAnswerResult(false);
                }}
              >
                {index + 1}
              </div>
            );
          })}
        </div>
      </Mask>
      <div className={styles.content}>
        <div className={styles.titleWrapper}>
          <img src={questionBg} className={styles.questionBg} />
          <div className={styles.title}>{paper?.title}</div>
        </div>
        <div className={styles.card}>
          <div className={styles.cardPositionDiv}>
            <div className={styles.useTimeWrapper}>
              <img src={useTime} className={styles.useTime} />
              <div className={styles.useTimeText}>{secToTime(use)}</div>
            </div>
            <div
              className={styles.questionCountWrapper}
              onClick={() => setShowAnswerResult(true)}
            >
              <img src={questionCount} className={styles.questionCount} />
              <div className={styles.questionCountText}>
                <span className={styles.current}>{currentIndex + 1}</span>/
                {paper?.questionCount}
              </div>
            </div>
          </div>

          <div className={styles.questionSeq}>题目{currentIndex + 1}</div>
          <div className={styles.questionTitleWrapper}>
            <span className={styles.type}>{getQuestionType()}</span>
            <span className={styles.title}>
              {paper?.questionList![currentIndex].title}
            </span>
          </div>
          {paper?.questionList![currentIndex].hint && (
            <div className={styles.questionHint}>
              {paper?.questionList![currentIndex].hint}
            </div>
          )}
          <div className={styles.questionContent}>{getQuestionContent()}</div>
          <Button
            type="primary"
            shape="round"
            className={styles.next}
            onClick={() => {
              if (currentIndex < paper?.questionCount! - 1) {
                setCurrentIndex(currentIndex + 1);
              } else {
                submit();
              }
            }}
          >
            {currentIndex < paper?.questionCount! - 1 ? '下一题' : '提交'}
          </Button>
          <Button
            shape="round"
            className={styles.last}
            onClick={() => setCurrentIndex(currentIndex - 1)}
            disabled={currentIndex == 0}
          >
            上一题
          </Button>
        </div>
      </div>
    </div>
  );
};
export default Question;
