<template>
  <div class="h-full bg-white">
    <div v-if="pageState" style="margin-top: 1rem">
      <n-form :label-width="200" inline>
        <n-form-item class="min-w-34" label="请选择查询学员" path="user.name">
          <n-select
            v-model:value="scheduleParamsOptions.studentId"
            filterable
            placeholder="请选择查询学员"
            :options="studentOptions"
            :loading="studentOptionsLoading"
            clearable
            remote
            @search="studentOptionsSearch"
          />
        </n-form-item>
        <n-form-item class="min-w-34" label="请选择要查询的班级" path="classId">
          <n-select
            v-model:value="scheduleParamsOptions.classId"
            :options="groupList"
            clearable
            placeholder="请选择班级"
          />
        </n-form-item>
        <n-form-item class="min-w-34" label="请选择要查询的时间范围" path="user.name">
          <n-date-picker
            v-model:value="dateRange"
            type="daterange"
            clearable
            time-zone="Asia/Shanghai"
            placeholder="请选择时间范围"
            :on-confirm="differenceInSevenDays"
            :on-clear="
              () => {
                scheduleParamsOptions.startTime = '';
                scheduleParamsOptions.endTime = '';
              }
            "
          />
        </n-form-item>
        <n-form-item class="min-w-34" label="要查询的授课教师" path="user.name">
          <n-select
            v-model:value="scheduleParamsOptions.teacherId"
            :options="teacherOptions"
            placeholder="请选择授课教师"
            clearable
          />
        </n-form-item>
      </n-form>
      <n-button-group>
        <n-button type="primary" ghost @click="previousDateSchedule"> 上一周 </n-button>
        <n-button type="primary" ghost @click="nextDateSchedule"> 下一周 </n-button>
        <n-button type="primary" @click="loadScheduleQuery"> 搜索 </n-button>
        <n-button type="primary" @click="pageState = !pageState"> 新增排课 </n-button>
      </n-button-group>
      <div style="height: 1rem"></div>
      <n-spin :show="loading">
        <table border="1" style="width: 100%">
          <tbody width="100">
            <tr>
              <th class="w-20 color-blue-800">时间</th>
              <th v-for="weekDate in [0, 1, 2, 3, 4, 5, 6]" :key="weekDate" class="font-500 color-blue-800">
                {{ new Date(weekStartTime + weekDate * 86400000).getMonth() + 1 }}月{{
                  new Date(weekStartTime + weekDate * 86400000).getDate()
                }}号 - 周{{ chineseNumbers[getDayOfTheWeekNow(weekStartTime, weekDate)] }}
              </th>
            </tr>
            <tr v-for="key in timeKey" :key="key">
              <td>{{ key }}</td>
              <template v-for="index in [0, 1, 2, 3, 4, 5, 6]" :key="index">
                <td
                  v-if="
                    scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key] &&
                    scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key]['empty'] === false &&
                    scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key]['break'] === false
                  "
                  :rowspan="scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key]['colspan']"
                >
                  时间:
                  {{ scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key]['startTime'] }} -
                  {{ scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key]['endTime'].split(' ').pop() }}<br />
                  讲师: {{ scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key]['teacherName'] }}<br />
                  授课: {{ scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key]['category'] }}
                  {{ scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key]['subjects'] }}<br />
                  教室: {{ scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key]['classroom'] }}<br />
                  班级: {{ scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key]['className'] }}
                </td>
                <td
                  v-else-if="
                    scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key] &&
                    scheduleList[getDayOfTheWeekNow(weekStartTime, index)][key]['empty'] === true
                  "
                >
                  暂无
                </td>
              </template>
            </tr>
          </tbody>
        </table>
      </n-spin>
    </div>
    <div v-if="!pageState" class="wh-full flex-col-center">
      <n-spin :show="formLoading">
        <n-form ref="formRef" size="large" label-placement="left" style="margin-right: 5rem" :model="model">
          <n-form-item label="排课班级" path="groupList">
            <n-select v-model:value="model.classId" :options="groupList" />
          </n-form-item>
          <n-form-item label="所在教室" path="classRoomList">
            <n-select v-model:value="model.roomId" :options="classRoomList" />
          </n-form-item>
          <n-form-item label="任课老师" path="teacherId">
            <n-select
              v-model:value="model.teacherId"
              placeholder="请选择任课老师"
              :options="teacherOptions"
              clearable
            />
          </n-form-item>
          <n-form-item label="助教老师" path="multipleSelectValue">
            <n-select
              v-model:value="model.assistantId"
              placeholder="请选择助教老师"
              :options="teacherOptions"
              clearable
            />
          </n-form-item>
          <n-form-item label="教授科目" path="multipleSelectValue">
            <n-cascader
              v-model:value="model.subjectsId"
              placeholder="请选择课程"
              :options="categoryAndSubjectOptions"
              show-path
              check-strategy="child"
              remote
              :on-load="categoryAndSubjectLoad"
            />
          </n-form-item>
          <n-form-item label="上课时间" path="datetimeValue">
            <n-space>
              <n-date-picker v-model:value="dateValue" clearable time-zone="Asia/Shanghai" type="date" />
              <n-time-picker v-model:value="startTime" clearable time-zone="Asia/Shanghai" />
              <n-time-picker v-model:value="endTime" clearable time-zone="Asia/Shanghai" />
            </n-space>
          </n-form-item>
          <n-form-item label="是否连选" path="switchValue">
            <n-switch v-model:value="isRepeatTime" />
          </n-form-item>
          <n-form-item label="连选天数" path="sliderValue">
            <n-slider v-model:value="repeatTime" :step="1" :max="7" />
          </n-form-item>
          <n-form-item label="单节课时长" path="inputNumberValue">
            <n-input-number v-model:value="model.lessonTime" />
          </n-form-item>
          <div style="display: flex; justify-content: flex-end">
            <n-button-group>
              <n-button type="primary" @click="handleValidateButtonClick"> 确认提交 </n-button>
              <n-button type="primary" @click="pageState = !pageState"> 返回前一页 </n-button>
            </n-button-group>
          </div>
        </n-form>
      </n-spin>
    </div>
    <div style="width: 100%; height: 1rem"></div>
  </div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue';
