import React, { useEffect, useState } from 'react';
// @ts-ignore
import { enquireScreen } from 'enquire-js';
import { history } from 'umi';
import { getPageQuery } from '@/utils/utils';
import styles from './index.less';
import { answer, detail } from '@/services/paper';
import questionCount from '../asset/ic_question_count.png';
import useTime from '../asset/ic_use_time.png';
import headerBg from '../asset/ic_paper_header.png';
import {
  QUESTION_TYPE_JUDGE,
  QUESTION_TYPE_MULTIPLE_CHOICE,
  QUESTION_TYPE_RATE,
  QUESTION_TYPE_SINGER_CHOICE,
  QUESTION_TYPE_TEXT,
} from '@/services/constants';
import {
  Button,
  Checkbox,
  Input,
  message,
  Modal,
  Radio,
  Space,
  Tooltip,
} from 'antd';
import { useModel } from '@@/plugin-model/useModel';
import login_logo from '@/pages/paper/mobile/asset/ic_login_logo.png';
import {
  LoginForm,
  ProForm,
  ProFormCaptcha,
  ProFormText,
} from '@ant-design/pro-components';
import { Toast } from 'antd-mobile/es';
import { login, sendCaptcha, sendEmailCaptcha } from '@/services/login';
import Cookies from 'js-cookie';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import { UnorderedListOutlined } from '@ant-design/icons';

const { TextArea } = Input;
let isMobile;
enquireScreen((b) => {
  isMobile = b;
});

