<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { jsonClone } from '@sa/utils';
import { fetchCreateSchoolDetail, fetchUpdateSchoolDetail } from '@/service/api/art/school-detail';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { $t } from '@/locales';

defineOptions({
  name: 'SchoolDetailOperateDrawer'
});

interface Props {
  /** the type of operation */
  operateType: NaiveUI.TableOperateType;
  /** the edit row data */
  rowData?: Api.Art.SchoolDetail | null;
  /** the default school id when opened from school list */
  defaultSchoolId?: CommonType.IdType | null;
}

const props = withDefaults(defineProps<Props>(), {
  rowData: null,
  defaultSchoolId: null
});

interface Emits {
  (e: 'submitted'): void;
}

const emit = defineEmits<Emits>();

const visible = defineModel<boolean>('visible', {
  default: false
});

const { formRef, validate, restoreValidation } = useNaiveForm();
const { createRequiredRule } = useFormRules();
const submitLoading = ref(false);
const detailTagInputValue = ref('');
const detailTagList = ref<string[]>([]);

const title = computed(() => {
  const titles: Record<NaiveUI.TableOperateType, string> = {
    add: '新增学校详细信息',
    edit: '编辑学校详细信息'
  };
  return titles[props.operateType];
});

const booleanOptions = [
  { value: 1, label: '是' },
  { value: 0, label: '否' }
];

function toNumberValue(value: CommonType.IdType | null | undefined) {
  if (value === null || value === undefined || value === '') return null;

  return typeof value === 'number' ? value : Number(value);
}

type Model = Api.Art.SchoolDetailOperateParams;

const model = ref<Model>(createDefaultModel());

function createDefaultModel(): Model {
  return {
    detailId: null,
    schoolId: null,
    introduction: '',
    schoolIcon: '',
    backGround: '',
    address: '',
    contact: '',
    email: '',
    website: '',
    postcode: '',
    establishYear: null,
    campusAreaMu: null,
    libraryCollection: null,
    maleRatio: null,
    femaleRatio: null,
    is985: null,
    is211: null,
    isDoubleFirstClass: null,
    isKeyUniversity: null,
    isPublic: null,
    tags: [],
    studentCount: null,
    teacherCount: null,
    masterPoint: null,
    doctorPoint: null,
    keyMajorCount: null,
    employmentRate: null,
    satisfactionRate: null,
    univId: null,
    masterProportionRate: null,
    abroadProportionRate: null,
    hasRegular: null,
    hasJunior: null,
    hasMaster: null,
    isDoubleHighPlan: null,
    isStrongPlan: null,
    twsdlRank: null,
    xyhRank: null,
    wslRank: null,
    usdaluRank: null,
    qsdaluRank: null,
    combinedScore: null,
    overallRank: null,
    envSatisfaction: null,
    envVote: null,
    liveSatisfaction: null,
    liveVote: null,
    combinedSatisfaction: null,
    combinedVote: null,
    teachers: '',
    scholarship: '',
    grantDesc: '',
    canteen: '',
    dormitory: '',
    masterExplain: '',
    doctorExplain: '',
    remark: ''
  };
}

type RuleKey = 'schoolId' | 'address' | 'contact';

const rules: Record<RuleKey, App.Global.FormRule> = {
  schoolId: createRequiredRule('关联学校主表ID不能为空'),
  address: createRequiredRule('学校地址不能为空'),
  contact: createRequiredRule('联系电话不能为空')
};

function normalizeStringList(values?: string[] | null) {
  if (!values?.length) return [];

  const uniqueValues = new Set<string>();

  values.forEach(value => {
    const normalizedValue = String(value).trim();
    if (normalizedValue) {
      uniqueValues.add(normalizedValue);
    }
  });

  return Array.from(uniqueValues);
}

function isSameStringList(source: string[], target: string[]) {
  if (source.length !== target.length) return false;
  return source.every((value, index) => value === target[index]);
}

