<template>
  <n-drawer v-model:show="drawer" :width="800" destroy-on-close>
    <n-drawer-content :native-scrollbar="false" :body-content-style="{ padding: '0' }">
      <template #header>
        <div class="flex items-center justify-between w-full">
          <div class="flex items-center">
            <span class="text-16px font-bold text-[#333]">编辑信息</span>
          </div>
          <div>
            <n-button
              type="primary"
              round
              :loading="submitLoading"
              :disabled="submitLoading || importImgLoading"
              @click="handleSubmit"
            >
              <template #icon>
                <icon-solar-cloud-upload-linear />
              </template>
              提交
            </n-button>
          </div>
        </div>
      </template>

      <div v-if="pageLoad.loadState === false" class="p-4">
        <n-form
          ref="formRef"
          :model="formData"
          :rules="rules"
          label-placement="left"
          label-width="80px"
          require-mark-placement="right-hanging"
        >
          <div class="mb-4">
            <h3 class="text-16px font-bold mb-4 border-l-4 border-primary pl-2">基本信息</h3>
            <div class="grid grid-cols-2 gap-4">
              <n-form-item label="学科" path="subjectId">
                <n-select
                  v-model:value="formData.subjectId"
                  :options="subjectList"
                  label-field="label"
                  value-field="value"
                  placeholder="请选择学科"
                  @update:value="subjectIdChange"
                />
              </n-form-item>

              <n-form-item label="知识点" path="knowledgepointIds">
                <n-tree-select
                  v-model:value="formData.knowledgepointIds"
                  :disabled="!formData.subjectId || formData.subjectId < 0"
                  :options="knowledgePointList"
                  key-field="id"
                  label-field="name"
                  children-field="childs"
                  multiple
                  cascade
                  checkable
                  placeholder="请选择知识点"
                />
              </n-form-item>

              <n-form-item label="题型" path="type">
                <n-select
                  v-model:value="formData.type"
                  :options="topicTypeList"
                  label-field="label"
                  value-field="value"
                  placeholder="请选择题型"
                />
              </n-form-item>

              <n-form-item v-if="[1, 2].includes(formData.type || 0)" label="可选项" path="options">
                <n-select
                  v-model:value="formData.options"
                  multiple
                  :options="answerOptionsList"
                  label-field="label"
                  value-field="value"
                  placeholder="请选择可选项"
                />
              </n-form-item>

              <n-form-item v-if="formData.type === 1" label="正确答案" path="singleChoiceAnswer">
                <n-select
                  v-model:value="formData.singleChoiceAnswer"
                  :options="optionsList"
                  label-field="label"
                  value-field="value"
                  placeholder="请选择正确答案"
                />
              </n-form-item>

              <n-form-item v-if="formData.type === 2" label="正确答案" path="multiChoiceAnswer">
                <n-select
                  v-model:value="formData.multiChoiceAnswer"
                  multiple
                  :options="optionsList"
                  label-field="label"
                  value-field="value"
                  placeholder="请选择正确答案"
                />
              </n-form-item>

              <n-form-item v-if="formData.type === 3" label="正确答案" path="trueOrFalseAnswer">
                <n-radio-group v-model:value="formData.trueOrFalseAnswer">
                  <n-radio :value="1">正确</n-radio>
                  <n-radio :value="0">错误</n-radio>
                </n-radio-group>
              </n-form-item>

              <n-form-item label="题号" path="no">
                <n-input v-model:value="formData.no" placeholder="请输入题号" />
              </n-form-item>

              <n-form-item label="分数" path="score">
                <n-input-number v-model:value="formData.score" :precision="1" placeholder="请输入分数" class="w-full" />
              </n-form-item>

              <n-form-item label="答题时间" path="answerTime">
                <n-input-number v-model:value="formData.answerTime" :precision="0" placeholder="请输入答题时间" class="w-full">
                  <template #suffix>秒</template>
                </n-input-number>
              </n-form-item>

              <n-form-item label="讲解视频" path="videourl">
                <rest-upload
                  v-model="videoInfo"
                  :accept="['.mp4']"
                  :custom-keys="{ bindFileUrlKey: 'url', bindPosterUrlKey: 'poster' }"
                  :width="160"
                  :height="90"
                  hint="上传讲解视频"
                />
              </n-form-item>
            </div>
          </div>

          <n-divider />

          <div class="mb-4">
            <h3 class="text-16px font-bold mb-4 border-l-4 border-primary pl-2">题目</h3>
            <div class="mb-4">
              <div class="text-14px font-bold mb-2">题目</div>
              <n-form-item label="" path="question" :show-label="false">
                <rest-basic-editor v-model="formData.question" />
              </n-form-item>
            </div>

            <div v-if="![1, 2, 3].includes(formData.type || 0)" class="mb-4">
              <div class="text-14px font-bold mb-2">答案</div>
              <n-form-item label="" path="textAnswer" :show-label="false">
                <rest-basic-editor v-model="formData.textAnswer" />
              </n-form-item>
            </div>

            <div class="mb-4">
              <div class="text-14px font-bold mb-2">解析</div>
              <n-form-item label="" path="analysis" :show-label="false">
                <rest-basic-editor v-model="formData.analysis" />
              </n-form-item>
            </div>
          </div>
        </n-form>
      </div>
      <div v-else-if="pageLoad.loadState === 'err'" class="flex justify-center items-center h-full">
        <n-empty :description="pageLoad.description">
          <template #extra>
            <n-button @click="getBaseDataAxios">重试</n-button>
          </template>
        </n-empty>
      </div>
      <div v-else class="flex justify-center items-center h-full">
        <n-spin size="large" />
      </div>
    </n-drawer-content>
  </n-drawer>