const Detail: React.FC = () => {
  const LOGIN_TYPE_PHONE_CAPTCHA = 1;
  const LOGIN_TYPE_EMAIL_CAPTCHA = 2;

  const [paper, setPaper] = useState<API.Paper>();
  const [answerList, setAnswerList] = useState<API.Answer[]>();
  const paperId = parseInt(getPageQuery().id + '');
  const secret = getPageQuery().secret;
  const [use, setUse] = useState(0);
  const [enableAnswer, setEnableAnswer] = useState(true);
  const [isLogin, setIsLogin] = useState(true);
  const { initialState, setInitialState } = useModel('@@initialState');
  const [form] = ProForm.useForm();
  const [draftTimeOutId, setDraftTimeOutId] = useState<NodeJS.Timeout>();
  const [loginType, setLoginType] = useState(LOGIN_TYPE_PHONE_CAPTCHA);

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

  useEffect(() => {
    if (isMobile) {
      if (secret) {
        history.push(`/paper/mobile/detail?id=${paperId}&secret=${secret}`);
      } else {
        history.push(`/paper/mobile/detail?id=${paperId}`);
      }
      return;
    }

    let timerId;
    detail(paperId, secret).then((response) => {
      if (response.code == 200) {
        let current = Date.now();
        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);
        setIsLogin(true);
      } else if (response.code == 3008) {
        setIsLogin(false);
      } 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);
    };
  }, [isLogin]);

  const fetchUserInfo = async () => {
    const userInfo = await initialState?.fetchUserInfo?.();
    if (userInfo) {
      await setInitialState((s) => ({
        ...s,
        currentUser: userInfo,
      }));
    }
  };

  const handleLogin = async (values: API.LoginParams) => {
    try {
      const response = await login({ ...values, type: loginType });
      if (response.code === 200) {
        await setInitialState((s) => ({
          ...s,
          currentUser: response.data,
        }));
        Cookies.set('ut', response!.data!.token!);
        await fetchUserInfo();
        setIsLogin(true);
      } else {
        message.error(response.message);
      }
    } catch (error) {
      message.error('登录失败，请重试');
    }
  };

  const getRateHint = (question?: API.Question, index?: number) => {
    if (question?.score != 5) {
      return '';
    }
    if (index == 0) {
      return '从不或者几乎没有';
    } else if (index == 1) {
      return '很少';
    } else if (index == 2) {
      return '有时';
    } else if (index == 3) {
      return '经常';
    } else if (index == 4) {
      return '总是或通常';
    } else {
      return '';
    }
  };

  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 = () => {
    if (draftTimeOutId) {
      clearTimeout(draftTimeOutId);
    }

    for (let i = 0; i < answerList?.length!; i++) {
      let finish = isFinish(answerList![i]);
      if (!finish) {
        message.error(`第${i + 1}题未完成作答,请继续作答！`);
        return;
      }
    }

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

    answer(submitParam)
      .then((response) => {
        if (response.code == 200) {
          history.push('/paper/result?type=success');
        } else {
          message.error('答题未完成,' + response.message);
        }
      })
      .catch(() => {
        message.error('答题未完成, 未知异常，请稍后再试');
      });
  };

  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 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 getQuestionType = (question?: API.Question) => {
    const type = question?.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 getQuestionContent = (
    index: number,
    question?: API.Question,
    answer?: API.Answer,
  ) => {
    const type = question?.type;
    if (type == QUESTION_TYPE_RATE) {
      return rateQuestion(index, question, answer);
    } else if (type == QUESTION_TYPE_SINGER_CHOICE) {
      return singerChoiceQuestion(index, question, answer);
    } else if (type == QUESTION_TYPE_MULTIPLE_CHOICE) {
      return multipleChoiceQuestion(index, question, answer);
    } else if (type == QUESTION_TYPE_JUDGE) {
      return judgeQuestion(index, question, answer);
    } else if (type == QUESTION_TYPE_TEXT) {
      return textQuestion(index, question, answer);
    } else {
      return <></>;
    }
  };

  const textQuestion = (
    questionIndex: number,
    question?: API.Question,
    answer?: API.Answer,
  ) => {
    return (
      <>
        <TextArea
          className={styles.textArea}
          rows={4}
          placeholder="请输入..."
          maxLength={100}
          defaultValue={answer?.text || ''}
          key={question?.id}
          onBlur={(b) => {
            draft();
          }}
          onChange={(e) => {
            answer!.text = e.target.value;
          }}
        />
      </>
    );
  };

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

            copy![questionIndex] = {
              questionId: answer?.questionId,
              optionId: e.target.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}>
                    {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={(e) => {
                          answer!.text = e.target.value;
                        }}
                      />
                    </div>
                  )}
                </div>
              );
            })}
          </Space>
        </Radio.Group>
      </>
    );
  };

  const judgeQuestion = (
    questionIndex: number,
    question?: API.Question,
    answer?: API.Answer,
  ) => {
    return (
      <>
        <Radio.Group
          key={question?.id}
          onChange={(e) => {
            const copy = [...(answerList || [])];
            copy![questionIndex] = {
              questionId: answer?.questionId,
              judge: e.target.value,
            };
            setAnswerList(copy);
            draft();
          }}
          value={answer?.judge}
        >
          <Space direction="vertical">
            <Radio value={1} className={styles.radio}>
              正确
            </Radio>
            <Radio value={2}>错误</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 = (
    questionIndex: number,
    question?: API.Question,
    answer?: API.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![questionIndex] = {
              questionId: answer?.questionId,
              optionIds: checkedValues,
              hasInput: hasInput,
            };

            setAnswerList(copy);
            draft();

            let newOptions = sortQuestionOptionList(
              question?.optionList,
              checkedValues,
            );

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

            // provided.draggableProps.updateSingleDrag({ ...provided, destination: null });

            setPaper((prevState) => ({
              ...prevState,
              questionList: updatedQuestionList,
            }));
          }}
          value={answer?.optionIds}
        >
          <Space direction="vertical">
            <DragDropContext
              onDragEnd={(result, provider) => {
                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[questionIndex].optionIds,
                  newOptions.map((obj) => obj.id),
                );
                const copy = [...(answerList || [])];

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

                if (question?.needSort == 1) {
                  newOptions = sortQuestionOptionList(
                    question?.optionList,
                    answerList[questionIndex].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}>
                                <Checkbox value={item.id} key={index}>
                                  {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={(e) => {
                                          answer!.text = e.target.value;
                                        }}
                                      />
                                    </div>
                                  )}
                              </div>
                              <div
                                className={styles.dragHandler}
                                hidden={
                                  question?.needSort != 1 ||
                                  answer?.optionIds == null ||
                                  answer?.optionIds?.indexOf(item.id) < 0
                                }
                              >
                                <UnorderedListOutlined />
                              </div>
                            </div>
                          )}
                        </Draggable>
                      );
                    })}
                    {provided.placeholder}
                  </div>
                )}
              </Droppable>
            </DragDropContext>
          </Space>
        </Checkbox.Group>
      </>
    );
  };

  const rateQuestion = (
    questionIndex: number,
    question?: API.Question,
    answer?: API.Answer,
  ) => {
    return (
      <>
        {' '}
        {[...new Array(question?.score)].map((item, index) => {
          return (
            <Tooltip
              placement="bottom"
              title={getRateHint(question, index)}
              color={'#3D8BF5'}
            >
              <div
                key={index}
                className={
                  index + 1 == answer?.score ? styles.rateSelected : styles.rate
                }
                onClick={() => {
                  setAnswerList((prestate) => {
                    const copy = [...(prestate || [])];
                    copy![questionIndex] = {
                      questionId: answer?.questionId,
                      score: index + 1,
                    };
                    return copy;
                  });
                  draft();
                }}
              >
                {index + 1}
              </div>
            </Tooltip>
          );
        })}{' '}
      </>
    );
  };

  return (
    <div className={styles.container}>
      <div className={styles.content}>
        <img src={headerBg} className={styles.header} />
        {isLogin && (
          <div className={styles.card}>
            <div className={styles.title}>{paper?.title}</div>
            <div className={styles.count}>
              <img className={styles.icon} src={useTime} />
              <span className={styles.hint}>答题用时:</span>
              <span className={styles.text}>{secToTime(use)}</span>
              <img className={styles.icon} src={questionCount} />
              <span className={styles.hint}>题目总数:</span>
              <span className={styles.text}>{paper?.questionCount}道</span>
            </div>
            <div className={styles.desc}>{paper?.desc}</div>
            {paper?.questionList?.map((item, index) => {
              return (
                <div className={styles.question}>
                  <div className={styles.questionTitle}>
                    {item.title}{' '}
                    <span className={styles.type}>{getQuestionType(item)}</span>
                  </div>

                  {item.hint && (
                    <div className={styles.questionHint}>{item.hint}</div>
                  )}

                  <div className={styles.questionContent}>
                    {getQuestionContent(index, item, answerList![index])}
                  </div>
                </div>
              );
            })}

            <Button
              type="primary"
              shape="round"
              className={styles.submit}
              disabled={!enableAnswer}
              onClick={() => {
                submit();
              }}
            >
              {enableAnswer ? '提交' : '已完成作答'}
            </Button>
          </div>
        )}
        {!isLogin && <div className={styles.card}></div>}
        <Modal
          centered
          visible={!isLogin}
          width={400}
          footer={null}
          closeIcon={<></>}
        >
          <div className={styles.loginWrapper}>
            <div className={styles.logoWrapper}>
              <img src={login_logo} className={styles.logo} />
            </div>
            <div className={styles.title}>欢迎登录</div>
            <LoginForm
              form={form}
              initialValues={{}}
              actions={[]}
              onFinish={async (values) => {
                await handleLogin({ ...values, sourceId: paperId });
              }}
              submitter={{
                render: (props, doms) => {
                  return [
                    <Button
                      type="primary"
                      shape="round"
                      size={'large'}
                      className={styles.submit}
                      onClick={() => props.form?.submit?.()}
                    >
                      登录
                    </Button>,
                  ];
                },
              }}
            >
              <>
                {loginType == LOGIN_TYPE_PHONE_CAPTCHA && (
                  <ProFormText
                    className={styles.formItem}
                    fieldProps={{
                      size: 'large',
                      className: styles.phone,
                    }}
                    name="phone"
                    placeholder="手机号"
                    rules={[
                      {
                        required: true,
                        message: '请输入手机号！',
                      },
                      {
                        pattern: /^1\d{10}$/,
                        message: '手机号格式错误！',
                      },
                    ]}
                  />
                )}
                {loginType == LOGIN_TYPE_EMAIL_CAPTCHA && (
                  <ProFormText
                    className={styles.formItem}
                    fieldProps={{
                      size: 'large',
                      className: styles.phone,
                    }}
                    name="email"
                    placeholder="邮箱"
                    rules={[
                      {
                        required: true,
                        message: '请输入邮箱！',
                      },
                      {
                        pattern:
                          /^[a-zA-Z0-9]+([-_.][A-Za-zd]+)*@([a-zA-Z0-9]+[-.])+[A-Za-zd]{2,5}$/,
                        message: '邮箱格式错误！',
                      },
                    ]}
                  />
                )}

                <ProFormCaptcha
                  className={styles.captchaItem}
                  fieldProps={{
                    size: 'large',
                    className: styles.captcha,
                  }}
                  captchaProps={{
                    size: 'large',
                    className: styles.getCaptcha,
                  }}
                  placeholder="请输入验证码"
                  captchaTextRender={(timing, count) => {
                    if (timing) {
                      return `${count} 获取验证码`;
                    }
                    return '获取验证码';
                  }}
                  name="captcha"
                  rules={[
                    {
                      required: true,
                      message: '请输入验证码！',
                    },
                    {
                      min: 4,
                    },
                    {
                      max: 6,
                    },
                  ]}
                  onGetCaptcha={async () => {
                    if (loginType == LOGIN_TYPE_PHONE_CAPTCHA) {
                      const phone = form.getFieldValue('phone');
                      if (!phone) {
                        Toast.show({
                          icon: 'fail',
                          content: '请先输入手机号',
                        });
                        throw new Error('请先输入手机号');
                      }
                      const result = await sendCaptcha({
                        phone,
                      });
                      console.log(result);
                      if (result === false) {
                        return;
                      }
                    } else if (loginType == LOGIN_TYPE_EMAIL_CAPTCHA) {
                      const email = form.getFieldValue('email');
                      if (!email) {
                        Toast.show({
                          icon: 'fail',
                          content: '请先输入邮箱',
                        });
                        throw new Error('请先输入邮箱');
                      }
                      const result = await sendEmailCaptcha({
                        email,
                      });
                      console.log(result);
                      if (result === false) {
                        return;
                      }
                    }
                  }}
                />
              </>
              <div
                style={{
                  marginBottom: 24,
                }}
              ></div>
              {loginType == LOGIN_TYPE_PHONE_CAPTCHA && (
                <div
                  className={styles.changeLogin}
                  onClick={() => {
                    setLoginType(LOGIN_TYPE_EMAIL_CAPTCHA);
                  }}
                >
                  切换邮箱登录
                </div>
              )}

              {loginType == LOGIN_TYPE_EMAIL_CAPTCHA && (
                <div
                  className={styles.changeLogin}
                  onClick={() => {
                    setLoginType(LOGIN_TYPE_PHONE_CAPTCHA);
                  }}
                >
                  切换手机登录
                </div>
              )}
            </LoginForm>
          </div>
        </Modal>
      </div>
    </div>
  );
};
export default Detail;
