<template>
    <view ref="questionEl" class="mx-question-content flex flex-col gap-40 text-content">
        <view v-html="titleWithSeq"/>
        <view class="mx-question-content-opt" :class="{'pl-30': deep>0}">
            <template v-if="question.options?.length">
                <slot name="options" v-bind="{options: optionsWithCode, deep, disabled}">
                    <component :is="optGroupComponent" :modelValue="modelValue" :disabled="disabled" placement="column"
                               :class="groupClass" @change="emits('update:modelValue', $event)">
                        <component :is="optComponent" v-for="op in optionsWithCode" :name="op.code"
                                   :class="calcOptionClass(op)">
                            <view v-html="formatOption(op.option)" :class="textClass"/>
                        </component>
                    </component>
                </slot>
            </template>
            <template v-if="question.subQuestions?.length">
                <mx-question-content v-for="sub in question.subQuestions" :question="sub" :deep="deep+1"
                                     :disabled="disabled">
                    <template v-for="(fn, name) in $slots" #[name]="scope">
                        <slot :name="name" v-bind="scope"/>
                    </template>
                </mx-question-content>
            </template>
        </view>
        <mx-question-subjective v-if="useSubjectiveStyle" :modelValue="modelValue" :attachments="attachments"
                                :disabled="disabled" @update:modelValue="emits('update:modelValue', $event)"
                                @update:attachments="emits('update:attachments', $event)"/>
    </view>
</template>

<script setup>
import {computed, onMounted, ref, watch} from 'vue'
import {createPropDefine} from "@/utils";
import _ from 'lodash';
import UvCheckboxGroup from "@/uni_modules/uv-checkbox/components/uv-checkbox-group/uv-checkbox-group.vue";
import UvRadioGroup from "@/uni_modules/uv-radio/components/uv-radio-group/uv-radio-group.vue";
import MxQuestionPlainOptionGroup from "@/components/mx-question-content/components/mx-question-plain-option-group.vue";
import UvRadio from "@/uni_modules/uv-radio/components/uv-radio/uv-radio.vue";
import UvCheckbox from "@/uni_modules/uv-checkbox/components/uv-checkbox/uv-checkbox.vue";
import MxQuestionPlainOption from "@/components/mx-question-content/components/mx-question-plain-option.vue";
import mxConst from "@/common/mxConst";
import MxQuestionSubjective from "@/components/mx-question-content/components/mx-question-subjective.vue";
import {useMathJaxService} from "@/hooks/useMathJaxService";
import {useInjectQuestionOptionFormatter} from "@/components/mx-question-content/useQuestionOptionInjection";
import {useInjectMathJaxSwitch} from "@/components/mx-question-content/useMathJaxSwitchInjection";
import {func} from "@/uni_modules/uv-ui-tools/libs/function/test";

/*NOTE：递归调用目前没有做事件穿透，所以子题还不支持作答
NOTE: mx-question-content 支持MathJax
* */

const props = defineProps({
    question: createPropDefine({}, Object),
    deep: createPropDefine(0, Number),
    disabled: createPropDefine(false, Boolean),
    modelValue: createPropDefine('', [String, Number, Array]),
    attachments: createPropDefine([], [String, Array]),
    sysAnswer: createPropDefine('', [String, Array]),
    readonly: createPropDefine(false, Boolean)
})
const emits = defineEmits(['update:modelValue', 'update:attachments'])

const questionEl = ref(null)
const {updateMathJax} = useMathJaxService()
const {formatter, optionClass} = useInjectQuestionOptionFormatter()
const {disabled: disabledMathJax} = useInjectMathJaxSwitch()

const titleWithSeq = computed(() => {
    const {title, seq, type, questionId} = props.question
    const arr = []
    if (seq) arr.push(`(${seq})`)
    if (type) arr.push(`[${type}]`)
    if (questionId) arr.push(`[${questionId}]`)
    arr.push(title)
    return arr.join('')
})

const optionsWithCode = computed(() => {
    const {options} = props.question
    return formatter(options)
})

const useMultipleStyle = computed(() => {
    const {deep, readonly, question: {typeId}} = props
    return deep == 0 && !readonly && mxConst.question.isCheckbox(typeId)
})

const useRadioStyle = computed(() => {
    // 子题都算主观题, 学生手写作答
    const {deep, readonly, question: {typeId}} = props
    return deep == 0 && !readonly && mxConst.question.isRadio(typeId)
})

const useSubjectiveStyle = computed(() => {
    // 一级题的主观题渲染输入框
    const {deep, readonly, question: {typeId}} = props
    return deep == 0 && !readonly && !mxConst.question.isObjective(typeId)
})

const optGroupComponent = computed(() => {
    if (useRadioStyle.value) return UvRadioGroup
    if (useMultipleStyle.value) return UvCheckboxGroup
    return MxQuestionPlainOptionGroup // 为了对齐UvCheckboxGroup/UvRadioGroup
})

const optComponent = computed(() => {
    if (useRadioStyle.value) return UvRadio
    if (useMultipleStyle.value) return UvCheckbox
    return MxQuestionPlainOption // 为了对齐UvCheckbox/UvRadio
})

const groupClass = computed(() => {
    return ['gap-20']
})

const textClass = computed(() => {
    return []
})

onMounted(() => updateMathJaxIfNeeded())
watch(() => props.question, () => updateMathJaxIfNeeded())

const updateMathJaxIfNeeded = () => {
    if (disabledMathJax) return
    updateMathJax(questionEl.value?.$el)
}

const calcOptionClass = function (op) {
    const defaultClass = 'px-15 py-20 border border-solid rounded'
    const injectClass = func(optionClass) ? optionClass(props.question) : optionClass
    const classes = [injectClass === undefined ? defaultClass : injectClass]
    if (props.sysAnswer) {
        // 如果有传入标准答案，则突出显示正确错误
        if (op.code == props.modelValue || props.modelValue.includes(op.code)) {
            // classes.push('border-primary')
            if (op.code != props.sysAnswer && !props.sysAnswer.includes(op.code)) {
                // 答错了
                classes.push('bg-[#f9e6e6] text-[#571515] border-[#e6c3c3]')
            }
        }
        if (op.code == props.sysAnswer || props.sysAnswer.includes(op.code)) {
            // 正确答案
            classes.push('bg-[#e0f9e6] text-[#155724] border-[#c3e6cb]')
        }
    } else {
        classes.push('border-border')
    }
    return classes
}

const tryRandomAnswer = () => {
    if (useRadioStyle.value) {
        // 随机选1个
        const rd = _.sample(optionsWithCode.value)
        emits('update:modelValue', rd.code)
    } else if (useMultipleStyle.value) {
        // 随机选N个
        const num = _.random(1, optionsWithCode.value.length + 1)
        const rd = _.sampleSize(optionsWithCode.value, num)
        // 与原选项保持顺序并提取code
        const codes = optionsWithCode.value.filter(i => rd.includes(i)).map(i => i.code)
        emits('update:modelValue', codes)
    }
}

const formatOption = (option) => {
  // 替换 option 中可能存在的A.这样的序号
    return option.replace(/A\./g, '')
    .replace(/B\./g, '')
    .replace(/C\./g, '')
    .replace(/D\./g, '')
    .replace(/E\./g, '')
    .replace(/F\./g, '')
    .replace(/G\./g, '')
}

defineExpose({tryRandomAnswer})
</script>

<style scoped lang="scss">
.mx-question-content + .mx-question-content {
    margin-top: 40rpx;
}
</style>