import { useRoute } from 'vue-router';
import type { CascaderOption } from 'naive-ui';
import { formatTimestamp } from '~/src/utils';
import {
  queryUserAll,
  queryCategoryParams,
  querySubject,
  queryClassAll,
  addSchedule,
  queryClassRoomList,
  querySchedule,
  getStudentByKeyword
} from './api';
import type { ScheduleParams, QueryScheduleParams } from './api';
const route = useRoute();
const model = reactive<ScheduleParams>({
  week: 0,
  startTime: 0,
  endTime: 0,
  roomId: null,
  classId: null,
  assistantId: null,
  teacherId: null,
  categoryId: null,
  subjectsId: null,
  createTime: 0,
  modifyTime: 0,
  createUid: 0,
  disabled: 'N'
});
const classId = route.query.classId;
const studentId = route.query.studentId;
const chineseNumbers: { [index: number]: string } = {
  0: '零',
  1: '一',
  2: '二',
  3: '三',
  4: '四',
  5: '五',
  6: '六',
  7: '日',
  8: '八',
  9: '九'
};
const dateValue = ref<number>(0);
const startTime = ref<number>(0);
const endTime = ref<number>(0);
const studentOptions = ref<any[]>([]);
const studentOptionsLoading = ref<boolean>(false);
const isRepeatTime = ref<boolean>(true);
const repeatTime = ref<number>(1);
const pageState = ref<boolean>(true);
const categoryAndSubjectOptions = ref<any[]>([]);
const groupList = ref<any[]>([]);
const classRoomList = ref<any[]>([]);
const teacherOptions = ref<any[]>();
const loading = ref<boolean>(false);
const formLoading = ref<boolean>(false);
const nowDate = new Date();
nowDate.setHours(0, 0, 0, 0);
const sevenDaysLater = new Date(nowDate);
sevenDaysLater.setDate(nowDate.getDate() + 6);
sevenDaysLater.setHours(0, 0, 0, 0);
const dateRange = ref<[number, number]>([nowDate.getTime(), sevenDaysLater.getTime()]);
const weekStartTime = ref<number>(nowDate.getTime());
const scheduleParamsOptions = reactive<QueryScheduleParams>({
  studentId: null,
  classId: null,
  subjectId: null,
  teacherId: null,
  startTime: null,
  endTime: null,
  week: null,
  roomId: null,
  assistantId: null,
  categoryId: null
});

