<template>
  <div class="periodCard" :class="{ 'periodCard-active': markedTimeRangeIds.includes(props.id) }">
    <div class="dayRrange">
      <el-select
        class="daySelect"
        v-model="timeItem.startDay"
        placeholder="开始日期"
        @change="changeDay"
      >
        <el-option
          v-for="item in dayOptions"
          :key="item.value"
          :label="item.label"
          :value="item.value"
          :disabled="timeItem.endDay && item.value > timeItem.endDay"
        >
        </el-option>
      </el-select>
      <div class="divider">-</div>
      <el-select
        class="daySelect"
        v-model="timeItem.endDay"
        placeholder="结束日期"
        @change="changeDay"
      >
        <el-option
          v-for="item in dayOptions"
          :key="item.value"
          :label="item.label"
          :value="item.value"
          :disabled="timeItem.startDay && item.value < timeItem.startDay"
        >
        </el-option>
      </el-select>
    </div>
    <div class="timeRange" v-for="item in timeItem.timeRangeList" :key="item.id">
      <div class="time-border" :class="{ 'time-border-active': markedTimes.includes(item.id) }">
        <el-time-picker
          v-model="item.startTime"
          format="HH:mm"
          value-format="HH:mm"
          :teleported="false"
          :editable="false"
          placeholder="开始时间"
          :disabled-hours="() => disabledHours(item.id, 0)"
          :disabled-minutes="(hour) => disabledMinutes(hour, item.id, 0)"
          @focus="handleOpen(item.id, 0)"
          @blur="handleBlur(item.id)"
        />
        <div class="divider">-</div>
        <el-time-picker
          v-model="item.endTime"
          format="HH:mm"
          value-format="HH:mm"
          :teleported="false"
          :editable="false"
          placeholder="结束时间"
          :disabled-hours="() => disabledHours(item.id, 1)"
          :disabled-minutes="(hour) => disabledMinutes(hour, item.id, 1)"
          @focus="handleOpen(item.id, 1)"
          @blur="handleBlur(item.id)"
        />
      </div>
      <el-icon
        size="18px"
        color="#d0d0d0"
        @click="handleDeleteTimeRange(item.id)"
        style="cursor: pointer"
      >
        <CircleClose />
      </el-icon>
    </div>
    <div class="timeAdd" @click="handleAddTimeRange">
      <el-icon color="#d0d0d0"><Plus /></el-icon>
    </div>
    <div class="paramOptIcons">
      <el-icon size="16px" @click="deleteTimeRange(props.id)"><Delete /></el-icon>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { computed, ref } from 'vue';
  import { TimePeriodItem } from './types';
  import { Plus, Delete, CircleClose } from '@element-plus/icons-vue';
  import useCameraAlgoStore from '../../store/useCameraAlgoStore';
  import { storeToRefs } from 'pinia';
  import { ElMessage } from 'element-plus';
  import { uid } from 'uid';

  const props = defineProps<{ id: string }>();

  const cameraAlgoStore = useCameraAlgoStore();
  const { selectedAlgoDetail, markedTimeRangeIds } = storeToRefs(cameraAlgoStore);
  const { deleteTimeRange } = cameraAlgoStore;

  const dayOptions = [
    {
      value: 1,
      label: '周一',
    },
    {
      value: 2,
      label: '周二',
    },
    {
      value: 3,
      label: '周三',
    },
    {
      value: 4,
      label: '周四',
    },
    {
      value: 5,
      label: '周五',
    },
    {
      value: 6,
      label: '周六',
    },
    {
      value: 7,
      label: '周日',
    },
  ];

  const markedTimes = ref<string[]>([]);
  const openTimeId = ref<string>('');
  const openTimeType = ref<number | null>();

  const timeItem = computed(
    () =>
      selectedAlgoDetail.value.timeRangeArr.find((item) => item.id === props.id) ||
      ({} as TimePeriodItem),
  );

  const changeDay = () => {
    if (timeItem.value.startDay && timeItem.value.endDay) {
      let isConflict = false;
      //判断日期是否冲突
      const otherDays = selectedAlgoDetail.value.timeRangeArr.filter(
        (item) => item.id !== props.id,
      );
      for (let i = 0; i < otherDays.length; i++) {
        const dayRange = otherDays[i];
        if (
          betweenTwoDays(timeItem.value.startDay, dayRange.startDay!, dayRange.endDay!) ||
          betweenTwoDays(timeItem.value.endDay, dayRange.startDay!, dayRange.endDay!)
        ) {
          isConflict = true;
          break;
        }
      }
      if (isConflict) {
        ElMessage.error('日期存在冲突');
        markedTimeRangeIds.value.push(props.id);
        return;
      }
      markedTimeRangeIds.value = markedTimeRangeIds.value.filter((id) => id !== props.id);
      //如果不冲突，排序
      selectedAlgoDetail.value.timeRangeArr.sort((a, b) => {
        return a.startDay! - b.endDay!;
      });
    }
  };

  const handleBlur = (curId: string) => {
    openTimeId.value = '';
    openTimeType.value = null;
    const curTimes = timeItem.value.timeRangeList.find((item) => item.id === curId);
    if (curTimes!.startTime && curTimes!.endTime) {
      // 检查时间是否冲突
      let isConflict = false;
      const otherTimes = timeItem.value.timeRangeList.filter((item) => item.id !== curId);
      for (let i = 0; i < otherTimes.length; i++) {
        const item = otherTimes[i];
        if (
          betweenTwoTimes(curTimes!.startTime, item.startTime, item.endTime) ||
          betweenTwoTimes(curTimes!.endTime, item.startTime, item.endTime)
        ) {
          isConflict = true;
          break;
        }
      }
      if (isConflict) {
        ElMessage.error('时间存在冲突');
        markedTimes.value.push(curId);
        return;
      }
      markedTimes.value = markedTimes.value.filter((id) => id !== curId);
      //如果不冲突，排序
      timeItem.value.timeRangeList.sort((a, b) => {
        return hm2Minutes(a.startTime) - hm2Minutes(b.endTime);
      });
    }
  };

  const betweenTwoDays = (day: number, start: number, end: number) => {
    if (day <= end && day >= start) return true;
    return false;
  };

  const betweenTwoTimes = (time: string, start: string, end: string) => {
    if (hm2Minutes(time) <= hm2Minutes(end) && hm2Minutes(time) >= hm2Minutes(start)) {
      return true;
    }
    return false;
  };

  const handleOpen = (curId: string, type: number) => {
    openTimeType.value = type;
    openTimeId.value = curId;
  };

  const disabledHours = (curId: string, type: number) => {
    if (openTimeId.value !== curId || openTimeType.value !== type) {
      return [];
    }
    let ret = [] as number[];
    const curTime = timeItem.value.timeRangeList.find((item) => item.id === curId);
    if (type === 0) {
      //选择开始时间
      if (curTime!.endTime) {
        const [h, m] = curTime!.endTime.split(':').map(Number);
        if (m === 0) {
          ret = ret.concat(makeRange(h, 23));
        } else {
          ret = ret.concat(makeRange(getH(h + 1), 23));
        }
      }
    }
    if (type == 1) {
      //选择结束时间
      if (curTime!.startTime) {
        const [h, m] = curTime!.startTime.split(':').map(Number);
        if (m === 59) {
          ret = ret.concat(makeRange(0, h));
        } else {
          ret = ret.concat(makeRange(0, getH(h - 1)));
        }
      }
    }
    return ret;
  };

  const disabledMinutes = (hour: number, curId: string, type: number) => {
    if (openTimeId.value !== curId || openTimeType.value !== type) {
      return [];
    }
    let ret = [] as number[];
    const curTime = timeItem.value.timeRangeList.find((item) => item.id === curId);
    if (type === 0) {
      //选择开始时间
      if (curTime!.endTime) {
        const [h, m] = curTime!.endTime.split(':').map(Number);
        if (hour == h) {
          ret = ret.concat(makeRange(m, 59));
        }
      }
    }
    if (type == 1) {
      //选择结束时间
      if (curTime!.startTime) {
        const [h, m] = curTime!.startTime.split(':').map(Number);
        if (hour == h) {
          ret = ret.concat(makeRange(0, m));
        }
      }
    }
    return ret;
  };

  const makeRange = (start: number, end: number): number[] => {
    let result: number[] = [];
    for (let i = start; i <= end; i++) {
      result.push(i);
    }
    return result;
  };

  const handleDeleteTimeRange = (curId: string) => {
    timeItem.value.timeRangeList = timeItem.value.timeRangeList.filter((item) => item.id !== curId);
    markedTimes.value = markedTimes.value.filter((id) => id !== curId);
  };

  const handleAddTimeRange = () => {
    const emptyList = timeItem.value.timeRangeList.filter(
      (item) => item.startTime === '' || item.endTime === '',
    );
    if (emptyList && emptyList.length > 0) {
      emptyList.forEach((time) => markedTimes.value.push(time.id));
      ElMessage.error('请填写完整时间段');
      return;
    }
    if (markedTimes.value.length > 0) {
      ElMessage.error('请先解决时间段冲突');
      return;
    }
    timeItem.value.timeRangeList.push({ id: uid(), startTime: '', endTime: '' });
  };

  const getD = (d) => {
    if (d < 1) {
      return 1;
    } else if (d > 7) {
      return 7;
    } else {
      return d;
    }
  };

  const getH = (h) => {
    if (h < 0) {
      return 0;
    } else if (h > 23) {
      return 23;
    } else {
      return h;
    }
  };

  const getM = (m) => {
    if (m < 0) {
      return 0;
    } else if (m > 59) {
      return 23;
    } else {
      return m;
    }
  };

  const hm2Minutes = (hm: string) => {
    const [h, m] = hm.split(':').map(Number);
    return h * 60 + m;
  };

  const checkValid = () => {
    if (markedTimes.value.length > 0) {
      return 0; // 存在冲突时间段
    }
    const emptyTimes = timeItem.value.timeRangeList.filter(
      (item) => !item.startTime || !item.endTime,
    );
    if (emptyTimes && emptyTimes.length > 0) {
      emptyTimes.forEach((val) => markedTimes.value.push(val.id));
      return 1; // 存在缺失时间段
    }
    if (timeItem.value.timeRangeList.length === 0) {
      return 2; // 至少有一个时间段
    }
    return 3; // 检验成功
  };

  defineExpose({ checkValid });
