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

      <!-- ปุ่มจัดเรียงและเพิ่มระยะห่าง -->
      <div class="gantt-buttons">
        <MakequeueBtn @click="openAddQueueDialog" />
        <SettingBtn class="mr-4" />
      </div>
    </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: แสดงเครื่องจักรจาก Machine Store -->
      <div class="rows">
        <div
          v-for="machine in machineStore.machines"
          :key="machine.MachineID"
          class="row"
          :data-machine-id="machine.MachineID"
          @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 (pagenum), และ 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 (ขณะลาก/resize) -->
      <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>
        <div class="pagination-right">
          <v-btn class="add-page-btn" @click="openAddQueueDialog" icon>
            <v-icon>mdi-plus</v-icon>
          </v-btn>
        </div>
        <AddQueueDialog
          :visible="showAddDialog"
          :queueItem="selectedQueueItem"
          :currentPage="currentPage"
          @close="closeAddQueueDialog"
        />
      </div>
      <OrderDialog
        v-if="selectedQueueItem && !showAddDialog"
        :queueItem="selectedQueueItem"
        :color="getQueueColor(selectedQueueItem.orderID)"
        @close="closeQueueDialog"
        @edit="openAddQueueDialogForEdit"
        @delete="handleDelete"
      />
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive, computed, onMounted, onBeforeUnmount, watch } from 'vue';
import { useQueueStore } from '@/stores/queue';
import { useMachineStore } from '@/stores/machine';
import { usePageStore } from '@/stores/page';
import { usePageContextStore } from '@/stores/pageContext';
import { useDateStore } from '@/stores/dateStore';
import { storeToRefs } from 'pinia';

import GanttCalendar from './GanttCalendar.vue';
import OrderDialog from './OrderDialog.vue';
import AddQueueDialog from './AddQueueDialog.vue';
import MakequeueBtn from './MakequeueBtn.vue';
import SettingBtn from './SettingBtn.vue';
import './ganttChart.css';

// Stores
const queueStore = useQueueStore();
const machineStore = useMachineStore();
const pageStore = usePageStore();
const dateStore = useDateStore();
const { currentDate: selectedDate } = storeToRefs(dateStore);
const pageContext = usePageContextStore();

// ใช้ currentPage เป็น pagenum จาก pageContext
const currentPage = computed({
  get: () => pageContext.currentPage,
  set: (val) => (pageContext.currentPage = val),
});

// เมื่อเข้าหน้า ให้ดึงข้อมูลจาก backend
onMounted(() => {
  machineStore.fetchMachines();
  queueStore.fetchQueues();
  pageStore.fetchPages();
});

// State สำหรับ Gantt Chart
const showAddDialog = ref(false);
const startTime = ref('06:00');
const endTime = ref('20:00');

const draggingQueue = ref<any | null>(null);
const dragOffset = ref(0);
const resizingQueue = ref<any | null>(null);
const resizeDirection = ref<string | null>(null);

const ghostQueue = ref<any | null>(null);
const ghostStyle = reactive({
  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,
});

// แปลงข้อมูล Queue จาก backend ให้เข้ากับรูปแบบที่ Gantt Chart ใช้
const formattedQueues = computed(() => {
  return queueStore.queues.map(q => ({
    QueueID: q.QueueID,
    orderID: q.order?.OrderID || "Unknown",
    machineID: q.machine?.MachineID || 0,
    machineName: q.machine?.name || "Unknown Machine",
    startTime: q.startTime ? convertToLocalTime(q.startTime) : "Unknown",
    finishTime: q.finishTime ? convertToLocalTime(q.finishTime) : "Unknown",
    status: q.status || "Unknown",
    bottleSize: q.bottleSize || "Unknown",
    producedQuantity: q.producedQuantity || 0,
    // เปลี่ยนจาก PageID เป็น pagenum
    pageNumber: q.page?.pagenum || 0,
  }));
});

function convertToLocalTime(utcString: string): string {
  const date = new Date(utcString);
  date.setHours(date.getHours() + 7);
  return date.toISOString().slice(0, 16).replace("T", " ");
}

// Pagination & Dialog
const pages = computed(() => pageStore.pages.map(p => p.pagenum));
const pageToShowDelete = ref<number | null>(null);
const selectedQueueItem = ref<any | null>(null);

