<!-- tab ปฏิทิน หน้าปฏิทินวันหยุด -->
<template>
  <div class="q-mt-md">
    <div class="row q-gutter-sm q-pb-sm main-content">
      <div class="demo-app-main">
        <!-- แสดงปฏิทิน -->
        <FullCalendar
          ref="fullCalendar"
          class="demo-app-calendar"
          :options="calendarOptions"
        >
          <template v-slot:eventContent="arg">
            <b>{{ arg.timeText }}</b>
            <i>{{ arg.event.title }}</i>
            <q-tooltip style="font-size: 15px">{{ arg.event.title }}</q-tooltip>
          </template>
        </FullCalendar>
      </div>
    </div>
    <div class="row q-col-gutter-md">
      <div class="items-center row">
        <q-icon color="blue" name="mdi-circle" class="q-mr-sm" />
        วันทำงาน 5 วัน
      </div>
      <div class="items-center row">
        <q-icon color="orange" name="mdi-circle" class="q-mr-sm" />
        วันทำงาน 6 วัน
      </div>
    </div>
  </div>

  <!-- modal เพิ่มวันหยุด -->
  <q-dialog v-model="modalAdd" persistent>
    <q-card style="min-width: 550px">
      <q-form ref="formDate" @submit.prevent.stop="onSubmit">
        <q-card-section class="row items-center q-pa-sm">
          <div class="text-bold" v-if="showEdit">แก้ไขวันหยุด</div>
          <div class="text-bold" v-else>เพิ่มวันหยุด</div>
          <q-space />
          <q-btn
            icon="close"
            unelevated
            round
            dense
            v-close-popup
            style="color: #ff8080; background-color: #ffdede"
          />
        </q-card-section>
        <q-separator />
        <q-card-section class="q-p-md row q-gutter-y-md">
          <div class="row col-12">
            <div class="col-12" v-if="!showEdit">
              {{ dateThaiRange(dateRange) }}
            </div>
            <datepicker
              v-else
              :readonly="!edit"
              v-model="dateRange"
              :locale="'th'"
              autoApply
              range
              :enableTimePicker="false"
              week-start="0"
            >
              <template #year="{ year }">
                {{ year + 543 }}
              </template>
              <template #year-overlay-value="{ value }">
                {{ parseInt(value + 543) }}
              </template>
              <template #trigger>
                <q-input
                  :class="getClass(edit)"
                  hide-bottom-space
                  :outlined="edit"
                  dense
                  label="วันที่"
                  lazy-rules
                  :borderless="!edit"
                  :model-value="dateThaiRange(dateRange)"
                >
                  <template v-slot:prepend>
                    <q-icon
                      name="event"
                      class="cursor-pointer"
                      style="color: var(--q-primary)"
                    >
                    </q-icon>
                  </template>
                </q-input>
              </template>
            </datepicker>
          </div>

          <q-input
            :class="getClass(edit)"
            hide-bottom-space
            :outlined="edit"
            label="คำอธิบาย"
            dense
            lazy-rules
            :readonly="!edit"
            :borderless="!edit"
            v-model="name"
            autogrow
            :rules="[(val) => (val && val.length > 0) || '']"
          />
          <q-option-group
            v-if="showEdit == false"
            v-model="category"
            :options="categoryOptions"
            color="primary"
            inline
          />
        </q-card-section>
        <q-separator />
        <q-card-actions align="right" class="text-primary">
          <q-btn
            v-if="showEdit && edit"
            flat
            color="red"
            @click="cancelClick()"
            label="ยกเลิกแก้ไข"
          > <!-- icon="mdi-undo"
            <q-tooltip>ยกเลิก</q-tooltip> -->
          </q-btn>
          <q-btn
            v-if="showEdit && edit"
            unelevated
            color="red"
            @click="deleteClick()"
            label="ลบวันหยุด"
          > <!-- icon="mdi-delete"
            <q-tooltip>ลบ</q-tooltip> -->
          </q-btn>
          <q-btn
            v-if="edit"
            unelevated
            color="public"
            label="บันทึก"
            type="submit"
          >
            <!-- icon="mdi-content-save-outline"
            <q-tooltip>บันทึก</q-tooltip> -->
          </q-btn>
          <q-btn
            v-if="!edit"
            outline
            color="primary"
            @click="editClick"
            label="แก้ไขข้อมูล"
          >
            <!-- icon="mdi-pencil-outline"
            <q-tooltip>แก้ไขข้อมูล</q-tooltip> -->
          </q-btn>
        </q-card-actions>
      </q-form>
    </q-card>
  </q-dialog>

  <!-- modal ลบวันหยุด -->
  <q-dialog v-model="modalDelete" persistent>
    <q-card style="min-width: 550px">
      <q-card-section class="row items-center q-pb-xs">
        <div class="text-bold">ต้องการลบข้อมูลนี้หรือไม่?</div>
        <q-space />
        <q-btn
          icon="close"
          unelevated
          round
          dense
          v-close-popup
          style="color: #ff8080; background-color: #ffdede"
        />
      </q-card-section>
      <q-separator />
      <q-card-section class="row items-center">
        <div class="q-pr-md">
          <q-avatar
            icon="mdi-trash-can-outline"
            font-size="25px"
            size="lg"
            color="red-1"
            text-color="red"
          />
        </div>
        <div class="col text-dark">
          <span>ข้อมูลที่กำลังถูกลบนี้จะมีผลใช้งานทันที</span>
        </div>
      </q-card-section>
      <q-separator />
      <q-card-actions align="right" class="bg-white text-teal">
        <q-btn label="ยกเลิก" flat color="grey-8" @click="cancelClick" />
        <q-btn label="ตกลง" color="primary" @click="deleteData" />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>