</script>

<style scoped lang="scss">
  .periodCard {
    position: relative;
    width: 294px;
    background: #0000000a;
    border-radius: 5px;
    border: 1px solid #e8ecf2;
    padding: 3px;
    margin: 0 5px 5px 5px;

    &-active {
      border: 1px solid #ff0000ab;
    }
  }

  .paramOptIcons {
    position: absolute;
    top: 6px;
    right: 6px;
    display: flex;
    justify-content: space-between;
    color: #00000026;
    cursor: pointer;
  }

  .dayRrange {
    display: flex;
    align-items: center;
  }

  .timeRange {
    display: flex;
    align-items: center;
  }

  .time-border {
    display: flex;
    align-items: center;
    border: 1px solid transparent;

    &-active {
      border: 1px solid #ff0000ab;
    }
  }

  .divider {
    color: #00000040;
  }

  .daySelect {
    width: 112px;
    margin: 5px;
  }

  .timeAdd {
    width: 240px;
    height: 26px;
    margin: 5px;
    border-radius: 4px;
    background: #ebebeb;
    border: 1px dashed #00000026;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  :deep(.el-date-editor) {
    width: 112px;
    margin: 5px;

    .el-input__prefix {
      order: 1;
    }

    .el-input__icon {
      margin: 0;
    }
  }

  :deep(.el-time-panel__footer) {
    display: none;
  }
</style>
