<template>
  <div class="card">
    <div class="card-body">
      <h2 class="card-title">휴가 신청</h2>
      <p class="require">* 필수입력</p>
      <div class="tbl-wrap">
        <table class="tbl data">
          <tbody>
            <tr>
              <th scope="row">유형 *</th>
              <td>
                <select class="form-select sm" v-model="vacationInfo.vcatnKnd" @change="handleVacationTypeChange">
                  <option value="" disabled hidden>유형 선택</option>
                  <option v-for="(item, idx) of vacationTypes" :key="idx" :value="item.code">{{ item.codeNm }}</option>
                </select>
              </td>
            </tr>
            <tr>
              <th scope="row">시작일 *</th>
              <td>
                <div class="d-flex gap-1">
                  <input type="date" class="form-control sm" v-model="vacationInfo.bgnde" @keydown="preventKeyboard" />
                  <input type="text" class="form-control sm" placeholder="시" style="width: 100px;" v-model="vacationInfo.beginHour" readonly />
                  <input type="text" class="form-control sm" placeholder="분" style="width: 100px;" v-model="vacationInfo.beginMnt" readonly />
                </div>
              </td>
            </tr>
            <tr>
              <th scope="row">종료일 *</th>
              <td>
                <div class="d-flex gap-1">
                  <input type="date" class="form-control sm" v-model="vacationInfo.endde" :readonly="vacationDayCount === 0.5" @keydown="preventKeyboard" />
                  <input type="text" class="form-control sm" placeholder="시" style="width: 100px;" v-model="vacationInfo.endHour" readonly />
                  <input type="text" class="form-control sm" placeholder="분" style="width: 100px;" v-model="vacationInfo.endMnt" readonly />
                </div>
              </td>
            </tr>
            <tr>
              <th scope="row">사용 휴가일</th>
              <td>
                <input type="text" class="form-control sm" v-model="totalDays" readonly />
              </td>
            </tr>
            <tr>
              <th scope="row">승인자 *</th>
              <td>
                <button type="button" title="추가" @click="isOpenApproverModal = true">
                  <PlusCircleFilled />
                </button>
                <HrPopup v-if="isOpenApproverModal" :selectedEmployees="vacationCnsul.sanctnList" idField="confmerId" @select="handleApproverAdd" @close="isOpenApproverModal = false" />
                <div class="approval-container">
                  <SanctnList v-model:lists="vacationCnsul.sanctnList" @delSanctn="handleApproverRemove" />
                </div>
              </td>
            </tr>
            <tr>
              <th scope="row">세부사항</th>
              <td>
                <EditorComponent v-model:contents="vacationCnsul.detailCn" />
              </td>
            </tr>
            <tr class="red" v-if="excessReqst">
              <td colspan="2">금년도 연차 소진으로 인해 내년도 연차를 선 사용하는 휴가 신청건입니다.</td>
            </tr>
          </tbody>
        </table>
      </div>
      <div class="buttons">
        <button type="button" class="btn sm btn-red" @click="handleLoadLastApprovers">이전 승인자 불러오기</button>
        <button type="button" class="btn sm primary" v-if="$isEmpty(pageId)" @click="handleSave">신청</button>
        <template v-else>
          <button type="button" class="btn sm primary" v-if="isReapplyMode" @click="handleReapply">재신청</button>
          <button type="button" class="btn sm primary" v-else @click="handleUpdate">수정</button>
          <button type="button" class="btn sm secondary" @click="handleCancel">취소</button>
        </template>
      </div>
    </div>
  </div>
</template>
<script>
import { PlusCircleFilled } from '@ant-design/icons-vue';
import HrPopup from '../../../component/Popup/HrPopup.vue';
import SanctnList from '../../../component/Sanctn/SanctnFormList.vue';
import EditorComponent from '../../../component/editor/EditorComponent.vue';
// API
import { findVcatnKndsProc, findVcatnProc, saveVcatnProc, findLastVcatnProc, updateVcatnProc, reapplyVcatnProc } from '../../../../resources/api/vcatn';
import { findUserExcessReqstAtProc } from '../../../../resources/api/userYryc';