<script setup lang="ts">
import type { QTableProps } from "quasar";
import { onMounted, ref, watch } from "vue";
import FullCalendar from "@fullcalendar/vue3";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import allLocales from "@fullcalendar/core/locales-all";
import listPlugin from "@fullcalendar/list";
import http from "@/plugins/http";
import config from "@/app.config";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import type {
  RequestItemsObject,
  DataDateRowObject,
  DataDateAddObject,
} from "@/modules/01_metadata/interface/request/Calendar";
import { useDataStore } from "@/stores/data";

const props = defineProps({
  dateYear: {
    //filter ปี วันหยุด
    type: Number,
    default: () => new Date().getFullYear(),
  },
  dateMonth: {
    //filter เดือน วันหยุด
    type: Number,
    default: () => new Date().getMonth(),
  },
  refreshData: {
    //หน้า main มีการอัพเดทค่าให้ refresh data
    type: Boolean,
    required: true,
  },
  fetchDataSummaryCalendar: {
    //ฟังก์ชันอัพเดทสรุปวันหยุด
    type: Function,
    default: () => console.log("not function"),
  },
});

const store = useDataStore();
const { loaderPage } = store;
const mixin = useCounterMixin(); //เรียกฟังก์ชันกลาง
const { success, dateToISO, date2Thai, messageError, showLoader, hideLoader } =
  mixin;
const $q = useQuasar(); //ใช้ noti quasar
const modalAdd = ref<boolean>(false); //modal เพิ่มวันหยุด
const modalDelete = ref<boolean>(false); //modal ลบวันหยุด
const edit = ref<boolean>(false); //modal เลือกวันหยุดกับวันลบวันหยุด
const showEdit = ref<boolean>(false); //กด event แก้ไขหรือเพิ่ม
const name = ref<string>(""); //ชื่อวันหยุด
const type = ref<string>(""); //ประเภทวันหยุด
const isSpecial = ref<boolean>(true); //เช็ควันหยุด
const id = ref<string>(""); //id ที่แก้ไขวันหยุด
const fullCalendar = ref<any>(); //ref calendar
const dateRange = ref<[Date, Date]>([new Date(), new Date()]); //วันที่ ที่เพิ่มเป็นวันหยุด
const formDate = ref<any>(); //ref เพิ่ม แก้ไข วันหยุดสำหรับ validate

