<script setup lang="ts">
import dayjs from 'dayjs'

const props = defineProps<{
  period: anyObj
}>()

const selectedDays: Ref<string[]> = computed(() =>
  props.period.inspectorCourseList.map((course: anyObj) =>
    dayjs(course.courseDate).format('YYYY-MM-DD'),
  ),
)

const calendarMaxDay = computed(() =>
  selectedDays.value
    .map(date => dayjs(date))
    .reduce((max, current) => (current.isAfter(max) ? current : max)),
)

const startDay = computed(() => selectedDays.value[0])
const startDayDayjs = computed(() => dayjs(startDay.value))

const activeMonth = ref(dayjs(props.period.inspectorCourseList[0].courseDate).toDate())
watch(
  () => props.period,
  () => {
    activeMonth.value = dayjs(props.period.inspectorCourseList[0].courseDate).toDate()
  },
)

const calendarHeight = computed(() => {
  const firstDay = dayjs(activeMonth.value).startOf('month')
  const totalDays = firstDay.daysInMonth()
  let startDayOfWeek = firstDay.day() - 1
  if (startDayOfWeek === -1) startDayOfWeek = 6
  const totalRows = Math.ceil((totalDays + startDayOfWeek) / 7)
  const pxValue = totalRows >= 6 ? 67.714285 : 79
  return (pxValue / 1200) * window.innerHeight + 'px'
})

const prevMonthVisible = computed(() => {
  const year = activeMonth.value.getFullYear()
  const month = activeMonth.value.getMonth()
  return (
    year > startDayDayjs.value.year() ||
    (year === startDayDayjs.value.year() && month > startDayDayjs.value.month())
  )
})

const nextMonthVisible = computed(() => {
  const year = activeMonth.value.getFullYear()
  const month = activeMonth.value.getMonth()
  const maxYear = calendarMaxDay.value.year()
  const maxMonth = calendarMaxDay.value.month()
  return year < maxYear || (year === maxYear && month < maxMonth)
})

function changeMonth(offset: number) {
  activeMonth.value = new Date(
    activeMonth.value.getFullYear(),
    activeMonth.value.getMonth() + offset,
  )
}

const getDayStatus = (date: string) => {
  if (!selectedDays.value.includes(date)) {
    return null
  }
  const today = dayjs()
  const courseDate = dayjs(date)
  if (courseDate.isSame(today, 'day')) return 'today'
  if (courseDate.isBefore(today, 'day')) return 'closed'
  return 'pending'
}
</script>

<template>
  <div class="calendar">
    <div class="calendar-header">
      <div class="month-navigation">
        <button v-if="prevMonthVisible" class="prev-month" @click="() => changeMonth(-1)"></button>
        <span class="month-title">{{ activeMonth.getMonth() + 1 }}月</span>
        <button v-if="nextMonthVisible" class="next-month" @click="() => changeMonth(1)"></button>
      </div>
    </div>
    <div class="calendar-body">
      <el-calendar :model-value="activeMonth" class="calendar-table">
        <template #header>
          <div></div>
        </template>
        <template #date-cell="{ data }">
          <div
            :class="[
              'calendar-day',
              {
                'start-day': startDay === data.day,
                selected: selectedDays.includes(data.day),
              },
              getDayStatus(data.day),
            ]"
          >
            {{ data.date.getDate() }}
          </div>
        </template>
      </el-calendar>
      <div class="calendar-legend">
        <span class="legend-item pending">待上课</span>
        <span class="legend-item closed">已上课</span>
        <span class="legend-item today">今日上课</span>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.calendar-day {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;

  &.today {
    background: #92fc90;
  }

  &.closed {
    background: #fff78c;
  }

  &.pending {
    background: #c4b5ff;
  }

  &.start-day {
    &:after {
      font-family: OPPOSans, sans-serif;
      content: '开课时间';
      color: #ff8d3b;
      text-align: center;
      font-size: 1.33vh;
      line-height: 2vh;
      position: absolute;
      top: 0;
    }

    &.pending:after {
      color: #fff;
    }
  }
}