watch(
  () => queueStore.queues,
  (newVal) => {
    console.log("🔄 Queues updated in GanttChart.vue:", newVal);
  },
  { deep: true }
);

const hours = computed(() => {
  const startHour = parseInt(startTime.value.split(':')[0]);
  const endHour = parseInt(endTime.value.split(':')[0]);
  return Array.from({ length: endHour - startHour + 1 }, (_, i) => startHour + i);
});

// Methods
function openQueueDialog(item: any) {
  selectedQueueItem.value = { ...item };
}
function closeQueueDialog() {
  selectedQueueItem.value = null;
}
function openAddQueueDialog() {
  selectedQueueItem.value = null;
  showAddDialog.value = true;
}
function openAddQueueDialogForEdit(queueItem: any) {
  selectedQueueItem.value = { ...queueItem };
  showAddDialog.value = true;
}
function handleDelete(queueItem: { QueueID: number; }) {
  if (!queueItem) return;
  queueStore
    .deleteQueue(queueItem.QueueID)
    .then(() => {
      console.log(`✅ Queue ID ${queueItem.QueueID} ถูกลบสำเร็จ`);
      closeAddQueueDialog();
    })
    .catch((error) => console.error(`❌ Error deleting queue:`, error));
}
function closeAddQueueDialog() {
  showAddDialog.value = false;
  selectedQueueItem.value = null;
}

function formatHour(hour: number): string {
  return (hour < 10 ? '0' + hour : hour) + ':00';
}
function getDateString(dateTimeStr: string): string {
  return dateTimeStr.split(' ')[0];
}
function getTimeString(dateTimeStr: string): string {
  return dateTimeStr.split(' ')[1];
}

function filteredQueue(machineID: number) {
  return formattedQueues.value.filter(q => {
    if (!q || !q.startTime || !q.finishTime) return false;
    const queueDate = getDateString(q.startTime);
    return (
      q.machineID === machineID &&
      q.pageNumber === currentPage.value &&
      queueDate === selectedDate.value
    );
  });
}

const colorMap: Record<string, string> = {};
function getQueueColor(orderID: string | number): string {
  const key = String(orderID);
  if (key === "ผลิตเผื่อ") return "#FFC1C1";
  if (key === "เปลี่ยนขนาด") return "#E1BEE7";
  if (colorMap[key]) return colorMap[key];
  const newColor = generateWaterPastel();
  colorMap[key] = newColor;
  return newColor;
}
function generateWaterPastel(): string {
  const waterHues = [180, 190, 200, 210, 220, 230, 240];
  const hue = waterHues[Math.floor(Math.random() * waterHues.length)];
  return `hsl(${hue}, 60%, 80%)`;
}
function getQueueStyle(item: any) {
  const start = getTimeString(item.startTime);
  const end = getTimeString(item.finishTime);
  const startDecimal = timeToDecimal(start);
  const endDecimal = timeToDecimal(end);
  const totalHours = hours.value.length;
  const leftPercent = ((startDecimal - timeToDecimal(startTime.value)) / totalHours) * 100;
  const widthPercent = ((endDecimal - startDecimal) / totalHours) * 100;
  const orderID = item.orderID || "Unknown";
  const backgroundColor = getQueueColor(orderID);
  console.log(`Queue ${item.QueueID}: orderID=${orderID}, color=${backgroundColor}`);
  return {
    left: `${leftPercent}%`,
    width: `${widthPercent}%`,
    backgroundColor,
    color: '#333',
    borderRadius: '10px',
    textAlign: 'center',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    padding: '5px',
    fontSize: '14px',
    fontWeight: 'bold',
    boxShadow: '0px 4px 6px rgba(0, 0, 0, 0.1)',
  };
}
function getLineStyle(hour: number) {
  const totalHours = hours.value.length;
  const leftPercent = ((hour - timeToDecimal(startTime.value)) / totalHours) * 100;
  return { left: `${leftPercent}%` };
}
function timeToDecimal(timeStr: string): number {
  const [h, m] = timeStr.split(':').map(Number);
  return h + m / 60;
}
function decimalToTime(decimal: number): string {
  const hrs = Math.floor(decimal);
  const minutes = Math.round((decimal - hrs) * 60);
  return (hrs < 10 ? '0' + hrs : hrs) + ':' + (minutes < 10 ? '0' + minutes : minutes);
}