const category = ref<string>("all");
const categoryOptions = ref<any>([
  {
    label: "ทั้งหมด",
    value: "all",
  },
  {
    label: "ทำงาน 5 วัน",
    value: "normal",
  },
  {
    label: "ทำงาน 6 วัน",
    value: "6days",
  },
]);
const dataHistory = ref<RequestItemsObject[]>([]);
const dataNormalRaw = ref<RequestItemsObject[]>([]);
const dataSixDaysRaw = ref<RequestItemsObject[]>([]);

/**
 * เรียกฟังก์ชันทั้งหมดตอนเรียกใช้ไฟล์นี้
 */
onMounted(async () => {
  hideLoader();
  const calen = fullCalendar.value.getApi();
  const date = new Date(props.dateYear, props.dateMonth);
  calen.gotoDate(date);
  await fetchData();
});

/**
 * ค่า props(วันเดือนปีที่เลือก) ตอนอัพเดท ค่าฏิทินให้อัพเดทใหม่
 */
watch(props, async (count, prevCount) => {
  const calen = fullCalendar.value.getApi();
  const date = new Date(props.dateYear, props.dateMonth);
  calen.gotoDate(date);
  await fetchData();
});

/**
 * เลือกค่าปฏิทินในช่องว่าง
 * @param selectInfo ค่าที่เลือกในฏิทิน
 */
const handleDateSelect = async (selectInfo: any) => {
  edit.value = true;
  category.value = "all";
  selectInfo.start;
  const checkNormalDate = dataNormalRaw.value.filter(
    (r: RequestItemsObject) =>
      dateToISO(new Date(r.holidayDate)) == dateToISO(selectInfo.start)
  );
  const checkSixDaysDate = dataSixDaysRaw.value.filter(
    (r: RequestItemsObject) =>
      dateToISO(new Date(r.holidayDate)) == dateToISO(selectInfo.start)
  );
  if (checkNormalDate.length == 0 || checkSixDaysDate.length == 0) {
    name.value = "";
    isSpecial.value = true;
    dateRange.value = [
      selectInfo.startStr,
      new Date(
        new Date(selectInfo.endStr).setDate(
          new Date(selectInfo.endStr).getDate() - 1
        )
      ),
    ];
    showEdit.value = false;
    modalAdd.value = true;
  }
};

/**
 * เลือกค่า event ในปฏิทิน
 * @param selectInfo ค่าที่เลือกในฏิทิน
 */
const handleEventClick = async (selectInfo: any) => {
  modalAdd.value = true;
  edit.value = false;
  showEdit.value = true;
  name.value = selectInfo.event.title;
  type.value = selectInfo.event.id;
  isSpecial.value = true;
  id.value = selectInfo.event.groupId;
  dataHistory.value = selectInfo.event.extendedProps.dataRangeRow;
  dateRange.value = [
    selectInfo.event.startStr,
    selectInfo.event.endStr == ""
      ? selectInfo.event.startStr
      : dateToISO(
          new Date(
            new Date(selectInfo.event.endStr).setDate(
              new Date(selectInfo.event.endStr).getDate() - 1
            )
          )
        ),
  ];
};

/**
 * กดปุ่มแก้ไขให้แสดง modal แก้ไข
 */
const editClick = async () => {
  showEdit.value = true;
  edit.value = true;
};

/**
 * กดปุ่มลบให้แสดง modal ลบ
 */
const deleteClick = async () => {
  modalDelete.value = true;
};

/**
 * ปุ่มยกเลิกให้ย้อนกลับไป modal เลือกแก้ไขหรือลบ
 */
const cancelClick = async () => {
  modalDelete.value = false;
  modalAdd.value = true;
  edit.value = false;
};

/**
 * option calendar
 */
