import { numberToChinese, maxNum } from "@/plugins/utils";
import {
  getModel as createFillQuestion,
  getFullModel as getFillQuesitonElements,
} from "../../../../card/elements/fill-question/model";
import {
  getModel as createFillLine,
  getFullModel as getFillLineElements,
} from "../../../../card/elements/fill-line/model";
import {
  getModel as createExplain,
  getFullModel as getExplainElements,
} from "../../../../card/elements/explain/model";

const COMMON_QUESTION_TYPES = [
  "SINGLE_ANSWER_QUESTION",
  "MULTIPLE_ANSWER_QUESTION",
  "BOOL_ANSWER_QUESTION",
  "FILL_BLANK_QUESTION",
  "TEXT_ANSWER_QUESTION",
];

const structTypeToCardElementType = {
  SINGLE_ANSWER_QUESTION: "FILL_QUESTION",
  MULTIPLE_ANSWER_QUESTION: "FILL_QUESTION",
  BOOL_ANSWER_QUESTION: "FILL_QUESTION",
  FILL_BLANK_QUESTION: "FILL_LINE",
  TEXT_ANSWER_QUESTION: "EXPLAIN",
};

const elementModel = {
  FILL_QUESTION: (presetData) => {
    const model = createFillQuestion(presetData);
    return getFillQuesitonElements(model, {
      pageSize: presetData.pageSize,
      columnNumber: presetData.columnNumber,
    });
  },
  FILL_LINE: (presetData) => {
    const model = createFillLine(presetData);
    return getFillLineElements(model);
  },
  EXPLAIN: (presetData) => {
    const model = createExplain(presetData);
    return getExplainElements(model);
  },
};

function parsePaperStruct(paperJson) {
  let structList = [];
  paperJson.paperDetails.forEach((detail) => {
    const commonQuestions = detail.paperDetailUnits.filter((q) =>
      COMMON_QUESTION_TYPES.includes(q.questionType)
    );
    if (commonQuestions.length) {
      const commonStructList = getCommonQuestionStructList(
        detail,
        commonQuestions,
        true,
        0
      );
      structList.push(...commonStructList);
    }

    const nestedQuestions = detail.paperDetailUnits.filter(
      (q) => !COMMON_QUESTION_TYPES.includes(q.questionType)
    );
    if (nestedQuestions.length) {
      const nestedStructList = getNestedQuestionStructList(
        detail,
        nestedQuestions
      );
      structList.push(...nestedStructList);
    }
  });

  structList.sort((a, b) => a.sortNo - b.sortNo);
  console.log(structList);
  return structList;
}

function getCommonQuestionStructList(
  detail,
  questions,
  isCommon,
  nestedQNo = 0
) {
  let structList = [];
  let structs = {};
  const qTypeNum = isCommon ? 1 : 2;
  questions.forEach((question) => {
    if (!structs[question.questionType]) structs[question.questionType] = [];
    structs[question.questionType].push(question);
  });
  Object.keys(structs).forEach((structType) => {
    const typeNo = COMMON_QUESTION_TYPES.indexOf(structType) + 1;
    const questions = parseCommonTypeQuestions(structType, structs[structType]);

    structList.push({
      detailName: detail.name,
      detailNo: detail.number,
      structType,
      isCommon,
      nestedQNo,
      sortNo:
        typeNo * 10000 + detail.number * 1000 + qTypeNum * 100 + nestedQNo,
      questions,
    });
  });
  return structList;
}

function getNestedQuestionStructList(detail, questions) {
  let structList = [];
  questions.forEach((question) => {
    const qStructList = getCommonQuestionStructList(
      detail,
      question.question.subQuestions.map((q) => {
        return {
          number: q.subNumber,
          questionType: q.questionType,
          question: q,
        };
      }),
      false,
      question.number
    );
    structList.push(...qStructList);
  });
  return structList;
}

function parseCommonTypeQuestions(structType, dataList) {
  const choiceQs = [
    "SINGLE_ANSWER_QUESTION",
    "MULTIPLE_ANSWER_QUESTION",
    "BOOL_ANSWER_QUESTION",
  ];
  let questions = [];
  if (choiceQs.includes(structType)) {
    questions = dataList.map((item) => {
      return {
        questionNo: item.number,
        optionCount:
          structType === "BOOL_ANSWER_QUESTION"
            ? 2
            : item.question.quesOptions.length,
      };
    });
  } else if (structType === "FILL_BLANK_QUESTION") {
    questions = dataList.map((item) => {
      return {
        questionNo: item.number,
        fillCount: getFillBackClozeCount(item.question.quesBody),
      };
    });
  } else {
    questions = dataList.map((item) => item.number);
  }
  return questions;
}