const scheduleList = ref<{ [index: string]: any }>({
  '1': {},
  '2': {},
  '3': {},
  '4': {},
  '5': {},
  '6': {},
  '7': {}
});

const timeKey = ref<string[]>([
  '08:00',
  '09:00',
  '10:00',
  '11:00',
  '12:00',
  '13:00',
  '14:00',
  '15:00',
  '16:00',
  '17:00',
  '18:00',
  '19:00',
  '20:00',
  '21:00',
  '22:00',
  '23:00'
]);

function categoryAndSubjectLoad(option: CascaderOption) {
  model.categoryId = option.value as number;
  return new Promise<void>(resolve => {
    option.children = [];
    querySubject(1, 100, {
      categoryId: option.value as number
    }).then(respone => {
      respone.data?.map(r => {
        option.children?.push({
          label: r.name,
          value: r.id,
          depth: 2,
          isLeaf: true
        });
        return r;
      });
      resolve();
    });
  });
}

async function handleValidateButtonClick() {
  formLoading.value = true;
  const modelStartTime = new Date(startTime.value);
  const modelEndTime = new Date(endTime.value);
  if (modelStartTime.getTime() >= modelEndTime.getTime()) {
    window.$message?.error('开始时间不能大于或等于结束时间');
    formLoading.value = false;
    return;
  }
  const modelDate = new Date(dateValue.value);
  modelStartTime.setFullYear(modelDate.getFullYear(), modelDate.getMonth(), modelDate.getDate());
  modelEndTime.setFullYear(modelDate.getFullYear(), modelDate.getMonth(), modelDate.getDate());
  model.startTime = formatTimestamp(modelStartTime.getTime());
  model.endTime = formatTimestamp(modelEndTime.getTime());
  model.week = modelStartTime.getDay();

  const res = await addSchedule(repeatTime.value, model);
  formLoading.value = false;
  if (!res.status && res.msg !== null) {
    window.$message?.error(res.msg);
    return;
  }
  pageState.value = !pageState.value;
  loadScheduleQuery();
  window.$message?.success('操作成功!');
}

function validateDate(nowtime: [number, number]): boolean {
  if (!nowtime) {
    return false;
  }
  if (nowtime instanceof Array) {
    const differenceInMilliseconds: number = nowtime[1] + 86400000 - nowtime[0];
    const days = Math.floor(differenceInMilliseconds / (1000 * 60 * 60 * 24));
    if (days > 7) {
      return false;
    }
    return true;
  }
  return false;
}

function previousDateSchedule() {
  const startDateTime = new Date(dateRange.value[0] - 1);
  startDateTime.setHours(0, 0, 0, 0);
  const sevenDays = new Date(startDateTime);
  sevenDays.setDate(startDateTime.getDate() - 6);
  sevenDays.setHours(0, 0, 0, 0);
  dateRange.value = [sevenDays.getTime(), startDateTime.getTime()];
  loadScheduleQuery();
}

function nextDateSchedule() {
  const endDateTime = new Date(dateRange.value[1]);
  endDateTime.setHours(24, 0, 0, 0);
  const sevenDays = new Date(endDateTime);
  sevenDays.setDate(endDateTime.getDate() + 6);
  sevenDays.setHours(0, 0, 0, 0);
  dateRange.value = [endDateTime.getTime(), sevenDays.getTime()];
  loadScheduleQuery();
}

function differenceInSevenDays(nowtime: [number, number]): boolean {
  if (!validateDate(nowtime)) {
    scheduleParamsOptions.startTime = '';
    scheduleParamsOptions.endTime = '';
    window.$message?.error('查询时间范围不能超过7天');
    return false;
  }
  scheduleParamsOptions.startTime = formatTimestamp(Number(nowtime[0]));
  scheduleParamsOptions.endTime = formatTimestamp(Number(nowtime[1] + 86399999));

  return true;
}