</template>

<script setup lang="ts">
import { ref, shallowRef, shallowReactive, watch, computed, nextTick } from 'vue';
import { useMessage } from 'naive-ui';
import type { FormInst, FormRules } from 'naive-ui';
import RestBasicEditor from '@/components/common/rest-basic-editor/rest-basic-editor.vue';
import RestUpload from '@/components/common/rest-upload/rest-upload.vue';
import {
  type BookPageQuestion,
  type BookPageQuestionUpdateInput,
  editQuestionInfoAxios,
  getQuestionInfoAxios,
  getQuestionBankNavAxios,
  getKnowledgePointDetailsAxios
} from '@/service/api/book';
import { fileToBase64, getFirstFrameOfVideo } from '@/utils/file';
import { myStrToJson } from '@/utils/data';
import { topicTypeList } from '@/views/template/template-detail/def-data';
import type { KeyValue, TopicInfo } from '@/views/template/template-detail/types';

// Mock data for answerOptionsList since it was imported from aa-util/def-data
const answerOptionsList = [
  { label: 'A', value: 'A' },
  { label: 'B', value: 'B' },
  { label: 'C', value: 'C' },
  { label: 'D', value: 'D' },
  { label: 'E', value: 'E' },
  { label: 'F', value: 'F' },
  { label: 'G', value: 'G' },
];

interface KnowledgePointOutput {
  id: number;
  name: string;
  childs?: KnowledgePointOutput[];
}

type FormData = Omit<BookPageQuestionUpdateInput, 'analysisUrl' | 'answer' | 'answerUrl' | 'knowledgepointIds' | 'options' | 'questionUrl'> & {
  knowledgepointIds: number[];
  singleChoiceAnswer: string;
  multiChoiceAnswer: string[];
  trueOrFalseAnswer?: 0 | 1;
  textAnswer: string;
  options: string[];
};

const message = useMessage();
const drawer = ref(false);
const submitLoading = ref(false);
const importImgLoading = ref(false);
const formRef = ref<FormInst | null>(null);

let topicInfo: TopicInfo | undefined = undefined;

