<template>
  <div
    ref="floatingDiv"
    :style="divStyle"
    @mousedown="startDrag"
  >
    <slot></slot>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';

const props = defineProps({
  id: {
    type: String,
    required: false,
  }
});

const floatingDiv = ref(null);
const position = reactive({ x: 0, y: 0 });
const isDragging = ref(false);
const isFloating = ref(false);
const dragStartOffset = reactive({ x: 0, y: 0 });

const divStyle = reactive({
  position: "",
  top: "",
  left: "",
  zIndex: "",
  cursor: "default",
});

let activeComponent = null;

function positionKey() {
  return props.id ? `floating-div-pos:${props.id}` : null;
}

function savePosition() {
  if (props.id) {
    localStorage.setItem(
      positionKey(),
      JSON.stringify({ x: position.x, y: position.y })
    );
  }
}

function loadPosition() {
  if (props.id) {
    const data = localStorage.getItem(positionKey());
    if (data) {
      try {
        const { x, y } = JSON.parse(data);
        position.x = x;
        position.y = y;
        divStyle.position = "fixed";
        divStyle.top = `${position.y}px`;
        divStyle.left = `${position.x}px`;
        divStyle.zIndex = 9999;
        isFloating.value = true;
      } catch {
        // Ignore corrupted data
      }
    }
  }
}

const startDrag = (event) => {
  if (event.shiftKey || event.ctrlKey) {
    if (!isFloating.value) {
      const rect = floatingDiv.value.getBoundingClientRect();
      position.x = rect.left;
      position.y = rect.top;
      divStyle.position = "fixed";
      divStyle.top = `${position.y}px`;
      divStyle.left = `${position.x}px`;
      divStyle.zIndex = 9999;
      isFloating.value = true;
    }

    isDragging.value = true;
    dragStartOffset.x = event.clientX - position.x;
    dragStartOffset.y = event.clientY - position.y;
    divStyle.cursor = "move";
    document.body.style.userSelect = "none";

    activeComponent = floatingDiv;

    window.addEventListener("mousemove", handleDrag);
    window.addEventListener("mouseup", stopDrag);
  }
};

const handleDrag = (event) => {
  if (isDragging.value && activeComponent === floatingDiv) {
    position.x = event.clientX - dragStartOffset.x;
    position.y = event.clientY - dragStartOffset.y;
    divStyle.top = `${position.y}px`;
    divStyle.left = `${position.x}px`;
  }
};

const stopDrag = () => {
  if (isDragging.value && activeComponent === floatingDiv) {
    isDragging.value = false;
    divStyle.cursor = "default";
    document.body.style.userSelect = "auto";
    activeComponent = null;

    savePosition();

    window.removeEventListener("mousemove", handleDrag);
    window.removeEventListener("mouseup", stopDrag);
  }
};

const handleOutsideDrag = (event) => {
  if (event.key === "Shift" || event.key === "Control") {
    stopDrag();
  }
};

onMounted(() => {
  document.addEventListener("keyup", handleOutsideDrag);
  loadPosition();
});

onBeforeUnmount(() => {
  document.removeEventListener("keyup", handleOutsideDrag);
  window.removeEventListener("mousemove", handleDrag);
  window.removeEventListener("mouseup", stopDrag);
});
</script>

<style>
div[ref="floatingDiv"] {
  background: rgba(255, 255, 255, 0.8);
  box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
</style>