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

defineOptions({
  name: 'SchoolOperateDrawer'
});

interface Props {
  /** the type of operation */
  operateType: NaiveUI.TableOperateType;
  /** the edit row data */
  rowData?: Api.Art.School | null;
}

const props = withDefaults(defineProps<Props>(), {
  rowData: 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 detailLoading = ref(false);
const enrollCodeInputValue = ref('');
const enrollCodeList = ref<string[]>([]);
const schoolTagInputValue = ref('');
const schoolTagList = ref<string[]>([]);

const title = computed(() => {
  const titles: Record<NaiveUI.TableOperateType, string> = {
    add: '新增院校（基础信息 + 详情信息）',
    edit: '编辑院校（基础信息 + 详情信息）'
  };
  return titles[props.operateType];
});

type Model = Api.Art.SchoolWithDetailOperateParams;

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

function createDefaultModel(): Model {
  return {
    school: {
      schoolId: null,
      mainCode: '',
      mainName: '',
      shortName: '',
      schoolIcon: '',
      province: '',
      city: '',
      district: '',
      universityType: '',
      educationLevel: '',
      schoolNature: '',
      supervisorDept: '',
      establishYear: null,
      campusAreaMu: null,
      maleRatio: null,
      femaleRatio: null,
      remark: ''
    },
    detail: {
      detailId: null,
      schoolId: null,
      introduction: '',
      address: '',
      contact: '',
      email: '',
      website: '',
      remark: ''
    },
    enrollCodes: [],
    schoolTags: []
  };
}

type RuleKey = 'school.mainCode' | 'school.mainName' | 'detail.address' | 'detail.contact';

const rules: Record<RuleKey, App.Global.FormRule> = {
  'school.mainCode': createRequiredRule('学校编码不能为空'),
  'school.mainName': createRequiredRule('学校主名称不能为空'),
  'detail.address': createRequiredRule('学校地址不能为空'),
  'detail.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((code, index) => code === target[index]);
}

function addEnrollCodes() {
  const inputCodes = enrollCodeInputValue.value
    .split(/[,，]/)
    .map(code => code.trim())
    .filter(Boolean);

  if (!inputCodes.length) return;

  enrollCodeList.value = normalizeStringList([...enrollCodeList.value, ...inputCodes]);
  enrollCodeInputValue.value = '';
}

function addSchoolTags() {
  const inputTags = schoolTagInputValue.value
    .split(/[,，]/)
    .map(tag => tag.trim())
    .filter(Boolean);

  if (!inputTags.length) return;

  schoolTagList.value = normalizeStringList([...schoolTagList.value, ...inputTags]);
  schoolTagInputValue.value = '';
}

function syncEnrollCodesToModel() {
  model.value.enrollCodes = normalizeStringList(enrollCodeList.value);
}

function syncSchoolTagsToModel() {
  model.value.schoolTags = normalizeStringList(schoolTagList.value);
}

async function loadEditFormData(schoolId: CommonType.IdType) {
  detailLoading.value = true;

  const [schoolRes, detailRes] = await Promise.all([
    fetchGetSchoolInfo(schoolId),
    fetchGetSchoolDetailBySchoolId(schoolId)
  ]);

  if (!schoolRes.error) {
    const schoolData = jsonClone(schoolRes.data);
    const { enrollCodes = [], schoolTags = [], ...schoolFields } = schoolData;
    Object.assign(model.value.school, schoolFields);
    enrollCodeList.value = normalizeStringList(enrollCodes);
    schoolTagList.value = normalizeStringList(schoolTags);
  } else if (props.rowData) {
    const schoolData = jsonClone(props.rowData);
    const { enrollCodes = [], schoolTags = [], ...schoolFields } = schoolData;
    Object.assign(model.value.school, schoolFields);
    enrollCodeList.value = normalizeStringList(enrollCodes);
    schoolTagList.value = normalizeStringList(schoolTags);
  }

  if (!detailRes.error && detailRes.data) {
    Object.assign(model.value.detail, jsonClone(detailRes.data));
  }

  syncEnrollCodesToModel();
  syncSchoolTagsToModel();
  model.value.detail.schoolId = model.value.school.schoolId;
  detailLoading.value = false;
}

async function handleUpdateModelWhenOpen() {
  model.value = createDefaultModel();
  enrollCodeInputValue.value = '';
  enrollCodeList.value = [];
  schoolTagInputValue.value = '';
  schoolTagList.value = [];

  if (props.operateType === 'edit' && props.rowData?.schoolId !== null && props.rowData?.schoolId !== undefined) {
    await loadEditFormData(props.rowData.schoolId);
  } else {
    syncEnrollCodesToModel();
    syncSchoolTagsToModel();
  }
}

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

function getStatusMessage(data: boolean | Api.Art.SchoolWithDetailSubmitStatus) {
  if (typeof data === 'boolean') return null;

  const schoolMsg = data.schoolMessage || data.schoolStatus;
  const detailMsg = data.detailMessage || data.detailStatus;

  if (!schoolMsg && !detailMsg) return null;

  return `基础信息：${schoolMsg || '处理完成'}；详情信息：${detailMsg || '处理完成'}`;
}

async function handleSubmit() {
  await validate();

  submitLoading.value = true;

  const payload: Api.Art.SchoolWithDetailOperateParams = {
    school: {
      ...model.value.school
    },
    detail: {
      ...model.value.detail,
      schoolId: model.value.school.schoolId
    },
    enrollCodes: normalizeStringList(enrollCodeList.value),
    schoolTags: normalizeStringList(schoolTagList.value)
  };

  let responseData: boolean | Api.Art.SchoolWithDetailSubmitStatus = true;

  if (props.operateType === 'add') {
    const { data, error } = await fetchCreateSchool(payload);
    submitLoading.value = false;
    if (error) return;
    responseData = data ?? true;
  }

  if (props.operateType === 'edit') {
    const { data, error } = await fetchUpdateSchool(payload);
    submitLoading.value = false;
    if (error) return;
    responseData = data ?? true;
  }

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

watch(visible, async show => {
  if (show) {
    await handleUpdateModelWhenOpen();
    restoreValidation();
  }
});

watch(
  enrollCodeList,
  codes => {
    const normalizedCodes = normalizeStringList(codes);

    if (!isSameStringList(codes, normalizedCodes)) {
      enrollCodeList.value = normalizedCodes;
      return;
    }

    syncEnrollCodesToModel();
  },
  { deep: true }
);

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

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

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

<template>
  <NDrawer v-model:show="visible" :title="title" display-directive="show" :width="960" class="max-w-92%">
    <NDrawerContent :title="title" :native-scrollbar="false" closable>
      <NForm ref="formRef" :model="model" :rules="rules" label-placement="left">
        <NCard title="院校基础信息" size="small" :bordered="true" class="mb-16px">
          <NGrid :cols="24" :x-gap="16">
            <NGi :span="12">
              <NFormItem label="学校编码" path="school.mainCode">
                <NInput v-model:value="model.school.mainCode" placeholder="请输入学校编码（唯一标识，如国标代码）" />
              </NFormItem>
            </NGi>
            <NGi :span="12">
              <NFormItem label="学校主名称" path="school.mainName">
                <NInput v-model:value="model.school.mainName" placeholder="请输入学校主名称（官方全称）" />
              </NFormItem>
            </NGi>
            <NGi :span="12">
              <NFormItem label="学校简称" path="school.shortName">
                <NInput v-model:value="model.school.shortName" placeholder="请输入学校简称（备用）" />
              </NFormItem>
            </NGi>
            <NGi :span="24">
              <NFormItem label="院校招生代码" path="enrollCodes">
                <NSpace vertical class="w-full">
                  <NSpace class="w-full" :wrap-item="false">
                    <NInput
                      v-model:value="enrollCodeInputValue"
                      class="flex-1"
                      placeholder="输入招生代码后回车或点击确认，可用逗号一次输入多个"
                      @keydown.enter.prevent="addEnrollCodes"
                    />
                    <NButton type="primary" ghost @click="addEnrollCodes">确认</NButton>
                  </NSpace>
                  <NDynamicTags v-model:value="enrollCodeList" />
                </NSpace>
              </NFormItem>
            </NGi>
            <NGi :span="24">
              <NFormItem label="学校标签" path="schoolTags">
                <NSpace vertical class="w-full">
                  <NSpace class="w-full" :wrap-item="false">
                    <NInput
                      v-model:value="schoolTagInputValue"
                      class="flex-1"
                      placeholder="输入学校标签后回车或点击确认，可用逗号一次输入多个"
                      @keydown.enter.prevent="addSchoolTags"
                    />
                    <NButton type="primary" ghost @click="addSchoolTags">确认</NButton>
                  </NSpace>
                  <NDynamicTags v-model:value="schoolTagList" />
                </NSpace>
              </NFormItem>
            </NGi>
            <NGi :span="12">
              <NFormItem label="院校图标" path="school.schoolIcon">
                <NInput v-model:value="model.school.schoolIcon" placeholder="请输入院校图标地址" />
              </NFormItem>
            </NGi>
            <NGi :span="8">
              <NFormItem label="省份" path="school.province">
                <NInput v-model:value="model.school.province" placeholder="请输入省份" />
              </NFormItem>
            </NGi>
            <NGi :span="8">
              <NFormItem label="城市" path="school.city">
                <NInput v-model:value="model.school.city" placeholder="请输入城市" />
              </NFormItem>
            </NGi>
            <NGi :span="8">
              <NFormItem label="区县" path="school.district">
                <NInput v-model:value="model.school.district" placeholder="请输入区县" />
              </NFormItem>
            </NGi>
            <NGi :span="8">
              <NFormItem label="大学类型" path="school.universityType">
                <NInput v-model:value="model.school.universityType" placeholder="如：综合/工科/财经/艺术" />
              </NFormItem>
            </NGi>
            <NGi :span="8">
              <NFormItem label="学历层次" path="school.educationLevel">
                <NSelect
                  v-model:value="model.school.educationLevel"
                  placeholder="请选择学历层次"
                  :options="[
                    { value: '', label: '请选择' },
                    { value: '本科', label: '本科' },
                    { value: '专科', label: '专科' }
                  ]"
                  clearable
                />
              </NFormItem>
            </NGi>
            <NGi :span="8">
              <NFormItem label="办学性质" path="school.schoolNature">
                <NSelect
                  v-model:value="model.school.schoolNature"
                  placeholder="请选择办学性质"
                  :options="[
                    { value: '公办', label: '公办' },
                    { value: '民办', label: '民办' },
                    { value: '中外合作', label: '中外合作' }
                  ]"
                  clearable
                />
              </NFormItem>
            </NGi>
            <NGi :span="8">
              <NFormItem label="主管部门" path="school.supervisorDept">
                <NInput v-model:value="model.school.supervisorDept" placeholder="请输入主管部门" />
              </NFormItem>
            </NGi>
            <NGi :span="8">
              <NFormItem label="建校时间(年)" path="school.establishYear">
                <NInput v-model:value="model.school.establishYear" placeholder="请输入建校年份" />
              </NFormItem>
            </NGi>
            <NGi :span="8">
              <NFormItem label="占地面积(亩)" path="school.campusAreaMu">
                <NInput v-model:value="model.school.campusAreaMu" placeholder="请输入占地面积(亩)" />
              </NFormItem>
            </NGi>
            <NGi :span="8">
              <NFormItem label="男生比例(%)" path="school.maleRatio">
                <NInput v-model:value="model.school.maleRatio" placeholder="请输入男生比例(%)" />
              </NFormItem>
            </NGi>
            <NGi :span="8">
              <NFormItem label="女生比例(%)" path="school.femaleRatio">
                <NInput v-model:value="model.school.femaleRatio" placeholder="请输入女生比例(%)" />
              </NFormItem>
            </NGi>
            <NGi :span="24">
              <NFormItem label="备注" path="school.remark">
                <NInput v-model:value="model.school.remark" :rows="2" type="textarea" placeholder="请输入备注" />
              </NFormItem>
            </NGi>
          </NGrid>
        </NCard>

        <NCard title="院校详情信息" size="small" :bordered="true" :loading="detailLoading">
          <NGrid :cols="24" :x-gap="16">
            <NGi :span="24">
              <NFormItem label="学校详细介绍" path="detail.introduction">
                <NInput
                  v-model:value="model.detail.introduction"
                  :rows="4"
                  type="textarea"
                  placeholder="请输入学校详细介绍"
                />
              </NFormItem>
            </NGi>
            <NGi :span="12">
              <NFormItem label="学校地址" path="detail.address">
                <NInput v-model:value="model.detail.address" placeholder="请输入学校地址" />
              </NFormItem>
            </NGi>
            <NGi :span="12">
              <NFormItem label="联系电话" path="detail.contact">
                <NInput v-model:value="model.detail.contact" placeholder="请输入联系电话" />
              </NFormItem>
            </NGi>
            <NGi :span="12">
              <NFormItem label="邮箱" path="detail.email">
                <NInput v-model:value="model.detail.email" placeholder="请输入邮箱" />
              </NFormItem>
            </NGi>
            <NGi :span="12">
              <NFormItem label="官网地址" path="detail.website">
                <NInput v-model:value="model.detail.website" placeholder="请输入官网地址" />
              </NFormItem>
            </NGi>
            <NGi :span="24">
              <NFormItem label="详情备注" path="detail.remark">
                <NInput v-model:value="model.detail.remark" :rows="2" type="textarea" placeholder="请输入详情备注" />
              </NFormItem>
            </NGi>
          </NGrid>
        </NCard>
      </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>