const videoInfo = ref<{ url: string; poster: string } | undefined>(undefined);
const subjectList = shallowRef<KeyValue[]>([]);
const pageLoad = shallowReactive<{ loadState: boolean | 'err'; description: string }>({ loadState: true, description: '' });
const optionsList = ref<typeof answerOptionsList>([]);
const knowledgePointList = shallowRef<KnowledgePointOutput[]>([]);

const formData = ref<FormData>({
  bookId: -1,
  bookPageId: -1,
  id: -1,
  no: undefined,
  question: undefined,
  score: undefined,
  analysis: undefined,
  type: 1,
  subjectId: undefined,
  knowledgepointIds: [],
  options: [],
  singleChoiceAnswer: '',
  multiChoiceAnswer: [],
  trueOrFalseAnswer: undefined,
  textAnswer: '',
  answerTime: undefined,
  videourl: '',
});

watch(
  () => videoInfo.value,
  (val) => {
    if (val) {
      formData.value.videourl = val.url;
    }
  }
);

watch(
  () => formData.value.type,
  () => {
    formData.value.singleChoiceAnswer = '';
    formData.value.multiChoiceAnswer = [];
    formData.value.trueOrFalseAnswer = undefined;
    formData.value.textAnswer = '';
  }
);

watch(
  () => formData.value.options,
  (val) => {
    optionsList.value = answerOptionsList.filter((item) => val.includes(item.value));
    formData.value.singleChoiceAnswer = '';
    formData.value.multiChoiceAnswer = [];
    formData.value.trueOrFalseAnswer = undefined;
    formData.value.textAnswer = '';
  },
  { deep: true }
);

const rules = computed<FormRules>(() => {
  const _rules: FormRules = {
    subjectId: [{ required: true, type: 'number', message: '请选择学科', trigger: ['blur', 'change'] }],
    knowledgepointIds: [{ required: true, type: 'array', message: '知识点不能为空', trigger: ['blur', 'change'] }],
    type: [{ required: true, type: 'number', message: '题型不能为空', trigger: ['blur', 'change'] }],
    no: [{ required: true, type: 'string', message: '题号不能为空', trigger: ['blur', 'change'] }],
    score: [{ required: true, type: 'number', message: '分数不能为空', trigger: ['blur', 'change'] }],
    answerTime: [{ required: true, type: 'number', message: '答题时间不能为空', trigger: ['blur', 'change'] }],
  };

  if ([1, 2].includes(formData.value.type || 0)) {
    _rules.options = [
      { required: true, type: 'array', message: '答案选项不能为空', trigger: ['blur', 'change'] },
      // min length validation in naive ui requires custom validator usually, but array min length works in async-validator
      { type: 'array', min: 2, message: '最少需要2个答案选项', trigger: ['blur', 'change'] },
    ];
  }

  if (formData.value.type === 1) {
    _rules.singleChoiceAnswer = [{ required: true, type: 'string', message: '请选择单选题答案', trigger: ['blur', 'change'] }];
  } else if (formData.value.type === 2) {
    _rules.multiChoiceAnswer = [{ required: true, type: 'array', min: 1, message: '请选择多选题答案', trigger: ['blur', 'change'] }];
  } else if (formData.value.type === 3) {
    _rules.trueOrFalseAnswer = [
      { required: true, type: 'number', message: '请选择判断题答案', trigger: ['blur', 'change'] },
    ];
  } else if (![1, 2, 3].includes(formData.value.type || 0)) {
    _rules.textAnswer = [{ required: true, type: 'string', message: '请输入答案', trigger: ['blur', 'change'] }];
  }

  return _rules;
});

async function loadKnowledgePointList() {
  if (!formData.value.subjectId) return;
  try {
    const res = await getKnowledgePointDetailsAxios({ subjectId: formData.value.subjectId });
    knowledgePointList.value = res || [];
  } catch (error) {
    console.error(error);
  }
}