const calendarOptions = ref<any>({
  plugins: [
    dayGridPlugin,
    timeGridPlugin,
    interactionPlugin, // needed for dateClick
    listPlugin,
  ],
  headerToolbar: null,
  selectable: true,
  select: handleDateSelect,
  eventClick: handleEventClick,
  locale: "th",
  locales: allLocales,
  height: "100%",
  eventColor: "#e4f3ff",
  eventTextColor: "#50a5fc",
  eventBorderColor: "#50a5fc",
  events: <any>[],
  firstDay: 0,
});

/**
 * ปุ่มบันทึกข้อมูลวันหยุด
 */
const onSubmit = async () => {
  if (showEdit.value === true) {
    await editData();
  } else {
    await addDate();
  }
};

/**
 * fetch วันหยุดในปฏิทิน
 */
const fetchData = async () => {
  calendarOptions.value.events = [];
  showLoader();
  await http
    .get(
      config.API.listHolidayHistoryYearMonth(
        props.dateYear,
        props.dateMonth + 1
      )
    )
    .then((res) => {
      const dataNormal = res.data.result.normal;
      const dataSixDays = res.data.result.sixDays;
      const dateStart = ref<Date | null>();
      const firstEvent = ref<boolean>(true);
      const dateRow = ref<DataDateRowObject[]>([]);
      dataNormalRaw.value = res.data.result.normal;
      dataSixDaysRaw.value = res.data.result.sixDays;
      dataNormal.map((e: RequestItemsObject, index: number) => {
        dateRow.value.push({
          holidayDate: new Date(e.holidayDate),
          name: e.name,
          isSpecial: true,
          id: e.id,
        });
        if (
          index == dataNormal.length - 1 ||
          dataNormal[index + 1].name != e.name ||
          (dataNormal[index + 1].name == e.name &&
            dateToISO(new Date(dataNormal[index + 1].holidayDate)) !=
              dateToISO(
                new Date(
                  new Date(e.holidayDate).setDate(
                    new Date(e.holidayDate).getDate() + 1
                  )
                )
              ))
        ) {
          firstEvent.value = true;
          calendarOptions.value.events.push({
            id: "normal",
            groupId: e.id,
            title:
              dateToISO(new Date(e.holidayDate)) ==
              dateToISO(new Date(e.originalDate))
                ? e.name
                : `ชดเชย ${e.name}`,
            start: dateStart.value ? dateStart.value : new Date(e.holidayDate),
            end: new Date(
              new Date(e.holidayDate).setDate(
                new Date(e.holidayDate).getDate() + 1
              )
            ),
            isSpecial: true,
            allDay: true,
            dataRangeRow: dateRow.value,
            backgroundColor: "#CCE5FF",
            textColor: "#0080FF",
          });
          dateStart.value = null;
          dateRow.value = [];
        } else if (firstEvent.value == true) {
          firstEvent.value = false;
          dateStart.value = new Date(e.holidayDate);
        }
      });
      dataSixDays.map((e: RequestItemsObject, index: number) => {
        dateRow.value.push({
          holidayDate: new Date(e.holidayDate),
          name: e.name,
          isSpecial: true,
          id: e.id,
        });
        if (
          index == dataSixDays.length - 1 ||
          dataSixDays[index + 1].name != e.name ||
          (dataSixDays[index + 1].name == e.name &&
            dateToISO(new Date(dataSixDays[index + 1].holidayDate)) !=
              dateToISO(
                new Date(
                  new Date(e.holidayDate).setDate(
                    new Date(e.holidayDate).getDate() + 1
                  )
                )
              ))
        ) {
          firstEvent.value = true;
          calendarOptions.value.events.push({
            id: "sixdays",
            groupId: e.id,
            title:
              dateToISO(new Date(e.holidayDate)) ==
              dateToISO(new Date(e.originalDate))
                ? e.name
                : `ชดเชย ${e.name}`,
            start: dateStart.value ? dateStart.value : new Date(e.holidayDate),
            end: new Date(
              new Date(e.holidayDate).setDate(
                new Date(e.holidayDate).getDate() + 1
              )
            ),
            isSpecial: true,
            allDay: true,
            dataRangeRow: dateRow.value,
            backgroundColor: "#FFE5CC",
            textColor: "#FF8000",
          });
          dateStart.value = null;
          dateRow.value = [];
        } else if (firstEvent.value == true) {
          firstEvent.value = false;
          dateStart.value = new Date(e.holidayDate);
        }
      });
    })
    .catch((e) => {
      messageError($q, e);
    })
    .finally(async () => {
      await props.fetchDataSummaryCalendar();
    });
};