export function getFillBackClozeCount(questionBodyContent) {
  let questionBody = null;
  let num = 0;
  try {
    questionBody = JSON.parse(questionBodyContent);
    questionBody.sections.forEach((section) => {
      section.blocks.forEach((block) => {
        if (block.type === "cloze") num++;
      });
    });
  } catch (error) {
    num = 1;
  }

  return num;
}

function parseCommonQuestionPresetData(struct) {
  const choiceQs = [
    "SINGLE_ANSWER_QUESTION",
    "MULTIPLE_ANSWER_QUESTION",
    "BOOL_ANSWER_QUESTION",
  ];
  const { questions, structType } = struct;
  let info = {};
  if (choiceQs.includes(structType)) {
    const optionCount = maxNum(questions.map((q) => q.optionCount));
    const maxQuestionNo = maxNum(questions.map((q) => q.questionNo));
    info = {
      questionsCount: questions.length,
      optionCount,
      startNumber: maxQuestionNo - questions.length + 1,
    };
  } else if (structType === "FILL_BLANK_QUESTION") {
    const optionCount = maxNum(questions.map((q) => q.fillCount));
    const maxQuestionNo = maxNum(questions.map((q) => q.questionNo));
    info = {
      questionLineNums: questions.map((item) => {
        return {
          no: item.questionNo,
          count: item.fillCount,
        };
      }),
      questionLineType: "custom",
      questionsCount: questions.length,
      optionCount,
      startNumber: maxQuestionNo - questions.length + 1,
    };
  } else {
    const maxQuestionNo = maxNum(questions);
    info = {
      questionsCount: questions.length,
      startNumber: maxQuestionNo - questions.length + 1,
    };
  }
  return info;
}

export function buildCardElements(structList, elementTypePreSetInfo = {}) {
  let cardElements = [];
  structList.forEach((struct) => {
    const detailChineseNumber = numberToChinese(struct.detailNo);
    let topicName =
      struct.isCommon || (!struct.isCommon && struct.isOnlyOneNested)
        ? `${detailChineseNumber}、${struct.detailName}`
        : `${detailChineseNumber}（${struct.nestedQNo}）`;
    const topicNo = struct.detailNo;
    const modelType = structTypeToCardElementType[struct.structType];
    const elementTypePreSet = elementTypePreSetInfo[modelType] || {};

    if (!struct.isCommon && struct.structType === "TEXT_ANSWER_QUESTION") {
      struct.questions.forEach((qno) => {
        const presetData = {
          ...elementTypePreSet,
          topicName: `${topicName}、${qno}`,
          topicNo,
          questionsCount: 1,
          startNumber: qno,
        };

        const elements = elementModel[modelType](presetData);
        cardElements.push(...elements);
      });
      return;
    }

    const presetData = {
      topicName,
      topicNo,
      ...elementTypePreSet,
      ...parseCommonQuestionPresetData(struct),
    };
    if (struct.structType === "MULTIPLE_ANSWER_QUESTION")
      presetData.isMultiply = true;
    if (struct.structType === "BOOL_ANSWER_QUESTION")
      presetData.isBoolean = true;

    const elements = elementModel[modelType](presetData);
    cardElements.push(...elements);
  });

  return cardElements;
}

export function buildPaperCard(paperJson) {
  const structList = parsePaperStruct(paperJson);
  const cardElements = buildCardElements(structList);
  // console.log(cardElements);
  return cardElements;
}

// const paperStruct = {
//   paperName: "",
//   structList: [
//     {
//       detailName: "",
//       detailNo: 1,
//       structType: 1,
//       questions: [
//         { questionNo: "1", optionCount: 4 },
//         { questionNo: "2", optionCount: 4 },
//       ],
//     },
//     {
//       detailName: "",
//       detailNo: 1,
//       structType: 2,
//       questions: [
//         { questionNo: "3", optionCount: 4 },
//         { questionNo: "4", optionCount: 4 },
//       ],
//     },
//     {
//       detailName: "",
//       detailNo: 1,
//       structType: 3,
//       questions: [
//         { questionNo: "5", optionCount: 2 },
//         { questionNo: "6", optionCount: 2 },
//       ],
//     },
//     {
//       detailName: "",
//       detailNo: 1,
//       structType: 4,
//       questions: [
//         { questionNo: "7", fillCount: 1 },
//         { questionNo: "8", fillCount: 2 },
//       ],
//     },
//     {
//       detailName: "",
//       detailNo: 1,
//       structType: 5,
//       questions: ["11", "12"],
//     },
//   ],
// };
