<template>
  <div class="gantt-container">
    <div class="gantt-header">
      <!-- Calendar: เชื่อมกับ selectedDate -->
      <GanttCalendar v-model:modelValue="selectedDate" />
      
      <!-- ปุ่ม Make a queue พร้อม event listener -->
      <MakequeueBtn @updateQueue="handleUpdateQueue" />
    </div>
    <!-- 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.name }}
          </div>
          <div class="row-timeline">
            <!-- เส้นแนวตั้ง (Grid Lines) -->
            <div
              v-for="hour in hours"
              :key="'line-' + hour"
              class="vertical-line"
              :style="getLineStyle(hour)"
            ></div>

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

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

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

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

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

      <!-- Pagination -->
      <div class="pagination-container">
        <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" :disabled="pages.length >= 10">
            +
          </button>
        </div>

        <!-- ปุ่ม Add Queue อยู่ขวาสุด -->
        <div class="pagination-right">
          <v-btn class="add-page-btn" @click="openAddQueueDialog" icon>
            <v-icon>mdi-plus</v-icon>
          </v-btn>
        </div>

        <!-- AddQueueDialog (สำหรับเพิ่ม/แก้ไข) -->
        <AddQueueDialog
          :visible="showAddDialog"
          :queueItem="selectedQueueItem"
          @close="closeAddQueueDialog"
          @add="handleAddQueue"
          @edit="handleEditQueue"
        />
      </div>

      <!-- Order Dialog (สำหรับดูรายละเอียดเพิ่มเติม) -->
      <OrderDialog
        v-if="selectedQueueItem && !showAddDialog"
        :queueItem="selectedQueueItem"
        :color="getQueueColor(selectedQueueItem.orderID)"
        @close="closeQueueDialog"
        @edit="openAddQueueDialogForEdit"
        @delete="deleteQueueItem"
      />
    </div>
  </div>
