import {ref, watch, computed, nextTick} from 'vue'
import {createEventHook, injectLocal, provideLocal} from "@vueuse/core";
import {useProvidePaperService} from "@/components/mx-paper/usePaperInjection";
import {numberToChinese} from "@/utils";
import {useProvideQuestionOptionFormatter} from "@/components/mx-question-content/useQuestionOptionInjection";
import {useProvideMathJaxSwitch} from "@/components/mx-question-content/useMathJaxSwitchInjection";
import {toast} from "@/uni_modules/uv-ui-tools/libs/function";
import {empty, func} from "@/uni_modules/uv-ui-tools/libs/function/test";
import mxConst from "@/common/mxConst";
import {fnPlaceholder} from "@/utils/uni-helper";

const key = Symbol('STEP_PAPER_SERVICE')

export const useProvideStepPaper = (name, answerFormatter = (v) => v) => {

    const title = ref(name)
    const welcomeShow = ref(true)
    const resultShow = ref(false)
    const step = ref(0)
    const steps = ref([])
    const stepQuestionContainer = ref(new Map())
    const answerData = ref(new Map())
    const beginEvent = createEventHook()
    const stepStartEvent = createEventHook()
    const finishEvent = createEventHook()
    const currentStep = computed(() => steps.value[step.value] || {})
    const currentStepQuestions = computed(() => stepQuestionContainer.value.get(currentStep.value.id))

    const paperData = computed(() => ({
        name: name,
        allowAnswer: true,
        allowScore: false,
        questions: currentStepQuestions.value
    }))

    const overridePaperService = {
        commitQuestion: async (commits) => {
            // step paper只涉及本地提交
            // 没有更改doChunk，业务上还是可以依靠它来驱动
            commits.forEach(item => {
                answerData.value.set(item.questionId, item.answer)
            })
        },
        commitPaper: async () => {
            // step paper表示往前走一步
            // 此进是强制走步，此时将触发finish
            step.value += 1
        }
    }

    // 只重写了step需要影响的部分
    const paperService = useProvidePaperService(paperData, overridePaperService)

    const optionFormatter = (options) => options.map(o => ({code: o.id, option: o.label}))
    const optionClass = (q) => mxConst.question.isRadio(q.typeId) ? 'pt-10' : ''
    useProvideQuestionOptionFormatter(optionFormatter, optionClass)
    useProvideMathJaxSwitch(true) // 明确此类测评没有包含任何公式转换

    const hasNextStep = computed(() => step.value < steps.value.length - 1)
    const hasPrevStep = computed(() => step.value > 0)
    const tryGoNextStep = () => {
        if (!hasNextStep.value) return toast('已经是最后一部分了')
        step.value += 1
        paperService.index.value = 0
    }
    const tryGoPrevStep = () => {
        if (!hasPrevStep.value) return toast('已经是第一题了')
        step.value -= 1
        nextTick().then(() => {
            // 需要等待题加载完毕，再重置题的位置
            paperService.index.value = paperService.questions.value.length - 1
        })
    }

    watch([welcomeShow, resultShow], async () => {
        if (!welcomeShow.value && !resultShow.value) {
            await beginEvent.trigger()
        }
    })
    watch(currentStep, async (step) => {
        if (!empty(step)) {
            await stepStartEvent.trigger(step.id)
        }
    })
    watch(() => step.value >= steps.value.length, async (complete) => {
        if (complete) {
            // 转成API要求的标准格式
            const details = []
            for (const [key, value] of answerData.value) {
                details.push({
                    questionId: key,
                    answer: answerFormatter(value)
                })
            }
            await finishEvent.trigger({details})
            resultShow.value = true
        }
    })

    const options = {
        ...paperService,
        title,
        welcomeShow,
        resultShow,
        step,
        steps,
        currentStep,
        stepQuestionContainer,
        hasPrevStep,
        hasNextStep,
        tryGoPrevStep,
        tryGoNextStep,
        paperData,
        answerData,
        onBegin: beginEvent.on,
        onStepStart: stepStartEvent.on,
        onFinish: finishEvent.on
    }

    provideLocal(key, options)
    return options
}

export const useInjectStepPaper = () => {
    return injectLocal(key)
}

export const stepFormatter = (steps) => {
    steps.forEach((s, i) => s.name = numberToChinese(i + 1))
    return steps
}

export const questionsFormatter = (questions, typeId, options = null) => {
    questions.forEach((q, i) => {
        const op = func(options) ? options(q) : options

        q.questionId = q.questionId || q.id
        q.typeId = typeId
        q.seq = i + 1
        q.options = op || q.options
    })
    return questions
}