<script setup lang="ts">
import { ref, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { useApp } from '@/composables/useApp'
import {
  FolderOpen,
  Download,
  FileArchive,
  Pencil,
  Trash2,
  Eye,
} from 'lucide-vue-next'

const props = defineProps<{
  itemPath: string
  itemName: string
  itemType: 'file' | 'directory'
  mimeType: string
}>()

const emit = defineEmits<{
  (e: 'rename'): void
  (e: 'preview'): void
  (e: 'download'): void
  (e: 'downloadZip'): void
  (e: 'delete'): void
  (e: 'open'): void
}>()

const app = useApp()
const router = useRouter()

const menuOpen = ref(false)
const menuX = ref(0)
const menuY = ref(0)

const longPressTimer = ref<ReturnType<typeof setTimeout> | null>(null)
const didLongPress = ref(false)
const touchMoved = ref(false)

function canPreview() {
  return props.mimeType.startsWith('image/') || props.mimeType.startsWith('video/') || props.mimeType.startsWith('audio/') || props.mimeType === 'application/pdf'
}

function showMenu(event: MouseEvent) {
  const wrapper = menuWrapper.value
  if (wrapper) {
    const rect = wrapper.getBoundingClientRect()
    menuX.value = event.clientX || rect.left
    menuY.value = event.clientY || rect.bottom
  } else {
    menuX.value = event.clientX || 0
    menuY.value = event.clientY || 0
  }
  menuOpen.value = true
  setTimeout(() => {
    document.addEventListener('click', closeMenu, { once: true })
  }, 0)
}

function closeMenu() {
  menuOpen.value = false
  document.removeEventListener('click', closeMenu)
}

function doAction(fn: () => void) {
  closeMenu()
  fn()
}

function handleClick() {
  if (didLongPress.value) {
    didLongPress.value = false
    return
  }
  emit('open')
}

function handleContextMenu(e: MouseEvent) {
  e.preventDefault()
  showMenu(e)
}

function handleTouchStart(e: TouchEvent) {
  touchMoved.value = false
  didLongPress.value = false
  longPressTimer.value = setTimeout(() => {
    didLongPress.value = true
    const touch = e.touches[0] || e.changedTouches[0]
    showMenu(new MouseEvent('contextmenu', { clientX: touch.clientX, clientY: touch.clientY }))
  }, 500)
}

function handleTouchMove() {
  touchMoved.value = true
  if (longPressTimer.value) {
    clearTimeout(longPressTimer.value)
    longPressTimer.value = null
  }
}

function handleTouchEnd(e: TouchEvent) {
  if (longPressTimer.value) {
    clearTimeout(longPressTimer.value)
    longPressTimer.value = null
  }
  if (!touchMoved.value && !didLongPress.value) {
    e.preventDefault()
    emit('open')
  }
}

function clampX(x: number) {
  return Math.min(x, typeof window !== 'undefined' ? window.innerWidth - 190 : 200)
}
function clampY(y: number) {
  return Math.min(y, typeof window !== 'undefined' ? window.innerHeight - 250 : 200)
}

onUnmounted(() => {
  if (longPressTimer.value) clearTimeout(longPressTimer.value)
})

const menuWrapper = ref<HTMLElement>()
</script>

<template>
  <div
    ref="menuWrapper"
    @click="handleClick"
    @contextmenu="handleContextMenu"
    @touchstart.passive="handleTouchStart"
    @touchmove.passive="handleTouchMove"
    @touchend="handleTouchEnd"
  >
    <slot />
  </div>

  <Teleport to="body">
    <div
      v-if="menuOpen"
      class="fixed z-[100] min-w-[180px] bg-card border border-border rounded-lg shadow-xl py-1"
      :style="{ left: clampX(menuX) + 'px', top: clampY(menuY) + 'px' }"
      @click.stop
    >
      <button
        v-if="itemType === 'directory'"
        class="w-full flex items-center gap-2.5 px-3 py-2 text-sm hover:bg-muted/70 transition-colors text-left"
        @click="doAction(() => router.push({ query: { path: itemPath } }))"
      >
        <FolderOpen class="size-3.5 shrink-0" />
        Open
      </button>

      <button
        v-if="itemType === 'directory'"
        class="w-full flex items-center gap-2.5 px-3 py-2 text-sm hover:bg-muted/70 transition-colors text-left"
        @click="doAction(() => emit('downloadZip'))"
      >
        <FileArchive class="size-3.5 shrink-0" />
        Download as ZIP
      </button>

      <button
        v-else
        class="w-full flex items-center gap-2.5 px-3 py-2 text-sm hover:bg-muted/70 transition-colors text-left"
        @click="doAction(() => emit('download'))"
      >
        <Download class="size-3.5 shrink-0" />
        Download
      </button>

      <button
        v-if="itemType === 'file' && canPreview()"
        class="w-full flex items-center gap-2.5 px-3 py-2 text-sm hover:bg-muted/70 transition-colors text-left"
        @click="doAction(() => emit('preview'))"
      >
        <Eye class="size-3.5 shrink-0" />
        Preview
      </button>

      <div class="h-px bg-border my-0.5 mx-2" />

      <button
        class="w-full flex items-center gap-2.5 px-3 py-2 text-sm hover:bg-muted/70 transition-colors text-left"
        @click="doAction(() => emit('rename'))"
      >
        <Pencil class="size-3.5 shrink-0" />
        Rename
      </button>

      <div class="h-px bg-border my-0.5 mx-2" />

      <button
        class="w-full flex items-center gap-2.5 px-3 py-2 text-sm hover:bg-destructive/10 text-destructive transition-colors text-left"
        @click="doAction(() => emit('delete'))"
      >
        <Trash2 class="size-3.5 shrink-0" />
        Delete
      </button>
    </div>
  </Teleport>
</template>