// Drag/Drop & Resize Functions
function onDragStart(event: DragEvent, item: any) {
  draggingQueue.value = item;
  const target = event.target as HTMLElement;
  const rect = target.getBoundingClientRect();
  dragOffset.value = rect.width / 2;
  const emptyImg = new Image();
  emptyImg.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
  event.dataTransfer?.setDragImage(emptyImg, 0, 0);
  ghostQueue.value = { ...item };
  ghostStyle.display = 'block';
  ghostStyle.backgroundColor = getQueueColor(item.order?.OrderID || "Unknown");
  document.addEventListener('dragover', onDragOverGlobal);
  document.addEventListener('dragend', onDragEndGlobal);
}
function onDragOver(event: DragEvent) {
  event.preventDefault();
}
function onDragOverGlobal(event: DragEvent) {
  event.preventDefault();
  const rowTimeline = document.querySelector('.row-timeline') as HTMLElement;
  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 timelineStartDec = timeToDecimal(startTime.value);
  const timelineEndDec = timeToDecimal(endTime.value);
  if (!draggingQueue.value) return;
  const startDecimal = timeToDecimal(getTimeString(draggingQueue.value.startTime));
  const endDecimal = timeToDecimal(getTimeString(draggingQueue.value.finishTime));
  const duration = endDecimal - startDecimal;
  let newStartDecimal = timelineStartDec + ratio * (timelineEndDec - timelineStartDec);
  newStartDecimal = Math.round(newStartDecimal * 2) / 2;
  let newEndDecimal = newStartDecimal + duration;
  if (newEndDecimal > timelineEndDec) {
    newEndDecimal = timelineEndDec;
    newStartDecimal = newEndDecimal - duration;
  }

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

  if (ghostQueue.value) {
    ghostQueue.value.startTime = newStartStr;
    ghostQueue.value.finishTime = newEndStr;
  }

  // คำนวณตำแหน่ง ghost element
  const snappedRatioStart = (newStartDecimal - timelineStartDec) / (timelineEndDec - timelineStartDec);
  const snappedLeft = timelineRect.left + snappedRatioStart * timelineWidth;
  const snappedRatioEnd = (newEndDecimal - timelineStartDec) / (timelineEndDec - timelineStartDec);
  const snappedWidth = (snappedRatioEnd - snappedRatioStart) * timelineWidth;

  // หาจุด row ที่ใกล้เคียงที่สุดและดึง machine id จาก attribute
  const rows = document.querySelectorAll('.row');
  let closestRow: HTMLElement | null = null;
  let minDistance = Infinity;
  rows.forEach((row) => {
    const rect = (row as HTMLElement).getBoundingClientRect();
    const distance = Math.abs(event.clientY - rect.top);
    if (distance < minDistance) {
      minDistance = distance;
      closestRow = row as HTMLElement;
    }
  });

  if (closestRow) {
    const machineIDString = (closestRow as HTMLElement).dataset.machineId;
    if (machineIDString) {
      ghostQueue.value.machineID = parseInt(machineIDString, 10);
    }
    ghostStyle.top = (closestRow as HTMLElement).getBoundingClientRect().top + 'px';
  }

  ghostStyle.left = snappedLeft + 'px';
  ghostStyle.width = snappedWidth + 'px';
}