async function getBaseDataAxios() {
  try {
    pageLoad.loadState = true;
    const [data, questionBankNav] = await Promise.all([getQuestionInfoAxios(topicInfo!.questionId!), getQuestionBankNavAxios()]);
    formData.value.bookId = data.bookId!;
    formData.value.bookPageId = data.bookPageId!;
    formData.value.id = data.id!;
    formData.value.no = data.no;
    formData.value.question = data.question || '';
    formData.value.score = data.score || undefined;
    formData.value.analysis = data.analysis || '';
    formData.value.type = data.type || 1;
    formData.value.answerTime = data.answerTime || undefined;
    formData.value.knowledgepointIds = data.knowledgePointIds || [];
    formData.value.subjectId = data.subjectId || undefined;
    formData.value.videourl = data.videoUrl || '';

    if (data.videoUrl) {
      let poster = '';
      try {
        const posterInfo = await getFirstFrameOfVideo(data.videoUrl);
        poster = (await fileToBase64(posterInfo.firstFrame)).img;
      } catch (error) {}
      videoInfo.value = { url: data.videoUrl, poster };
    } else {
      videoInfo.value = undefined;
    }

    await loadKnowledgePointList();
    formData.value.options = myStrToJson<string[]>(data.options || '[]') || [];
    subjectList.value = questionBankNav.subjects || [];
    await nextTick();

    if (formData.value.type === 1) {
      formData.value.singleChoiceAnswer = (myStrToJson<string[]>(data.answer || '[]') || [])[0] || '';
    } else if (formData.value.type === 2) {
      formData.value.multiChoiceAnswer = myStrToJson<string[]>(data.answer || '[]') || [];
    } else if (formData.value.type === 3) {
      const _answer = data.answer ?? undefined;
      formData.value.trueOrFalseAnswer = _answer !== undefined ? (parseInt(_answer) === 1 ? 1 : 0) : undefined;
    } else if (![1, 2, 3].includes(formData.value.type || 0)) {
      formData.value.textAnswer = data.answer ?? '';
    }
    pageLoad.loadState = false;
  } catch (error: any) {
    pageLoad.loadState = 'err';
    pageLoad.description = error.message || '系统错误';
  }
}

function subjectIdChange() {
  formData.value.knowledgepointIds = [];
  loadKnowledgePointList();
}

async function handleSubmit() {
  try {
    await formRef.value?.validate();
  } catch (error) {
    message.warning('请完善表单');
    return;
  }

  try {
    let answer = '';
    if (formData.value.type === 1) {
      answer = formData.value.singleChoiceAnswer || '';
      answer = answer ? JSON.stringify([answer]) : '[]';
    } else if (formData.value.type === 2) {
      answer = JSON.stringify(formData.value.multiChoiceAnswer || []);
    } else if (formData.value.type === 3) {
      answer = formData.value.trueOrFalseAnswer === 1 ? '1' : '0';
    } else if (![1, 2, 3].includes(formData.value.type || 0)) {
      answer = formData.value.textAnswer || '';
    }

    submitLoading.value = true;
    const data: BookPageQuestionUpdateInput = {
      analysis: formData.value.analysis,
      answer,
      bookId: formData.value.bookId,
      bookPageId: formData.value.bookPageId,
      id: formData.value.id,
      options: JSON.stringify(formData.value.options || []),
      subjectId: formData.value.subjectId,
      knowledgepointIds: formData.value.knowledgepointIds,
      no: formData.value.no,
      question: formData.value.question,
      score: formData.value.score,
      type: formData.value.type,
      answerTime: formData.value.answerTime,
      videoUrl: formData.value.videourl,
    };

    await editQuestionInfoAxios(data);
    message.success('修改成功');
    drawer.value = false;
  } catch (error: any) {
    message.error(error.msg || '修改失败');
  } finally {
    submitLoading.value = false;
  }
}

function show(data: { topicInfo: TopicInfo }) {
  topicInfo = data.topicInfo;
  drawer.value = true;
  getBaseDataAxios();
}

function hide() {
  drawer.value = false;
}

defineExpose({
  show,
  hide,
});
</script>

<style scoped>
:deep(.n-input-number .n-input__input-el) {
  text-align: center;
}
</style>
