<template>
  <Teleport to="body">
    <div
      v-if="isOpen"
      ref="modalRef"
      :style="{
        position: 'absolute',
        left: `${position.x}px`,
        top: `${position.y}px`,
        width: `${size.width}px`,
        height: `${size.height}px`,
      }"
      class="bg-white rounded-2xl border-2 border-gray-300 shadow-xl flex flex-col z-50"
    >
      <!-- Header with drag handle -->
      <div class="flex justify-between items-center p-4 border-b border-gray-200 cursor-move" @mousedown="startDrag" @touchstart="startDrag">
        <h3 class="text-2xl font-semibold text-gray-900">{{ title }}</h3>
        <button @click="close" class="p-2 hover:bg-gray-100 rounded-lg transition-colors">
          <img src="@/assets/images/close-icon.svg" class="w-5 h-5" alt="Close" />
        </button>
      </div>

      <!-- Body -->
      <div class="p-6 flex-1 overflow-auto">
        <slot></slot>
      </div>

      <!-- Resize handle -->
      <div class="absolute bottom-0 right-0 w-5 h-5 cursor-se-resize" @mousedown="startResize" @touchstart="startResize"></div>
    </div>
  </Teleport>
</template>

<script setup lang="ts">
  import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';

  const props = defineProps<{
    isOpen: boolean;
    title: string;
    initialWidth?: number;
    initialHeight?: number;
  }>();

  const emit = defineEmits<{
    (e: 'close'): void;
  }>();

  const modalRef = ref<HTMLElement | null>(null);
  const position = ref({ x: 0, y: 0 });
  const size = ref({
    width: props.initialWidth || 800,
    height: props.initialHeight || 600,
  });

  const isDragging = ref(false);
  const isResizing = ref(false);
  const startPos = ref({ x: 0, y: 0 });
  const startSize = ref({ width: 0, height: 0 });

  // Unified start function for both drag and resize
  const startAction = (event: MouseEvent | TouchEvent, action: 'drag' | 'resize') => {
    event.preventDefault();
    const clientX = 'touches' in event ? event.touches[0].clientX : event.clientX;
    const clientY = 'touches' in event ? event.touches[0].clientY : event.clientY;

    if (action === 'drag') {
      isDragging.value = true;
      startPos.value = {
        x: clientX - position.value.x,
        y: clientY - position.value.y,
      };
    } else {
      isResizing.value = true;
      startPos.value = { x: clientX, y: clientY };
      startSize.value = { ...size.value };
    }

    document.addEventListener('mousemove', handleMove);
    document.addEventListener('touchmove', handleMove, { passive: false });
    document.addEventListener('mouseup', stopAction);
    document.addEventListener('touchend', stopAction);
  };

  const startDrag = (event: MouseEvent | TouchEvent) => startAction(event, 'drag');
  const startResize = (event: MouseEvent | TouchEvent) => startAction(event, 'resize');

  const handleMove = (event: MouseEvent | TouchEvent) => {
    if (!isDragging.value && !isResizing.value) return;
    event.preventDefault();

    const clientX = 'touches' in event ? event.touches[0].clientX : event.clientX;
    const clientY = 'touches' in event ? event.touches[0].clientY : event.clientY;

    if (isDragging.value) {
      const newX = clientX - startPos.value.x;
      const newY = clientY - startPos.value.y;
      position.value = constrainPosition(newX, newY);
    } else if (isResizing.value) {
      const deltaX = clientX - startPos.value.x;
      const deltaY = clientY - startPos.value.y;
      size.value = constrainSize(startSize.value.width + deltaX, startSize.value.height + deltaY);
    }
  };

  const stopAction = () => {
    isDragging.value = false;
    isResizing.value = false;
    document.removeEventListener('mousemove', handleMove);
    document.removeEventListener('touchmove', handleMove);
    document.removeEventListener('mouseup', stopAction);
    document.removeEventListener('touchend', stopAction);
  };

  const constrainPosition = (x: number, y: number) => {
    if (!modalRef.value) return { x, y };
    const modalRect = modalRef.value.getBoundingClientRect();
    return {
      x: Math.max(0, Math.min(x, window.innerWidth - modalRect.width)),
      y: Math.max(0, Math.min(y, window.innerHeight - modalRect.height)),
    };
  };

  const constrainSize = (width: number, height: number) => {
    return {
      width: Math.max(400, Math.min(width, window.innerWidth - position.value.x)),
      height: Math.max(300, Math.min(height, window.innerHeight - position.value.y)),
    };
  };

  const centerModal = () => {
    if (!modalRef.value) return;
    position.value = {
      x: (window.innerWidth - size.value.width) / 2,
      y: (window.innerHeight - size.value.height) / 2,
    };
  };

  const close = () => {
    emit('close');
    position.value = { x: 0, y: 0 };
  };

  // Event handlers
  const handleKeyDown = (event: KeyboardEvent) => {
    if (event.key === 'Escape' && props.isOpen) close();
  };

  const handleResize = () => {
    if (!isDragging.value && !isResizing.value) {
      position.value = constrainPosition(position.value.x, position.value.y);
      size.value = constrainSize(size.value.width, size.value.height);
    }
  };

  // Lifecycle
  watch(
    () => props.isOpen,
    newValue => {
      if (newValue) nextTick(centerModal);
    }
  );

  onMounted(() => {
    document.addEventListener('keydown', handleKeyDown);
    window.addEventListener('resize', handleResize);
    if (props.isOpen) centerModal();
  });

  onUnmounted(() => {
    document.removeEventListener('keydown', handleKeyDown);
    window.removeEventListener('resize', handleResize);
    stopAction();
  });
</script>
