<template>
  <div class="gantt-container">
    <!-- Calendar: เชื่อมกับ selectedDate -->
    <GanttCalendar v-model:modelValue="selectedDate" />

    <!-- Gantt Chart UI -->
    <div class="gantt-chart">
      <!-- Header: Time Scale -->
      <div class="header">
        <div class="machine-label"></div>
        <div class="time-scale">
          <div
            v-for="hour in hours"
            :key="hour"
            class="time-cell"
          >
            {{ formatHour(hour) }}
          </div>
        </div>
      </div>

      <!-- Rows: เครื่องจักรแต่ละตัว -->
      <div class="rows">
        <div
          v-for="machine in machines"
          :key="machine.id"
          class="row"
          @dragover.prevent="onDragOver($event)"
          @drop="onDrop($event, machine.machineID)"
        >
          <div class="machine-label">
            {{ machine.machineID }}
          </div>
          <div class="row-timeline">
            <!-- เส้นแนวตั้ง (Grid Lines) -->
            <div
              v-for="hour in hours"
              :key="'line-' + hour"
              class="vertical-line"
              :style="getLineStyle(hour)"
            ></div>

            <!-- แสดง Order ที่ตรงกับวันที่ (selectedDate), Page, และ Machine -->
            <div
              v-for="order in filteredOrders(machine.machineID)"
              :key="order.queueID"
              class="order"
              :class="{ 'faded': draggingOrder && draggingOrder.queueID === order.queueID }"
              :style="getOrderStyle(order)"
            >
              <!-- Handle สำหรับ Resize ด้านซ้าย -->
              <div
                class="resize-handle left"
                @mousedown="onResizeStart($event, order, 'left')"
              ></div>

              <!-- ส่วนกลางของ Order ใช้สำหรับลาก และเปิด Dialog เมื่อคลิก -->
              <div
                class="order-content"
                draggable="true"
                @dragstart="onDragStart($event, order)"
                @dragend="onDragEnd($event, order)"
                @click.stop="openOrderDialog(order)"
              >
                {{ order.orderID }} ({{ getTimeString(order.startTime) }} - {{ getTimeString(order.finishTime) }})
              </div>

              <!-- Handle สำหรับ Resize ด้านขวา -->
              <div
                class="resize-handle right"
                @mousedown="onResizeStart($event, order, 'right')"
              ></div>
            </div>
          </div>
        </div>
      </div>

      <!-- Ghost Order ขณะลาก -->
      <div v-if="ghostOrder" class="drag-ghost" :style="ghostStyle">
        {{ ghostOrder.orderID }} ({{ getTimeString(ghostOrder.startTime) }} - {{ getTimeString(ghostOrder.finishTime) }})
      </div>

      <v-divider :thickness="7"></v-divider>

      <!-- Pagination -->
      <div class="pagination">
        <button
          v-for="p in pages"
          :key="p"
          :class="['page-btn', { active: p === currentPage }]"
          @click="currentPage = p"
          @contextmenu.prevent="onPageRightClick(p, $event)"
        >
          {{ p }}
          <button
            v-if="pageToShowDelete === p"
            class="delete-btn"
            @click.stop="deletePage(p)"
          >
            Delete
          </button>
        </button>
        <button class="page-btn add-page" @click="addPage">+</button>
      </div>

      <!-- Order Dialog -->
      <OrderDialog
        v-if="selectedOrder"
        :order="selectedOrder"
        @close="closeOrderDialog"
        @edit="editOrder"
        @delete="deleteOrder"
      />
    </div>
  </div>
</template>

<script>
import GanttCalendar from './GanttCalendar.vue';
import OrderDialog from './OrderDialog.vue';
import './ganttChart.css';