function syncTagsToModel() {
  model.value.tags = normalizeStringList(detailTagList.value);
}

function addDetailTags() {
  const values = detailTagInputValue.value
    .split(/[,，]/)
    .map(item => item.trim())
    .filter(Boolean);

  if (!values.length) return;

  detailTagList.value = normalizeStringList([...detailTagList.value, ...values]);
  detailTagInputValue.value = '';
}

function handleUpdateModelWhenEdit() {
  model.value = createDefaultModel();
  detailTagInputValue.value = '';
  detailTagList.value = [];

  if (props.operateType === 'add' && props.defaultSchoolId !== null) {
    model.value.schoolId = props.defaultSchoolId;
  }

  if (props.operateType === 'edit' && props.rowData) {
    const detailData = jsonClone(props.rowData);
    Object.assign(model.value, detailData);
    detailTagList.value = normalizeStringList(detailData.tags);
  }

  syncTagsToModel();
}

function closeDrawer() {
  visible.value = false;
}

async function handleSubmit() {
  await validate();

  submitLoading.value = true;

  const {
    detailId,
    schoolId,
    introduction,
    schoolIcon,
    backGround,
    address,
    contact,
    email,
    website,
    postcode,
    establishYear,
    campusAreaMu,
    libraryCollection,
    maleRatio,
    femaleRatio,
    is985,
    is211,
    isDoubleFirstClass,
    isKeyUniversity,
    isPublic,
    studentCount,
    teacherCount,
    masterPoint,
    doctorPoint,
    keyMajorCount,
    employmentRate,
    satisfactionRate,
    univId,
    masterProportionRate,
    abroadProportionRate,
    hasRegular,
    hasJunior,
    hasMaster,
    isDoubleHighPlan,
    isStrongPlan,
    twsdlRank,
    xyhRank,
    wslRank,
    usdaluRank,
    qsdaluRank,
    combinedScore,
    overallRank,
    envSatisfaction,
    envVote,
    liveSatisfaction,
    liveVote,
    combinedSatisfaction,
    combinedVote,
    teachers,
    scholarship,
    grantDesc,
    canteen,
    dormitory,
    masterExplain,
    doctorExplain,
    remark
  } = model.value;

  const payload: Api.Art.SchoolDetailOperateParams = {
    detailId,
    schoolId,
    introduction,
    schoolIcon,
    backGround,
    address,
    contact,
    email,
    website,
    postcode,
    establishYear,
    campusAreaMu,
    libraryCollection,
    maleRatio,
    femaleRatio,
    is985,
    is211,
    isDoubleFirstClass,
    isKeyUniversity,
    isPublic,
    tags: normalizeStringList(detailTagList.value),
    studentCount,
    teacherCount,
    masterPoint,
    doctorPoint,
    keyMajorCount,
    employmentRate,
    satisfactionRate,
    univId,
    masterProportionRate,
    abroadProportionRate,
    hasRegular,
    hasJunior,
    hasMaster,
    isDoubleHighPlan,
    isStrongPlan,
    twsdlRank,
    xyhRank,
    wslRank,
    usdaluRank,
    qsdaluRank,
    combinedScore,
    overallRank,
    envSatisfaction,
    envVote,
    liveSatisfaction,
    liveVote,
    combinedSatisfaction,
    combinedVote,
    teachers,
    scholarship,
    grantDesc,
    canteen,
    dormitory,
    masterExplain,
    doctorExplain,
    remark
  };

  if (props.operateType === 'add') {
    const { error } = await fetchCreateSchoolDetail(payload);
    submitLoading.value = false;
    if (error) return;
  }

  if (props.operateType === 'edit') {
    const { error } = await fetchUpdateSchoolDetail(payload);
    submitLoading.value = false;
    if (error) return;
  }

  window.$message?.success(props.operateType === 'add' ? $t('common.addSuccess') : $t('common.updateSuccess'));
  closeDrawer();
  emit('submitted');
}

watch(visible, show => {
  if (show) {
    handleUpdateModelWhenEdit();
    restoreValidation();
  }
});