function loadScheduleQuery() {
  if (differenceInSevenDays(dateRange.value)) {
    loadSchedule();
  }
}

function loadSchedule() {
  loading.value = true;
  querySchedule(scheduleParamsOptions).then(response => {
    scheduleList.value = [];
    for (let i = 1; i <= 7; i += 1) {
      scheduleList.value[i] = {};
      for (let j = 0; j < timeKey.value.length; j += 1) {
        scheduleList.value[i][timeKey.value[j]] = { empty: true, break: false };
      }
    }
    response.data?.forEach((r: any) => {
      if (!r.startTime) return;
      const time = r.startTime
        ?.split(' ')
        .pop()
        .replace(/(\d{2}):\d{2}/, '$1:00');
      const week = new Date(r.startTime).getDay();
      if (time && timeKey.value.indexOf(time) === -1) return;
      if (week && time && r.endTime && r.startTime && scheduleList.value[week][time].empty) {
        r.colspan = new Date(r.endTime).getHours() - new Date(r.startTime).getHours() + 1;
        r.empty = false;
        r.break = false;
        scheduleList.value[week][time] = r;
        let n = 1;
        while (n < r.colspan) {
          const index = timeKey.value.indexOf(time) + n;
          scheduleList.value[week][timeKey.value[index]] = { empty: false, break: true };
          n += 1;
        }
      }
    });
    weekStartTime.value = dateRange.value[0];
    loading.value = false;
  });
}

function getDayOfTheWeekNow(theWeekStartTime: number, weekDate: number): number {
  const week = new Date(theWeekStartTime + weekDate * 86400000).getDay();
  return week === 0 ? 7 : week;
}

function studentOptionsSearch(keyword: string) {
  if (!keyword.length) {
    studentOptions.value = [];
    return;
  }
  studentOptionsLoading.value = true;
  studentOptions.value = [];
  getStudentByKeyword(keyword).then(response => {
    response.data?.forEach(r => {
      studentOptions.value.push({
        label: r.studentName,
        value: r.id
      });
    });
  });
  studentOptionsLoading.value = false;
}

async function findStudent(sId: number) {
  if (sId) {
    studentOptionsLoading.value = true;
    studentOptions.value = [];
    getStudentByKeyword(sId.toString()).then(response => {
      response.data?.forEach(r => {
        studentOptions.value.push({
          label: r.studentName,
          value: r.id
        });
        if (Number(sId) === r.id) {
          scheduleParamsOptions.studentId = Number(sId);
        }
      });
    });
    studentOptionsLoading.value = false;
    loadScheduleQuery();
  }
}

async function loadData() {
  await queryUserAll().then(response => {
    teacherOptions.value = response.data?.map(r => {
      return {
        label: r.relname,
        value: r.id
      };
    });
  });
  await queryCategoryParams(1, 100, {}).then(response => {
    response.data?.map(r => {
      categoryAndSubjectOptions.value.push({
        label: r.name,
        value: r.id,
        depth: 1,
        isLeaf: false
      });
      return r;
    });
  });
  await queryClassAll().then(response => {
    response.data?.map(r => {
      groupList.value.push({
        label: r.name,
        value: r.id
      });
      if (Number(classId) === r.id) {
        scheduleParamsOptions.classId = Number(classId);
      }
      return r;
    });
  });
  await queryClassRoomList(1, 100, {}).then(response => {
    response.data?.map(r => {
      classRoomList.value.push({
        label: r.name,
        value: r.id
      });
      return r;
    });
  });

  await findStudent(Number(studentId));

  loadScheduleQuery();
  if (classId) {
    model.classId = Number(classId);
  }
}

loadData();
</script>
<style scoped>
table {
  table-layout: fixed;
}
th {
  font-size: calc(var(--baseSize, 14px) * 2);
  font-weight: bold;
}

th,
td {
  padding: 16px 12px;
  font-size: var(--baseSize, 14px);
  outline: 1px solid rgb(226, 226, 226);
  text-align: center;
}
td {
  color: rgb(99, 99, 99);
}
</style>