.calendar {
  width: 728px;
  height: 542px + 80px;
  border-radius: 1.33vh;
  overflow: hidden;
  background: #fff;
  filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25));

  :deep(.el-calendar__header) {
    display: none;
  }

  :deep(.el-calendar__body) {
    padding: 0;

    table {
      table-layout: auto;
    }

    th {
      background: #ece5ff;
    }

    th,
    td {
      border: none;
    }

    .el-calendar-day,
    .el-calendar-day:hover {
      background: transparent;
    }

    th,
    .el-calendar-day {
      position: relative;
      padding: 0;
      height: v-bind(calendarHeight);
    }

    .prev,
    .next {
      .calendar-day {
        color: #ccc;
        background: #fafafa;
      }
    }

    .is-selected,
    .is-selected:hover {
      background: transparent;
    }

    th {
      color: $font-color;
      font-family: $font-special, sans-serif;
      font-size: 2vh;
      line-height: 3vh;
    }

    .el-calendar-day {
      color: $font-color;
      font-family: $font-special, sans-serif;
      font-size: 2.33vh;
      line-height: 3.5vh;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    tr {
      position: relative;
    }

    tr::after {
      content: '';
      position: absolute;
      height: 0.17vh;
      top: 0;
      width: 100%;
      left: 0;
      background: repeating-linear-gradient(
        to right,
        #cfc8e3,
        #cfc8e3 8px,
        transparent 8px,
        transparent 16px
      );
    }

    th,
    td {
      position: relative;

      &:not(:last-child):after {
        z-index: 1;
        content: '';
        position: absolute;
        height: 100%;
        bottom: 0;
        right: 0;
        width: 2px;
        background: repeating-linear-gradient(
          to bottom,
          #cfc8e3,
          #cfc8e3 8px,
          transparent 8px,
          transparent 16px
        );
      }
    }
  }
}

.calendar-table {
  height: 39.5vh;
  overflow: auto;
  background: rgba(0, 0, 0, 0.05);
  border-radius: 0 0 1.33vh 1.33vh;
}

.calendar-header {
  height: 6.67vh;
  color: $font-color;
  font-family: $font-special, sans-serif;
  font-size: 3.33vh;
  line-height: 5vh;

  display: flex;
  align-items: center;
  padding: 0 24px 0 24px;
  justify-content: flex-end;

  background:
    url('../../assets/bg-mesh.svg') left bottom,
    linear-gradient(269deg, #adadff 2.25%, #cab5ff 51.93%, #8f9df7 99.65%);

  text-shadow:
    -2px -2px 0 #fff,
    2px -2px 0 #fff,
    -2px 2px 0 #fff,
    2px 2px 0 #fff,
    0px 4px 2px rgba(0, 0, 0, 0.25);
}

.calendar-legend {
  display: flex;
  justify-content: center;
  height: 5.67vh;
  align-items: center;

  color: $font-color;
  font-family: $font-special, sans-serif;
  font-size: 2vh;
  font-style: normal;
  font-weight: 400;
  line-height: 3vh;

  .legend-item {
    border-radius: 2.75vh;
    display: flex;
    align-items: center;

    + .legend-item {
      margin-left: 72px;
    }

    &:before {
      content: ' ';
      display: inline-block;
      width: 56px;
      height: 2vh;
      border-radius: 2.67vh;
      margin-right: 16px;
      box-shadow: 0 0.17vh 0.17vh 0 rgba(0, 0, 0, 0.25);
    }

    &.pending:before {
      background: #c4b5ff;
    }

    &.closed:before {
      background: #fff78c;
    }

    &.today:before {
      background: #92fc90;
    }
  }
}

.month-navigation {
  display: flex;
  align-items: center;
  column-gap: 16px;

  button {
    background: url('../../assets/nav-prev.svg') no-repeat center;
    background-size: 100%;
    width: 48px;
    height: 4vh;

    &.next-month {
      background-image: url('../../assets/nav-next.svg');
    }
  }
}
</style>