watch(
  detailTagList,
  tags => {
    const normalizedTags = normalizeStringList(tags);

    if (!isSameStringList(tags, normalizedTags)) {
      detailTagList.value = normalizedTags;
      return;
    }

    syncTagsToModel();
  },
  { deep: true }
);
</script>

<template>
  <NDrawer v-model:show="visible" :title="title" display-directive="show" :width="980" class="max-w-96%">
    <NDrawerContent :title="title" :native-scrollbar="false" closable>
      <NForm ref="formRef" :model="model" :rules="rules" label-placement="left">
        <NGrid :cols="24" :x-gap="16">
          <NGi :span="8">
            <NFormItem label="关联学校主表ID" path="schoolId">
              <NInputNumber
                :value="toNumberValue(model.schoolId)"
                :disabled="props.defaultSchoolId !== null"
                class="w-full"
                clearable
                placeholder="请输入关联学校主表ID"
                @update:value="value => (model.schoolId = value)"
              />
            </NFormItem>
          </NGi>
          <NGi :span="8">
            <NFormItem label="外部学校ID" path="univId">
              <NInputNumber v-model:value="model.univId" class="w-full" clearable placeholder="请输入外部学校ID" />
            </NFormItem>
          </NGi>
          <NGi :span="8">
            <NFormItem label="邮编" path="postcode">
              <NInput v-model:value="model.postcode" placeholder="请输入邮编" />
            </NFormItem>
          </NGi>
          <NGi :span="24">
            <NFormItem label="学校详细介绍" path="introduction">
              <NInput
                v-model:value="model.introduction"
                :rows="3"
                type="textarea"
                placeholder="请输入学校详细介绍（大文本）"
              />
            </NFormItem>
          </NGi>
          <NGi :span="12">
            <NFormItem label="院校图标" path="schoolIcon">
              <NInput v-model:value="model.schoolIcon" placeholder="请输入院校图标地址" />
            </NFormItem>
          </NGi>
          <NGi :span="12">
            <NFormItem label="学校背景图" path="backGround">
              <NInput v-model:value="model.backGround" placeholder="请输入学校背景图地址" />
            </NFormItem>
          </NGi>
          <NGi :span="12">
            <NFormItem label="官网地址" path="website">
              <NInput v-model:value="model.website" placeholder="请输入官网地址" />
            </NFormItem>
          </NGi>
          <NGi :span="12">
            <NFormItem label="学校地址" path="address">
              <NInput v-model:value="model.address" placeholder="请输入学校地址" />
            </NFormItem>
          </NGi>
          <NGi :span="12">
            <NFormItem label="联系电话" path="contact">
              <NInput v-model:value="model.contact" placeholder="请输入联系电话" />
            </NFormItem>
          </NGi>
          <NGi :span="12">
            <NFormItem label="邮箱" path="email">
              <NInput v-model:value="model.email" placeholder="请输入邮箱" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="建校年份" path="establishYear">
              <NInputNumber v-model:value="model.establishYear" class="w-full" clearable placeholder="请输入建校年份" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="占地面积(亩)" path="campusAreaMu">
              <NInputNumber v-model:value="model.campusAreaMu" class="w-full" clearable placeholder="请输入占地面积" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="图书馆藏书量" path="libraryCollection">
              <NInputNumber
                v-model:value="model.libraryCollection"
                class="w-full"
                clearable
                placeholder="请输入图书馆藏书量"
              />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="学生人数" path="studentCount">
              <NInputNumber v-model:value="model.studentCount" class="w-full" clearable placeholder="请输入学生人数" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="教师人数" path="teacherCount">
              <NInputNumber v-model:value="model.teacherCount" class="w-full" clearable placeholder="请输入教师人数" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="硕士点数量" path="masterPoint">
              <NInputNumber v-model:value="model.masterPoint" class="w-full" clearable placeholder="请输入硕士点数量" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="博士点数量" path="doctorPoint">
              <NInputNumber v-model:value="model.doctorPoint" class="w-full" clearable placeholder="请输入博士点数量" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="重点专业数" path="keyMajorCount">
              <NInputNumber v-model:value="model.keyMajorCount" class="w-full" clearable placeholder="请输入重点专业数" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="男生比例(%)" path="maleRatio">
              <NInputNumber v-model:value="model.maleRatio" class="w-full" clearable placeholder="请输入男生比例" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="女生比例(%)" path="femaleRatio">
              <NInputNumber v-model:value="model.femaleRatio" class="w-full" clearable placeholder="请输入女生比例" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="就业率(%)" path="employmentRate">
              <NInputNumber v-model:value="model.employmentRate" class="w-full" clearable placeholder="请输入就业率" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="满意度(%)" path="satisfactionRate">
              <NInputNumber v-model:value="model.satisfactionRate" class="w-full" clearable placeholder="请输入满意度" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="是否985" path="is985">
              <NSelect v-model:value="model.is985" :options="booleanOptions" clearable placeholder="请选择" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="是否211" path="is211">
              <NSelect v-model:value="model.is211" :options="booleanOptions" clearable placeholder="请选择" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="是否双一流" path="isDoubleFirstClass">
              <NSelect v-model:value="model.isDoubleFirstClass" :options="booleanOptions" clearable placeholder="请选择" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="是否重点大学" path="isKeyUniversity">
              <NSelect v-model:value="model.isKeyUniversity" :options="booleanOptions" clearable placeholder="请选择" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="是否公办" path="isPublic">
              <NSelect v-model:value="model.isPublic" :options="booleanOptions" clearable placeholder="请选择" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="考研率(%)" path="masterProportionRate">
              <NInputNumber
                v-model:value="model.masterProportionRate"
                class="w-full"
                clearable
                placeholder="请输入考研率"
              />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="出国率(%)" path="abroadProportionRate">
              <NInputNumber
                v-model:value="model.abroadProportionRate"
                class="w-full"
                clearable
                placeholder="请输入出国率"
              />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="普通本科" path="hasRegular">
              <NSelect v-model:value="model.hasRegular" :options="booleanOptions" clearable placeholder="请选择" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="专科" path="hasJunior">
              <NSelect v-model:value="model.hasJunior" :options="booleanOptions" clearable placeholder="请选择" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="硕士点" path="hasMaster">
              <NSelect v-model:value="model.hasMaster" :options="booleanOptions" clearable placeholder="请选择" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="双高计划" path="isDoubleHighPlan">
              <NSelect v-model:value="model.isDoubleHighPlan" :options="booleanOptions" clearable placeholder="请选择" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="强基计划" path="isStrongPlan">
              <NSelect v-model:value="model.isStrongPlan" :options="booleanOptions" clearable placeholder="请选择" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="泰晤士排名" path="twsdlRank">
              <NInputNumber v-model:value="model.twsdlRank" class="w-full" clearable placeholder="请输入泰晤士排名" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="校友会排名" path="xyhRank">
              <NInputNumber v-model:value="model.xyhRank" class="w-full" clearable placeholder="请输入校友会排名" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="武书连排名" path="wslRank">
              <NInputNumber v-model:value="model.wslRank" class="w-full" clearable placeholder="请输入武书连排名" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="US排名" path="usdaluRank">
              <NInputNumber v-model:value="model.usdaluRank" class="w-full" clearable placeholder="请输入US排名" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="QS排名" path="qsdaluRank">
              <NInputNumber v-model:value="model.qsdaluRank" class="w-full" clearable placeholder="请输入QS排名" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="综合评分" path="combinedScore">
              <NInputNumber v-model:value="model.combinedScore" class="w-full" clearable placeholder="请输入综合评分" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="综合排名" path="overallRank">
              <NInputNumber v-model:value="model.overallRank" class="w-full" clearable placeholder="请输入综合排名" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="环境满意度" path="envSatisfaction">
              <NInputNumber
                v-model:value="model.envSatisfaction"
                class="w-full"
                clearable
                placeholder="请输入环境满意度"
              />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="环境投票数" path="envVote">
              <NInputNumber v-model:value="model.envVote" class="w-full" clearable placeholder="请输入环境投票数" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="生活满意度" path="liveSatisfaction">
              <NInputNumber
                v-model:value="model.liveSatisfaction"
                class="w-full"
                clearable
                placeholder="请输入生活满意度"
              />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="生活投票数" path="liveVote">
              <NInputNumber v-model:value="model.liveVote" class="w-full" clearable placeholder="请输入生活投票数" />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="综合满意度" path="combinedSatisfaction">
              <NInputNumber
                v-model:value="model.combinedSatisfaction"
                class="w-full"
                clearable
                placeholder="请输入综合满意度"
              />
            </NFormItem>
          </NGi>
          <NGi :span="6">
            <NFormItem label="综合投票数" path="combinedVote">
              <NInputNumber v-model:value="model.combinedVote" class="w-full" clearable placeholder="请输入综合投票数" />
            </NFormItem>
          </NGi>
          <NGi :span="24">
            <NFormItem label="详情标签" path="tags">
              <NSpace vertical class="w-full">
                <NSpace class="w-full" :wrap-item="false">
                  <NInput
                    v-model:value="detailTagInputValue"
                    class="flex-1"
                    placeholder="输入详情标签后回车或点击确认，可用逗号一次输入多个"
                    @keydown.enter.prevent="addDetailTags"
                  />
                  <NButton type="primary" ghost @click="addDetailTags">确认</NButton>
                </NSpace>
                <NDynamicTags v-model:value="detailTagList" />
              </NSpace>
            </NFormItem>
          </NGi>
          <NGi :span="24">
            <NFormItem label="师资力量" path="teachers">
              <NInput v-model:value="model.teachers" :rows="3" type="textarea" placeholder="请输入师资力量描述" />
            </NFormItem>
          </NGi>
          <NGi :span="24">
            <NFormItem label="奖学金说明" path="scholarship">
              <NInput v-model:value="model.scholarship" :rows="3" type="textarea" placeholder="请输入奖学金说明" />
            </NFormItem>
          </NGi>
          <NGi :span="24">
            <NFormItem label="助学金说明" path="grantDesc">
              <NInput v-model:value="model.grantDesc" :rows="3" type="textarea" placeholder="请输入助学金说明" />
            </NFormItem>
          </NGi>
          <NGi :span="24">
            <NFormItem label="食堂说明" path="canteen">
              <NInput v-model:value="model.canteen" :rows="3" type="textarea" placeholder="请输入食堂说明" />
            </NFormItem>
          </NGi>
          <NGi :span="24">
            <NFormItem label="宿舍说明" path="dormitory">
              <NInput v-model:value="model.dormitory" :rows="3" type="textarea" placeholder="请输入宿舍说明" />
            </NFormItem>
          </NGi>
          <NGi :span="24">
            <NFormItem label="硕士点说明" path="masterExplain">
              <NInput v-model:value="model.masterExplain" :rows="3" type="textarea" placeholder="请输入硕士点说明" />
            </NFormItem>
          </NGi>
          <NGi :span="24">
            <NFormItem label="博士点说明" path="doctorExplain">
              <NInput v-model:value="model.doctorExplain" :rows="3" type="textarea" placeholder="请输入博士点说明" />
            </NFormItem>
          </NGi>
          <NGi :span="24">
            <NFormItem label="备注" path="remark">
              <NInput v-model:value="model.remark" :rows="3" type="textarea" placeholder="请输入备注" />
            </NFormItem>
          </NGi>
        </NGrid>
      </NForm>
      <template #footer>
        <NSpace :size="16">
          <NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
          <NButton type="primary" :loading="submitLoading" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
        </NSpace>
      </template>
    </NDrawerContent>
  </NDrawer>
</template>

<style scoped></style>