/**
 * บันทึกแก้ไขวันหยุด
 */
const editData = async () => {
  await formDate.value.validate().then(async (result: boolean) => {
    if (result) {
      const dataEdit = ref<DataDateAddObject[]>([]);
      let i = 0;
      const dateStart = ref<Date>(dateRange.value[0]);
      do {
        i = i + 1;
        dataEdit.value.push({
          year: new Date(dateStart.value).getFullYear(),
          holidayDate: dateToISO(new Date(dateStart.value)),
          name: name.value,
          isSpecial: true,
        });
        dateStart.value = new Date(
          new Date(dateStart.value).setDate(
            new Date(dateStart.value).getDate() + 1
          )
        );
      } while (new Date(dateStart.value) <= new Date(dateRange.value[1]));

      const _dataHistory = ref<RequestItemsObject[]>([]);
      dataHistory.value.map((e: RequestItemsObject, index: number) => {
        _dataHistory.value.push({
          ...e,
          holidayDate: dateToISO(new Date(e.holidayDate)),
        });
      });

      showLoader();
      await http
        .post(config.API.listHolidayHistoryEdit(type.value), {
          history: _dataHistory.value,
          updated: dataEdit.value,
        })
        .then((res) => {
          modalAdd.value = false;
          success($q, "แก้ไขข้อมูลสำเร็จ");
        })
        .catch((e) => {
          messageError($q, e);
        })
        .finally(async () => {
          await fetchData();
        });
    }
  });
};

/**
 * บันทึกเพิ่มวันหยุด
 */
const addDate = async () => {
  await formDate.value.validate().then(async (result: boolean) => {
    if (result) {
      const dataAdd = ref<DataDateAddObject[]>([]);
      let i = 0;
      const dateStart = ref<Date>(dateRange.value[0]);
      do {
        i = i + 1;
        dataAdd.value.push({
          year: new Date(dateStart.value).getFullYear(),
          holidayDate: dateToISO(new Date(dateStart.value)),
          name: name.value,
          isSpecial: true,
        });
        dateStart.value = new Date(
          new Date(dateStart.value).setDate(
            new Date(dateStart.value).getDate() + 1
          )
        );
      } while (new Date(dateStart.value) <= new Date(dateRange.value[1]));
      showLoader();
      await http
        .post(config.API.listHolidayHistoryAdd(category.value), dataAdd.value)
        .then((res) => {
          modalAdd.value = false;
          success($q, "เพิ่มข้อมูลสำเร็จ");
        })
        .catch((e) => {
          messageError($q, e);
        })
        .finally(async () => {
          await fetchData();
        });
    }
  });
};

/**
 * ลบข้อมูลวันหยุด
 */
const deleteData = async () => {
  modalDelete.value = false;
  const dataDelete = ref<DataDateAddObject[]>([]);
  let i = 0;
  const dateStart = ref<Date>(dateRange.value[0]);
  do {
    i = i + 1;
    dataDelete.value.push({
      year: new Date(dateStart.value).getFullYear(),
      holidayDate: dateToISO(new Date(dateStart.value)),
      name: name.value,
      isSpecial: true,
    });
    dateStart.value = new Date(
      new Date(dateStart.value).setDate(new Date(dateStart.value).getDate() + 1)
    );
  } while (new Date(dateStart.value) <= new Date(dateRange.value[1]));
  showLoader();
  await http
    .post(config.API.listHolidayHistoryDelete(type.value), dataDelete.value)
    .then((res) => {
      success($q, "ลบข้อมูลสำเร็จ");
    })
    .catch((e) => {
      messageError($q, e);
    })
    .finally(async () => {
      modalAdd.value = false;
      await fetchData();
    });
};

