<template>
  <div class="flex direction-column">
    <div class="p-base p-t-medium-base p-b-medium-base fill-blank flex items-center">
      <span class="m-r-mini label">科目</span>
      <base-select v-model="subjectCode" clearable size="small" :options="subjectList"></base-select>
      <el-button class="m-l-base" size="small" type="primary" @click="onSearch">查询</el-button>
      <el-button class="m-l-mini" size="small" type="primary" special @click="onAddMainQuestion">新增</el-button>
    </div>
    <div class="flex-1 p-base">
      <el-card shadow="never">
        <base-table size="small" :columns="columns" :data="data">
          <template #column-operation="{ row }">
            <el-button type="primary" link @click="onEdit(row)">编辑</el-button>
            <el-popconfirm
              :width="useVW(220)"
              hide-icon
              :title="`确认${row.enable ? '禁用' : '启用'}科目?`"
              @confirm="toggleEnable(row)"
            >
              <template #reference>
                <el-button type="primary" link>
                  {{ row.enable ? '禁用' : '启用' }}
                </el-button>
              </template>
            </el-popconfirm>
            <el-popconfirm :width="useVW(220)" hide-icon :title="`确认删除科目?`" @confirm="onDelete(row)">
              <template #reference>
                <el-button type="primary" link>删除</el-button>
              </template>
            </el-popconfirm>
          </template>
        </base-table>
      </el-card>
    </div>
    <base-dialog v-model="visibleSubjectEditor" unless :footer="false" destroy-on-close>
      <base-form
        ref="formRef"
        :label-width="useVW(88)"
        :model="editInfo"
        :items="items"
        :rules="rules"
        :loading="saving"
      >
        <el-form-item class="m-t-base">
          <confirm-button :loading="saving" @confirm="onSubmit" @cancel="toggleVisible(false)"></confirm-button>
        </el-form-item>
      </base-form>
    </base-dialog>
  </div>
</template>

<script setup lang="tsx" name="SubjectManage">
/** 科目管理 */
import { reactive, ref, computed } from 'vue'
import { useRouter } from 'vue-router'
import { ElButton, ElCard, ElPopconfirm, ElFormItem, ElMessage } from 'element-plus'
import ConfirmButton from '@/components/common/ConfirmButton.vue'
import BaseSelect from '@/components/element/BaseSelect.vue'
import BaseForm from '@/components/element/BaseForm.vue'
import BaseTable from '@/components/element/BaseTable.vue'
import BaseDialog from '@/components/element/BaseDialog.vue'
import useOptions from '@/hooks/useOptions'
import useForm from '@/hooks/useForm'
import useTable from '@/hooks/useTable'
import useFetch from '@/hooks/useFetch'
import useVW from '@/hooks/useVW'
import { StatusMap } from '@/constants/dicts'

import type { EpFormItem, EpFormRules, EpTableColumn } from 'global-type'
import type { ExtractApiParams, ExtractMultipleApiResponse } from '@/api/api'

const { push } = useRouter()

const subjectCode = ref<string>()

const { subjectList, forceRefresh } = useOptions(['subject'], {}, true, null)

const request = reactive({ code: '' })

const { data, fetchTable } = useTable('getSubjectList', request)

const columns: EpTableColumn<ExtractMultipleApiResponse<'getSubjectList'>>[] = [
  { label: '科目代码', prop: 'code' },
  {
    label: '科目名称',
    prop: 'name',
    formatter(row) {
      return (
        <ElButton type="primary" link onClick={() => onViewSubjectStruct(row)}>
          {row.name}
        </ElButton>
      )
    },
  },
  { label: '主观分', prop: 'subjectiveScore' },
  { label: '客观分', prop: 'objectiveScore' },
  { label: '试卷总分', prop: 'totalScore' },
  { label: '操作', slotName: 'operation' },
]

async function onSearch() {
  Object.assign(request, { code: subjectCode.value })
}

function onViewSubjectStruct(row: ExtractMultipleApiResponse<'getSubjectList'>) {
  row.id && push({ name: 'StructManage', params: { id: row.id } })
}

const { fetch: saveSubjectInfo, loading: saving } = useFetch('saveSubjectInfo')

const initModel = {
  id: void 0,
  code: '',
  name: '',
  objectiveScore: 0,
  enable: true,
}

const editInfo = reactive<ExtractApiParams<'saveSubjectInfo'>>({ ...initModel })

const { formRef, elFormRef } = useForm()

const rules = computed<EpFormRules>(() => {
  return {
    code: [
      { required: !editInfo.id, message: '请填写科目代码' },
      { max: 50, message: '科目代码限制50字以内' },
    ],
    name: [
      { required: true, message: '请填写科目名称' },
      { max: 50, message: '科目名称限制50字以内' },
    ],
    objectiveScore: [
      { required: true, message: '请填写科目客观分总分' },
      { type: 'number', min: 0, max: 200, message: '客观分总分限制0-200分以内' },
    ],
  }
})

const items = computed<EpFormItem[]>(() => {
  return [
    { label: '科目代码', prop: 'code', slotType: 'input', slot: { placeholder: '科目代码', disabled: !!editInfo.id } },
    { label: '科目名称', prop: 'name', slotType: 'input', slot: { placeholder: '科目名称' } },
    {
      label: '客观分',
      prop: 'objectiveScore',
      slotType: 'inputNumber',
      slot: { placeholder: '客观分', stepStrictly: true, step: 1 },
    },
    { label: '状态', prop: 'enable', slotType: 'select', slot: { placeholder: '状态', options: StatusMap } },
  ]
})

const visibleSubjectEditor = ref<boolean>(false)

function toggleVisible(visible: boolean) {
  visibleSubjectEditor.value = visible
}

/** 新增科目 */
function onAddMainQuestion() {
  Object.assign(editInfo, { ...initModel })
  toggleVisible(true)
}

/** 编辑科目 */
function onEdit(row: ExtractMultipleApiResponse<'getSubjectList'>) {
  const { id, name, code, enable, objectiveScore } = row
  Object.assign(editInfo, { id, name, code, enable, objectiveScore })
  toggleVisible(true)
}

async function onSubmit() {
  try {
    const valid = await elFormRef?.value?.validate()
    valid && (await saveSubjectInfo(editInfo))
    ElMessage.success(`保存成功`)
    forceRefresh()
    fetchTable()
    toggleVisible(false)
  } catch (error) {
    console.error(error)
  }
}

/** 启用/禁用科目 */
const { fetch: toggleEnableSubject } = useFetch('toggleEnableSubject')

function toggleEnable(row: ExtractMultipleApiResponse<'getSubjectList'>) {
  row.id && toggleEnableSubject({ ids: [row.id], enable: !row.enable }).then(fetchTable)
}

/** 删除科目 */
const { fetch: deleteSubject } = useFetch('deleteSubject')

function onDelete(row: ExtractMultipleApiResponse<'getSubjectList'>) {
  row.id &&
    deleteSubject({ id: row.id }).then(() => {
      forceRefresh()
      fetchTable()
    })
}
</script>

<style scoped lang="scss">
.label {
  font-size: $SmallFont;
  color: $RegularFontColor;
}
</style>