export default {
  name: 'GanttChart',
  components: {
    GanttCalendar,
    OrderDialog,
  },
  data() {
    return {
      // ค่าจาก Calendar
      selectedDate: '1/1/2024',

      // กำหนดช่วงเวลาใน Gantt
      startTime: '08:00',
      endTime: '17:00',

      // รายการเครื่องจักร
      machines: [
        { id: 1, machineID: 'MC1' },
        { id: 2, machineID: 'MC2' },
        { id: 3, machineID: 'MC3' },
        { id: 4, machineID: 'MC4' },
        { id: 5, machineID: 'MC5' },
      ],

      // ข้อมูล Order ตามโครงสร้าง Queue
      orders: [
        {
          queueID: 1,
          machineID: 'MC1',
          orderID: 1,
          pageNumber: 1,
          startTime: '1/1/2024 09:00',
          finishTime: '1/1/2024 11:00',
          status: 'Process',
          bottleSize: '600ml',
          producedQuantity: 400,
        },
        {
          queueID: 2,
          machineID: 'MC2',
          orderID: 2,
          pageNumber: 1,
          startTime: '1/1/2024 13:00',
          finishTime: '1/1/2024 15:00',
          status: 'Waiting',
          bottleSize: '500ml',
          producedQuantity: 200,
        },
        {
          queueID: 3,
          machineID: 'MC1',
          orderID: 3,
          pageNumber: 2,
          startTime: '1/1/2024 10:00',
          finishTime: '1/1/2024 12:00',
          status: 'Process',
          bottleSize: '700ml',
          producedQuantity: 350,
        },
        {
          queueID: 4,
          machineID: 'MC5',
          orderID: 4,
          pageNumber: 2,
          startTime: '1/1/2024 14:00',
          finishTime: '1/1/2024 16:00',
          status: 'Process',
          bottleSize: '600ml',
          producedQuantity: 500,
        },
        {
          queueID: 5,
          machineID: 'MC5',
          orderID: 4,
          pageNumber: 1,
          startTime: '2/1/2024 14:00',
          finishTime: '2/1/2024 16:00',
          status: 'Process',
          bottleSize: '600ml',
          producedQuantity: 500,
        },
      ],

      // จัดการการลาก, Resize
      draggingOrder: null,
      dragOffset: 0,
      resizingOrder: null,
      resizeDirection: null,

      // Ghost Order (ขณะลาก)
      ghostOrder: null,
      ghostStyle: {
        position: 'fixed',
        top: '0px',
        left: '0px',
        display: 'none',
        width: 'auto',
        height: '40px',
        lineHeight: '40px',
        padding: '0 10px',
        borderRadius: '20px',
        pointerEvents: 'none',
        backgroundColor: '#4caf50',
        color: '#fff',
        zIndex: 9999,
      },

      // Pagination
      pages: [1, 2],
      currentPage: 1,
      pageToShowDelete: null,

      // Dialog
      selectedOrder: null,
    };
  },
  computed: {
    // สร้าง list ของชั่วโมงทั้งหมดจาก startTime ถึง endTime
    hours() {
      const startHour = parseInt(this.startTime.split(':')[0]);
      const endHour = parseInt(this.endTime.split(':')[0]);
      return Array.from({ length: endHour - startHour + 1 }, (_, i) => startHour + i);
    },
  },
  methods: {
    // แยก date ส่วนหน้า (1/1/2024) ออกจาก startTime/finishTime
    getDateString(dateTimeStr) {
      // สมมติ format = '1/1/2024 09:00'
      return dateTimeStr.split(' ')[0];
    },
    // แยกเฉพาะส่วนเวลา (09:00)
    getTimeString(dateTimeStr) {
      return dateTimeStr.split(' ')[1];
    },

    // ฟิลเตอร์ order ตาม machineID, pageNumber, และ selectedDate
    filteredOrders(machineID) {
      return this.orders.filter((o) => {
        const orderDate = this.getDateString(o.startTime);
        return (
          o.machineID === machineID &&
          o.pageNumber === this.currentPage &&
          orderDate === this.selectedDate
        );
      });
    },

    // แปลงเลขชั่วโมงเป็น "HH:00"
    formatHour(hour) {
      return (hour < 10 ? '0' + hour : hour) + ':00';
    },

    // สไตล์ตำแหน่งของ Order
    getOrderStyle(order) {
      // แยกเวลาเฉพาะส่วน HH:mm
      const start = this.getTimeString(order.startTime); // ex "09:00"
      const end = this.getTimeString(order.finishTime);  // ex "11:00"

      const startDecimal = this.timeToDecimal(start);
      const endDecimal = this.timeToDecimal(end);
      const timelineStart = this.timeToDecimal(this.startTime);
      const timelineEnd = this.timeToDecimal(this.endTime);

      const ratioStart = (startDecimal - timelineStart) / (timelineEnd - timelineStart);
      const ratioEnd = (endDecimal - timelineStart) / (timelineEnd - timelineStart);

      return {
        left: ratioStart * 100 + '%',
        width: (ratioEnd - ratioStart) * 100 + '%',
        backgroundColor: '#4caf50', // สามารถปรับตาม status หรืออื่นๆ ได้
      };
    },

    // สไตล์ของเส้นแนวตั้ง (grid lines)
    getLineStyle(hour) {
      const timelineStart = this.timeToDecimal(this.startTime);
      const timelineEnd = this.timeToDecimal(this.endTime);
      const ratio = (hour - timelineStart) / (timelineEnd - timelineStart);
      return {
        left: ratio * 100 + '%',
      };
    },

    // แปลงเวลา "HH:MM" -> เลขทศนิยม
    timeToDecimal(timeStr) {
      const [hours, minutes] = timeStr.split(':').map(Number);
      return hours + minutes / 60;
    },
    // แปลงเลขทศนิยม -> "HH:MM"
    decimalToTime(decimal) {
      const hours = Math.floor(decimal);
      const minutes = Math.round((decimal - hours) * 60);
      return (hours < 10 ? '0' + hours : hours) + ':' + (minutes < 10 ? '0' + minutes : minutes);
    },

    // Event ลาก (DragStart)
    onDragStart(event, order) {
      this.draggingOrder = order;
      const rect = event.target.getBoundingClientRect();
      this.dragOffset = rect.width / 2;
      // ปิด preview เริ่มต้นของ HTML5 Drag & Drop
      const emptyImg = document.createElement('img');
      emptyImg.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
      event.dataTransfer.setDragImage(emptyImg, 0, 0);

      this.ghostOrder = { ...order };
      this.ghostStyle.display = 'block';
      this.ghostStyle.backgroundColor = '#4caf50';

      document.addEventListener('dragover', this.onDragOverGlobal);
      document.addEventListener('dragend', this.onDragEndGlobal);
    },
    onDragOver(event) {
      event.preventDefault();
    },
    onDragOverGlobal(event) {
      event.preventDefault();
      const rowTimeline = document.querySelector('.row-timeline');
      if (!rowTimeline) return;
      const timelineRect = rowTimeline.getBoundingClientRect();
      const timelineWidth = timelineRect.width;
      const offsetX = event.clientX - timelineRect.left;

      let ratio = offsetX / timelineWidth;
      ratio = Math.min(Math.max(ratio, 0), 1);

      const timelineStart = this.timeToDecimal(this.startTime);
      const timelineEnd = this.timeToDecimal(this.endTime);

      // คำนวณเวลาเริ่มใหม่ (เฉพาะส่วนเวลา)
      const startDecimal = this.timeToDecimal(this.getTimeString(this.draggingOrder.startTime));
      const endDecimal = this.timeToDecimal(this.getTimeString(this.draggingOrder.finishTime));
      const duration = endDecimal - startDecimal;

      let newStartDecimal = timelineStart + ratio * (timelineEnd - timelineStart);
      newStartDecimal = Math.round(newStartDecimal * 2) / 2;

      let newEndDecimal = newStartDecimal + duration;
      if (newEndDecimal > timelineEnd) {
        newEndDecimal = timelineEnd;
        newStartDecimal = newEndDecimal - duration;
      }

      // สร้าง String ใหม่ "วัน/เดือน/ปี เวลา"
      const datePart = this.getDateString(this.draggingOrder.startTime); // ex "1/1/2024"
      const newStartStr = datePart + ' ' + this.decimalToTime(newStartDecimal);
      const newEndStr = datePart + ' ' + this.decimalToTime(newEndDecimal);

      this.ghostOrder.startTime = newStartStr;
      this.ghostOrder.finishTime = newEndStr;

      const snappedRatioStart = (newStartDecimal - timelineStart) / (timelineEnd - timelineStart);
      const snappedLeft = timelineRect.left + snappedRatioStart * timelineWidth;
      const snappedRatioEnd = (newEndDecimal - timelineStart) / (timelineEnd - timelineStart);
      const snappedWidth = (snappedRatioEnd - snappedRatioStart) * timelineWidth;

      // หาแถว (machine) ที่ใกล้ที่สุด
      const rows = document.querySelectorAll('.row');
      let closestRow = null;
      let minDistance = Infinity;

      rows.forEach((row) => {
        const rect = row.getBoundingClientRect();
        const distance = Math.abs(event.clientY - rect.top);
        if (distance < minDistance) {
          minDistance = distance;
          closestRow = row;
        }
      });

      if (closestRow) {
        this.ghostOrder.machineID = closestRow.querySelector('.machine-label').textContent.trim();
        this.ghostStyle.top = closestRow.getBoundingClientRect().top + 'px';
      }

      this.ghostStyle.left = snappedLeft + 'px';
      this.ghostStyle.width = snappedWidth + 'px';
    },
    onDragEndGlobal() {
      this.ghostOrder = null;
      this.ghostStyle.display = 'none';
      this.draggingOrder = null;
      document.removeEventListener('dragend', this.onDragEndGlobal);
    },
    onDragEnd(event, order) {
      if (!this.ghostOrder) return;
      order.startTime = this.ghostOrder.startTime;
      order.finishTime = this.ghostOrder.finishTime;
      order.machineID = this.ghostOrder.machineID;
      document.removeEventListener('dragover', this.onDragOverGlobal);
      this.ghostOrder = null;
      this.ghostStyle.display = 'none';
      this.draggingOrder = null;
    },
    onDrop(event, newMachine) {
      event.preventDefault();
      if (this.draggingOrder && this.ghostOrder) {
        this.draggingOrder.startTime = this.ghostOrder.startTime;
        this.draggingOrder.finishTime = this.ghostOrder.finishTime;
        this.draggingOrder.machineID = newMachine;
      }
      this.ghostOrder = null;
      this.ghostStyle.display = 'none';
      this.draggingOrder = null;
    },

    // Resize
    onResizeStart(event, order, direction) {
      event.preventDefault();
      this.resizingOrder = order;
      this.resizeDirection = direction;
      document.addEventListener('mousemove', this.onResizing);
      document.addEventListener('mouseup', this.onResizeEnd);
    },
    onResizing(event) {
      if (!this.resizingOrder) return;
      const rowTimeline = document.querySelector('.row-timeline');
      if (!rowTimeline) return;
      const timelineRect = rowTimeline.getBoundingClientRect();
      const timelineWidth = timelineRect.width;
      const offsetX = event.clientX - timelineRect.left;

      let ratio = offsetX / timelineWidth;
      ratio = Math.min(Math.max(ratio, 0), 1);

      const timelineStart = this.timeToDecimal(this.startTime);
      const timelineEnd = this.timeToDecimal(this.endTime);

      const startDec = this.timeToDecimal(this.getTimeString(this.resizingOrder.startTime));
      const endDec = this.timeToDecimal(this.getTimeString(this.resizingOrder.finishTime));

      let newTimeDecimal = timelineStart + ratio * (timelineEnd - timelineStart);
      newTimeDecimal = Math.round(newTimeDecimal * 2) / 2;

      const datePart = this.getDateString(this.resizingOrder.startTime); // ex: "1/1/2024"

      if (this.resizeDirection === 'left') {
        if (newTimeDecimal >= endDec) return;
        const newStartStr = datePart + ' ' + this.decimalToTime(newTimeDecimal);
        this.resizingOrder.startTime = newStartStr;
      } else if (this.resizeDirection === 'right') {
        if (newTimeDecimal <= startDec) return;
        const newEndStr = datePart + ' ' + this.decimalToTime(newTimeDecimal);
        this.resizingOrder.finishTime = newEndStr;
      }
    },
    onResizeEnd() {
      this.resizingOrder = null;
      this.resizeDirection = null;
      document.removeEventListener('mousemove', this.onResizing);
      document.removeEventListener('mouseup', this.onResizeEnd);
    },

    // Pagination
    addPage() {
      const newPage = this.pages.length + 1;
      this.pages.push(newPage);
    },
    onPageRightClick(page, event) {
      event.preventDefault();
      this.pageToShowDelete = page;
    },
    deletePage(page) {
      const index = this.pages.indexOf(page);
      if (index !== -1) {
        this.pages.splice(index, 1);
        if (this.currentPage === page) {
          this.currentPage = this.pages.length > 0 ? this.pages[0] : 1;
        }
      }
      this.pageToShowDelete = null;
    },
    onDocumentClick(event) {
      if (!event.target.closest('.page-btn')) {
        this.pageToShowDelete = null;
      }
    },

    // Dialog
    openOrderDialog(order) {
      this.selectedOrder = { ...order };
    },
    closeOrderDialog() {
      this.selectedOrder = null;
    },
    editOrder(order) {
      alert('Edit functionality not implemented yet.\nOrder ID: ' + order.orderID);
    },
    deleteOrder(order) {
      this.orders = this.orders.filter((o) => o.queueID !== order.queueID);
      this.closeOrderDialog();
    },
  },
  mounted() {
    document.addEventListener('click', this.onDocumentClick);
  },
  beforeUnmount() {
    document.removeEventListener('click', this.onDocumentClick);
  },
};
</script>