export default {
  name: 'VacationInsert',

  components: {
    PlusCircleFilled,
    HrPopup,
    SanctnList,
    EditorComponent,
  },

  data() {
    return {
      pageId: null,
      pageMode: null,
      isOpenApproverModal: false,
      vacationDayCount: 0,
      totalDays: 0,
      workConfig: {
        startHour: 9,
        endHour: 18,
        lunchStart: 12,
        lunchEnd: 13,
      },
      vacationInfo: {
        vcatnId: null,
        userId: null,
        vcatnKnd: '',
        deptId: null,
        clsf: null,
        bgnde: null,
        beginHour: null,
        beginMnt: null,
        endde: null,
        endHour: null,
        endMnt: null,
        confmAt: null,
        rgsde: null,
        register: null,
        updde: null,
        updusr: null,
      },
      vacationCnsul: {
        detailCn: null,
        sanctnList: []
      },
      vacationTypes: [],
      approvalCodes: [],
      excessReqst: false,
    };
  },

  watch: {
    // 시작일 변동 시 날짜 재계산
    'vacationInfo.bgnde'(newVal, oldVal) {
      if (newVal !== oldVal) {
        this.handleStartDateChange();
      }
    },
    // 종료일 변동 시 날짜 재계산
    'vacationInfo.endde'(newVal, oldVal) {
      if (newVal !== oldVal) {
        this.validateAndCalculateDays();
      }
    },
  },

  computed: {
    // 재신청 여부
    isReapplyMode() {
      return this.pageMode === 'reapply';
    },
  },

  async created() {
    this.pageId = this.$route.query.id;
    this.pageMode = this.$route.query.type;

    await this.fetchUserExcessReqstAt(); // 사용자 연차 초과 신청 여부 조회
    await this.fetchVacationTypes(); // 휴가 유형 조회
    this.approvalCodes = await this.$findChildCodes('sanctn_code'); // 결재 구분 조회
  },

  mounted() {
    if (!this.$isEmpty(this.pageId)) {
      this.fetchData(); // 상세 조회
    }
  },

  methods: {
    // 사용자 연차 초과 신청 여부 조회
    async fetchUserExcessReqstAt() {
      try {
        const response = await findUserExcessReqstAtProc();
        const result = response.data.data;

        this.excessReqst = result.isNegativeAnnualLeave;
        if (this.excessReqst) {
          const chk = confirm("금년도 연차를 모두 소진하였습니다.\n내년도 연차를 미리 사용하시겠습니까?");
          if (!chk) {
            this.handleNavigation('list');
          }
        } else {
          if (result.isTotalCntOver) {
            alert("이미 금년도 연차 보유 수 만큼 휴가를 신청한 상태입니다.\n마이너스 이월은 기존 휴가 신청이 모두 승인된 뒤 신청 가능합니다.");
            this.handleNavigation('list');
          }
        }
      } catch (error) {
        this.handleError(error);
        this.handleNavigation('list');
      }
    },

    // 휴가 유형 조회
    async fetchVacationTypes() {
      try {
        const response = await findVcatnKndsProc();
        const result = response.data.data;

        this.vacationTypes = result;
      } catch (error) {
        this.handleError(error);
        this.handleNavigation('list');
      }
    },

    // 휴가 정보 조회
    async fetchData() {
      try {
        const response = await findVcatnProc(this.pageId);
        const result = response.data.data;

        this.vacationInfo = {
          vcatnId: result.vcatnId,
          userId: result.userId,
          vcatnKnd: result.vcatnKnd,
          deptId: result.deptId,
          clsf: result.clsf,
          bgnde: result.bgnde,
          beginHour: result.beginHour,
          beginMnt: result.beginMnt,
          endde: result.endde,
          endHour: result.endHour,
          endMnt: result.endMnt,
          confmAt: result.confmAt,
          rgsde: result.rgsde,
          register: result.register,
          updde: result.updde,
          updusr: result.updusr,
        };
        this.vacationCnsul = {
          detailCn: result.detailCn,
          sanctnList: result.sanctnList
        };
      } catch (error) {
        this.handleError(error);
        this.handleNavigation('list');
      }
    },

    // 휴가 유형 변경 핸들러
    handleVacationTypeChange() {
      const selectedVacation = this.vacationTypes.find(item => item.code === this.vacationInfo.vcatnKnd);
      if (!selectedVacation) {
        console.warn('선택된 휴가 유형을 찾을 수 없습니다.');
        return;
      }

      if (selectedVacation.codeValue != 1) {
        this.setHalfDayTime(selectedVacation.codeValue);
        this.handleStartDateChange(); // 반차일 경우 종료일을 시작일과 동일하게 설정
      } else {
        this.vacationDayCount = parseFloat(selectedVacation.codeValue);

        // 전체 근무시간으로 설정
        this.vacationInfo.beginHour = this.workConfig.startHour.toString().padStart(2, '0');
        this.vacationInfo.beginMnt = '00';
        this.vacationInfo.endHour = this.workConfig.endHour.toString().padStart(2, '0');
        this.vacationInfo.endMnt = '00';
        this.calculateTotalDays();
      }
    },

    // 반차 시간 설정
    setHalfDayTime(codeValue) {
      // 전체 실제 근무시간 계산 (점심시간 제외)
      const totalHours = this.workConfig.endHour - this.workConfig.startHour;
      const lunchHours = this.workConfig.lunchEnd - this.workConfig.lunchStart;
      const actualWorkHours = totalHours - lunchHours;
      const halfWorkHours = actualWorkHours / 2;

      this.vacationInfo.beginMnt = '00';
      this.vacationInfo.endMnt = '00';

      if (codeValue === 'AM') {
        this.vacationDayCount = 0.5;
        this.vacationInfo.beginHour = this.workConfig.startHour.toString().padStart(2, '0');
        this.vacationInfo.endHour = this.calculateTimeWithLunch(this.workConfig.startHour, halfWorkHours, 1).toString().padStart(2, '0');
      } else if (codeValue === 'PM') {
        this.vacationDayCount = 0.5;
        this.vacationInfo.beginHour = this.calculateTimeWithLunch(this.workConfig.endHour, halfWorkHours, -1).toString().padStart(2, '0');
        this.vacationInfo.endHour = this.workConfig.endHour.toString().padStart(2, '0');
      }
    },

    // 점심시간을 고려하여 시간 계산 (방향: 1=앞으로, -1=뒤로)
    calculateTimeWithLunch(startTime, workHours, direction = 1) {
      let currentHour = startTime;
      let remainingHours = workHours;

      while (remainingHours > 0) {
        if (direction === 1) {
          // 앞으로 계산 (종료시간 구하기)
          if (currentHour >= this.workConfig.lunchStart && currentHour < this.workConfig.lunchEnd) {
            currentHour++;
          } else {
            currentHour++;
            remainingHours--;
          }
        } else {
          // 뒤로 계산 (시작시간 구하기)
          currentHour--;
          if (!(currentHour >= this.workConfig.lunchStart && currentHour < this.workConfig.lunchEnd)) {
            remainingHours--;
          }
        }
      }

      return currentHour;
    },

    // 시작일 변경 핸들러
    handleStartDateChange() {
      if (!this.vacationInfo.bgnde) {
        return;
      }

      // 반차인 경우 종료일을 시작일과 동일하게 설정
      if (this.vacationDayCount < 1) {
        this.vacationInfo.endde = this.vacationInfo.bgnde;
      }

      this.validateAndCalculateDays();
    },

    // 사용 휴가일 유효성 검사 및 계산
    validateAndCalculateDays() {
      if (!this.vacationInfo.bgnde || !this.vacationInfo.endde) {
        this.totalDays = 0;
        return;
      }

      const startDate = new Date(this.vacationInfo.bgnde);
      const endDate = new Date(this.vacationInfo.endde);

      // 날짜 유효성 검사
      if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
        this.totalDays = 0;
        return;
      }

      // 종료일이 시작일보다 이전인지 확인 (반차가 아닌 경우)
      if (this.vacationDayCount == 1 && endDate < startDate) {
        alert('종료일은 시작일보다 이전일 수 없습니다.');
        this.vacationInfo.endde = this.vacationInfo.bgnde;
        return;
      }

      this.calculateTotalDays();
    },

    // 총 휴가일 계산
    calculateTotalDays() {
      if (!this.vacationInfo.bgnde || !this.vacationInfo.endde) {
        this.totalDays = 0;
        return;
      }

      const startDate = new Date(this.vacationInfo.bgnde);
      const endDate = new Date(this.vacationInfo.endde);

      if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
        this.totalDays = 0;
        return;
      }

      const timeDiff = endDate.getTime() - startDate.getTime();
      const dayDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24)) + 1;

      // 반차의 경우 0.5일, 그 외의 경우 실제 일수 계산
      if (this.vacationDayCount === 0.5) {
        this.totalDays = 0.5;
      } else {
        this.totalDays = Math.max(0, dayDiff);
      }
    },

    // 키보드 입력 방지
    preventKeyboard(event) {
      if (event.key !== 'Tab') {
        event.preventDefault();
      }
    },

    // 승인자 추가 핸들러
    handleApproverAdd(user) {
      const data = {
        confmerId: user.userId,
        confmerNm: user.userNm,
        clsf: user.clsf,
        clsfNm: user.clsfNm,
        sanctnOrdr: this.vacationCnsul.sanctnList.length + 1,
        sanctnIem: 'sanctn_mby_vcatn',
        sanctnSe: this.approvalCodes[0].code,
      };

      this.vacationCnsul.sanctnList.push(data);
      this.isOpenApproverModal = false;
    },

    // 승인자 삭제 핸들러
    handleApproverRemove(idx) {
      this.vacationCnsul.sanctnList.splice(idx, 1);
      this.vacationCnsul.sanctnList.forEach((item, index) => {
        item.sanctnOrdr = index + 1;
      });
    },

    // 이전 승인자 불러오기 핸들러
    async handleLoadLastApprovers() {
      try {
        const response = await findLastVcatnProc();
        const result = response.data.data;

        if (this.$isEmpty(result)) {
          alert("휴가 기록이 존재하지 않아, 이전 승인자를 불러올 수 없습니다.");
          return;
        }

        this.vacationCnsul.sanctnList = result;
      } catch (error) {
        this.handleError(error);
      }
    },

    // 저장 핸들러
    async handleSave() {
      try {
        if (!this.validateForm()) {
          return;
        }

        const data = this.buildSendData();

        const response = await saveVcatnProc(data);
        alert("등록되었습니다.");

        this.handleNavigation('view', response.data.data.pageId);
      } catch (error) {
        this.handleError(error);
      }
    },

    // 수정 핸들러
    async handleUpdate() {
      try {
        if (!this.validateForm()) {
          return;
        }

        const data = this.buildSendData();

        const response = await updateVcatnProc(this.pageId, data);
        alert("수정되었습니다.");

        this.handleNavigation('view', response.data.data.pageId);
      } catch (error) {
        this.handleError(error);
      }
    },

    // 재신청 핸들러
    async handleReapply() {
      try {
        if (!this.validateForm()) {
          return;
        }

        const data = this.buildSendData();

        const response = await reapplyVcatnProc(this.pageId, data);
        alert("재신청되었습니다.");

        this.handleNavigation('view', response.data.data.pageId);
      } catch (error) {
        this.handleError(error);
      }
    },

    // 취소 핸들러
    handleCancel() {
      if (confirm('작성 중인 내용이 삭제됩니다. 계속하시겠습니까?')) {
        this.handleNavigation('view', this.pageId);
      }
    },

    // 페이지 이동 핸들러
    handleNavigation(type, id) {
      const routeMap = {
        'list': { name: this.pageMode === 'sanctns' ? 'PendingApprovalListPage' : 'VcatnListPage' },
        'view': { name: 'VcatnViewPage', query: { id } },
        'insert': { name: 'VcatnInsertPage', query: this.$isEmpty(id) ? {} : { id } },
        'reapply': { name: 'VcatnInsertPage', query: { id, type: 'reapply' } },
      };

      const route = routeMap[type];
      if (route) {
        this.$router.push(route);
      } else {
        alert("올바르지 않은 경로입니다.");
        this.$router.push(routeMap['list']);
      }
    },

    // 에러 핸들러
    handleError(error) {
      const message = error.response?.data?.message || '에러가 발생했습니다.';
      alert(message);
    },

    // 입력값 전체 유효성 검사 유틸리티
    validateForm() {
      if (this.$isEmpty(this.vacationInfo.vcatnKnd)) {
        alert("유형을 선택해 주세요.");
        return false;
      }

      if (this.$isEmpty(this.vacationInfo.bgnde)) {
        alert("시작일을 선택해 주세요.");
        return false;
      }

      if (this.$isEmpty(this.vacationInfo.endde)) {
        alert("종료일을 선택해 주세요.");
        return false;
      }

      if (this.$isEmpty(this.vacationCnsul.sanctnList)) {
        alert("승인자를 선택해 주세요.");
        return false;
      }

      return true;
    },

    // 데이터 가공 유틸리티
    buildSendData() {
      const sanctnList = [];
      for (let sanctn of this.vacationCnsul.sanctnList) {
        sanctnList.push({
          confmerId: sanctn.confmerId,
          clsf: sanctn.clsf,
          sanctnOrdr: sanctn.sanctnOrdr,
          sanctnIem: sanctn.sanctnIem,
          sanctnMbyId: sanctn.sanctnMbyId,
          sanctnSe: sanctn.sanctnSe,
        });
      }

      return {
        userId: this.vacationInfo.userId,
        vcatnKnd: this.vacationInfo.vcatnKnd,
        bgnde: this.vacationInfo.bgnde,
        beginHour: this.vacationInfo.beginHour,
        beginMnt: this.vacationInfo.beginMnt,
        endde: this.vacationInfo.endde,
        endHour: this.vacationInfo.endHour,
        endMnt: this.vacationInfo.endMnt,
        detailCn: this.vacationCnsul.detailCn,
        sanctnList: sanctnList,
      };
    },
  },
};
</script>
<style scoped>
.red th,
.red td {
  text-align: center;
  color: #fb2c36 !important;
  background-color: #fef2f2 !important;
}
</style>