/**
 * แปลงช่วงวันที่ถ้า2ค่าเป็นวันเดียวกันจะโชววันเดียวแต่ถ้าไม่เท่ากันจะแสดงเป็นช่วง
 * @param val ช่วงวันที่
 */
const dateThaiRange = (val: [Date, Date]) => {
  if (val === null) {
  } else if (date2Thai(val[0]) === date2Thai(val[1])) {
    return `${date2Thai(val[0])}`;
  } else {
    return `${date2Thai(val[0])} - ${date2Thai(val[1])} `;
  }
};

const getClass = (val: boolean) => {
  return {
    "full-width inputgreen cursor-pointer": val,
    "full-width cursor-pointer": !val,
  };
};
</script>

<style scope lang="scss">
.main-content {
  height: 70vh;
}

.color-main {
  color: #18a259;
}

.padding-content {
  padding: 10px;
}

.demo-app-main {
  flex-grow: 1;
  /* padding: 3em; */
}

.fc {
  /* the calendar root */
  max-width: 1100px;
  margin: 0 auto;
  background-color: white;
  border-radius: 10px;
}

.fc-day-today {
  background-color: rgb(255, 255, 255) !important;
}

// .fc-day-sun {
//   background-color: rgba(207, 205, 205, 0.177) !important;
//   width: 80px;
// }

// .fc-day-sat {
//   background-color: rgba(207, 205, 205, 0.177) !important;
//   width: 80px;
// }

.fc-day-today .fc-daygrid-day-number {
  display: flex;
  justify-content: center;
  align-items: center;
  /* border: 2px solid #17a259; */
  border-radius: 50%;
  height: 25px;
  width: 25px;
  font-weight: bold;
  color: white !important;
  background: #17a259;
}

.fc-day-today .fc-daygrid-day-frame {
  padding: 5%;
}

.fc .fc-button-group > .fc-button {
  color: black;
  background-color: #fafafa;
  border: none;
}

.fc .fc-button-group > .fc-button:active {
  color: white;
  background-color: #22a15e;
  border: none;
}

.fc .fc-button-group > .fc-button.fc-button-active {
  color: white;
  background-color: #22a15e;
  border: none;
}

.fc-header-toolbar {
  background-color: white;
  padding: 0px 10px 0px 10px;
  border-radius: 10px 10px 0px 0px;
}

.fc .fc-scrollgrid-liquid > thead {
  background-color: #f8f8f8;
}

.dp-custom-cell {
  border-radius: 50%;
}

.dp__today {
  border: 1px solid var(--q-primary);
}

.dp__range_end,
.dp__range_start,
.dp__active_date {
  background: var(--q-primary);
  color: var(--dp-primary-text-color);
}

.datepicker .q-field__label {
  padding-left: 5px;
}

.datepicker .q-field__messages {
  padding-left: 20px;
}

.datepicker .q-field__native {
  padding-left: 5px;
  color: var(--q-primary) !important;
}

.datepicker .q-field__prepend {
  padding-left: 6px;
}

.datepicker .q-field__append {
  padding-right: 6px;
}

.datepicker .q-field__after {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  font-weight: 500;
}

.fc .fc-popover {
  z-index: 6000;
}

.fc-direction-ltr .fc-daygrid-event.fc-event-end,
.fc-direction-rtl .fc-daygrid-event.fc-event-start {
  cursor: pointer;
}

.subName {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  font-weight: 500;
}

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

.fc-event {
  overflow: hidden;
  border-color: transparent !important;
  font-weight: 500;
}

.fc-event-main {
  text-align: center;
}

.fc-direction-ltr .fc-daygrid-event.fc-event-end,
.fc-direction-rtl .fc-daygrid-event.fc-event-start {
  padding-left: 0px;
}
</style>