</template>

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

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

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

      // รายการเครื่องจักร
      machines: [
        { machineID: 'MC1' , name: 'เครื่องเป่าขวด' },
        { machineID: 'MC2' , name: 'เครื่องเป่าขวด2' },
        { machineID: 'MC3' , name: 'เครื่องสวมฉลาก' },
        { machineID: 'MC4' , name: 'เครื่องบรรจุ+แพ็ค' },
      ],

      // รายการ Queue เริ่มต้น (สามารถเปลี่ยนแปลงได้)
      Queue: [
        {
          queueID: 1,
          machineID: 'MC1',
          orderID: 5,
          pageNumber: 1,
          startTime: '1/1/2025 09:00',
          finishTime: '1/1/2025 11:00',
          status: 'Process',
          bottleSize: '600ml',
          producedQuantity: 400,
        },
        {
          queueID: 2,
          machineID: 'MC2',
          orderID: 1,
          pageNumber: 1,
          startTime: '1/1/2025 13:00',
          finishTime: '1/1/2025 15:00',
          status: 'Waiting',
          bottleSize: '500ml',
          producedQuantity: 200,
        },
      ],

      // Drag/Drop และ Resize
      draggingQueue: null,
      dragOffset: 0,
      resizingQueue: null,
      resizeDirection: null,

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

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

      // Dialog
      selectedQueueItem: 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: {
    // รับข้อมูล Queue ที่ส่งมาจาก MakequeueBtn
    handleUpdateQueue(newQueue) {
      console.log("Received new queue:", newQueue);
      // ในที่นี้เราสามารถแทนที่ Queue เดิมหรือ merge กับข้อมูลที่มีอยู่
      // ตัวอย่างนี้ใช้แทนที่ Queue ทั้งหมด
      this.Queue = newQueue;
    },

    // -------------------- Dialog & Edit --------------------
    openQueueDialog(item) {
      this.selectedQueueItem = { ...item };
    },
    closeQueueDialog() {
      this.selectedQueueItem = null;
    },
    openAddQueueDialog() {
      this.selectedQueueItem = null;
      this.showAddDialog = true;
    },
    deleteQueueItem(item) {
      this.Queue = this.Queue.filter(q => q.queueID !== item.queueID);
      this.closeQueueDialog();
    },
    openAddQueueDialogForEdit(queueItem) {
      this.selectedQueueItem = { ...queueItem };
      this.showAddDialog = true;
    },
    closeAddQueueDialog() {
      this.showAddDialog = false;
      this.selectedQueueItem = null;
    },
    handleAddQueue(newQueueItem) {
      this.Queue.push({
        queueID: this.Queue.length + 1,
        ...newQueueItem,
      });
      this.showAddDialog = false;
    },
    handleEditQueue(updatedQueueItem) {
      const index = this.Queue.findIndex(q => q.queueID === updatedQueueItem.queueID);
      if (index !== -1) {
        this.Queue.splice(index, 1, { ...updatedQueueItem });
      }
      this.selectedQueueItem = null;
      this.showAddDialog = false;
    },

    // -------------------- Utility Functions --------------------
    formatHour(hour) {
      return (hour < 10 ? '0' + hour : hour) + ':00';
    },
    getDateString(dateTimeStr) {
      return dateTimeStr.split(' ')[0];
    },
    getTimeString(dateTimeStr) {
      return dateTimeStr.split(' ')[1];
    },
    filteredQueue(machineID) {
      return this.Queue.filter((q) => {
        const queueDate = this.getDateString(q.startTime);
        return (
          q.machineID === machineID &&
          q.pageNumber === this.currentPage &&
          queueDate === this.selectedDate
        );
      });
    },
    getQueueColor(orderID) {
      const colors = ['#F58181', '#FDDC5C', '#C5A1BC', '#49E060'];
      return colors[(orderID - 1) % colors.length];
    },
    getQueueStyle(item) {
      const start = this.getTimeString(item.startTime);
      const end = this.getTimeString(item.finishTime);
      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: this.getQueueColor(item.orderID),
        color: '#fff',
        borderRadius: '10px',
        textAlign: 'center',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        padding: '5px',
        fontSize: '14px',
      };
    },
    getLineStyle(hour) {
      const timelineStart = this.timeToDecimal(this.startTime);
      const timelineEnd = this.timeToDecimal(this.endTime);
      const ratio = (hour - timelineStart) / (timelineEnd - timelineStart);
      return { left: ratio * 100 + '%' };
    },
    timeToDecimal(timeStr) {
      const [hours, minutes] = timeStr.split(':').map(Number);
      return hours + minutes / 60;
    },
    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);
    },

    // -------------------- Drag/Drop & Resize --------------------
    onDragStart(event, item) {
      this.draggingQueue = item;
      const rect = event.target.getBoundingClientRect();
      this.dragOffset = rect.width / 2;
      const emptyImg = document.createElement('img');
      emptyImg.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
      event.dataTransfer.setDragImage(emptyImg, 0, 0);

      this.ghostQueue = { ...item };
      this.ghostStyle.display = 'block';
      this.ghostStyle.backgroundColor = this.getQueueColor(item.orderID);

      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.draggingQueue.startTime));
      const endDecimal = this.timeToDecimal(this.getTimeString(this.draggingQueue.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;
      }

      const datePart = this.getDateString(this.draggingQueue.startTime);
      const newStartStr = datePart + ' ' + this.decimalToTime(newStartDecimal);
      const newEndStr = datePart + ' ' + this.decimalToTime(newEndDecimal);

      this.ghostQueue.startTime = newStartStr;
      this.ghostQueue.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;

      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.ghostQueue.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.ghostQueue = null;
      this.ghostStyle.display = 'none';
      this.draggingQueue = null;
      document.removeEventListener('dragend', this.onDragEndGlobal);
    },
    onDragEnd(event, item) {
      if (!this.ghostQueue) return;
      item.startTime = this.ghostQueue.startTime;
      item.finishTime = this.ghostQueue.finishTime;
      item.machineID = this.ghostQueue.machineID;
      document.removeEventListener('dragover', this.onDragOverGlobal);
      this.ghostQueue = null;
      this.ghostStyle.display = 'none';
      this.draggingQueue = null;
    },
    onDrop(event, newMachine) {
      event.preventDefault();
      if (this.draggingQueue && this.ghostQueue) {
        this.draggingQueue.startTime = this.ghostQueue.startTime;
        this.draggingQueue.finishTime = this.ghostQueue.finishTime;
        this.draggingQueue.machineID = newMachine;
      }
      this.ghostQueue = null;
      this.ghostStyle.display = 'none';
      this.draggingQueue = null;
    },
    onResizeStart(event, item, direction) {
      event.preventDefault();
      this.resizingQueue = item;
      this.resizeDirection = direction;
      document.addEventListener('mousemove', this.onResizing);
      document.addEventListener('mouseup', this.onResizeEnd);
    },
    onResizing(event) {
      if (!this.resizingQueue) 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.resizingQueue.startTime));
      const endDec = this.timeToDecimal(this.getTimeString(this.resizingQueue.finishTime));
      let newTimeDecimal = timelineStart + ratio * (timelineEnd - timelineStart);
      newTimeDecimal = Math.round(newTimeDecimal * 2) / 2;
      const datePart = this.getDateString(this.resizingQueue.startTime);

      if (this.resizeDirection === 'left') {
        if (newTimeDecimal >= endDec) return;
        const newStartStr = datePart + ' ' + this.decimalToTime(newTimeDecimal);
        this.resizingQueue.startTime = newStartStr;
      } else if (this.resizeDirection === 'right') {
        if (newTimeDecimal <= startDec) return;
        const newEndStr = datePart + ' ' + this.decimalToTime(newTimeDecimal);
        this.resizingQueue.finishTime = newEndStr;
      }
    },
    onResizeEnd() {
      this.resizingQueue = null;
      this.resizeDirection = null;
      document.removeEventListener('mousemove', this.onResizing);
      document.removeEventListener('mouseup', this.onResizeEnd);
    },
    addPage() {
      if (this.pages.length < 10) {
        const newPage = this.pages.length + 1;
        this.pages.push(newPage);
      } else {
        alert("Maximum of 10 pages allowed.");
      }
    },
    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;
      }
    },
  },
  mounted() {
    document.addEventListener('click', this.onDocumentClick);
  },
  beforeUnmount() {
    document.removeEventListener('click', this.onDocumentClick);
  },
};
</script>