function onDragEndGlobal() {
  ghostQueue.value = null;
  ghostStyle.display = 'none';
  draggingQueue.value = null;
  document.removeEventListener('dragend', onDragEndGlobal);
}
async function onDragEnd(event: DragEvent, item: any) {
  if (!ghostQueue.value) return;
  console.log(`🔄 Updating Queue ${item.QueueID} after drag...`);
  item.startTime = ghostQueue.value.startTime;
  item.finishTime = ghostQueue.value.finishTime;
  const newMachineID = ghostQueue.value.machine?.MachineID || item.machineID;
  await queueStore.updateQueue(item.QueueID, {
    startTime: item.startTime,
    finishTime: item.finishTime,
    MachineID: newMachineID,
  });
  ghostQueue.value = null;
  ghostStyle.display = 'none';
  draggingQueue.value = null;
}
async function onDrop(event: DragEvent, newMachineID: number) {
  event.preventDefault();
  if (!draggingQueue.value || !ghostQueue.value) return;
  console.log(`🔄 Dropped Queue ${draggingQueue.value.QueueID} to Machine ${newMachineID}`);
  draggingQueue.value.startTime = ghostQueue.value.startTime;
  draggingQueue.value.finishTime = ghostQueue.value.finishTime;
  draggingQueue.value.machineID = newMachineID;
  try {
    await queueStore.updateQueue(draggingQueue.value.QueueID, {
      startTime: draggingQueue.value.startTime,
      finishTime: draggingQueue.value.finishTime,
      MachineID: newMachineID,
    });
    console.log(`✅ Queue ${draggingQueue.value.QueueID} updated to Machine ${newMachineID}`);
  } catch (error) {
    console.error(`❌ Error updating queue:`, error);
  }
  ghostQueue.value = null;
  ghostStyle.display = 'none';
  draggingQueue.value = null;
}

function onResizeStart(event: MouseEvent, item: any, direction: string) {
  event.preventDefault();
  ghostQueue.value = { ...item };
  resizingQueue.value = item;
  resizeDirection.value = direction;
  document.addEventListener('mousemove', onResizing);
  document.addEventListener('mouseup', onResizeEnd);
}
function onResizing(event: MouseEvent) {
  if (!resizingQueue.value) return;
  const rowTimeline = document.querySelector('.row-timeline') as HTMLElement;
  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 timelineStartDec = timeToDecimal(startTime.value);
  const timelineEndDec = timeToDecimal(endTime.value);
  const startDec = timeToDecimal(getTimeString(resizingQueue.value.startTime));
  const endDec = timeToDecimal(getTimeString(resizingQueue.value.finishTime));
  let newTimeDecimal = timelineStartDec + ratio * (timelineEndDec - timelineStartDec);
  newTimeDecimal = Math.round(newTimeDecimal * 2) / 2;
  const datePart = getDateString(resizingQueue.value.startTime);
  if (resizeDirection.value === 'left') {
    if (newTimeDecimal >= endDec) return;
    const newStartStr = datePart + ' ' + decimalToTime(newTimeDecimal);
    ghostQueue.value.startTime = newStartStr;
  } else if (resizeDirection.value === 'right') {
    if (newTimeDecimal <= startDec) return;
    const newEndStr = datePart + ' ' + decimalToTime(newTimeDecimal);
    ghostQueue.value.finishTime = newEndStr;
  }
}
async function onResizeEnd() {
  if (!resizingQueue.value) return;
  console.log(`🔄 Updating Queue ${resizingQueue.value.QueueID} after resize...`);
  await queueStore.updateQueue(resizingQueue.value.QueueID, {
    startTime: ghostQueue.value.startTime,
    finishTime: ghostQueue.value.finishTime,
  });
  resizingQueue.value = null;
  resizeDirection.value = null;
  ghostQueue.value = null;
  ghostStyle.display = 'none';
  document.removeEventListener('mousemove', onResizing);
  document.removeEventListener('mouseup', onResizeEnd);
}

// Pagination Functions
async function addPage() {
  if (pageStore.pages.length < 10) {
    await pageStore.addPage();
    await pageStore.fetchPages(); // 👈 โหลดหน้าทั้งหมดใหม่
  } else {
    alert('Maximum of 10 pages allowed.');
  }
}
function onPageRightClick(page: number, event: MouseEvent) {
  event.preventDefault();
  pageToShowDelete.value = page;
}

async function deletePage(pageNum: number) {
  await pageStore.removePage(pageNum);
  await pageStore.fetchPages(); // 👈 โหลดหน้าทั้งหมดใหม่

  if (currentPage.value === pageNum) {
    const remaining = pageStore.pages.map(p => p.pagenum);
    currentPage.value = remaining.length > 0 ? remaining[0] : 1;
  }
  pageToShowDelete.value = null;
}

function onDocumentClick(event: MouseEvent) {
  const target = event.target as HTMLElement;
  if (!target.closest('.page-btn')) {
    pageToShowDelete.value = null;
  }
}
onMounted(() => {
  document.addEventListener('click', onDocumentClick);
});
onBeforeUnmount(() => {
  document.removeEventListener('click', onDocumentClick);
});
</script>