<script setup>
import { ref, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'
import {
    FolderOpenIcon, PencilSquareIcon, CodeBracketIcon,
    EyeIcon, PlayCircleIcon, SpeakerWaveIcon, PhotoIcon,
    ArrowDownTrayIcon, ClipboardDocumentIcon, DocumentDuplicateIcon,
    TrashIcon, ArchiveBoxIcon, ArchiveBoxXMarkIcon,
    LockClosedIcon, LinkIcon, InformationCircleIcon, ScissorsIcon,
    DocumentIcon, ArrowsRightLeftIcon,
} from '@heroicons/vue/24/outline'
import { useFileIcon } from '@/Composables/useFileIcons'

/**
 * Floating, viewport-aware context menu.
 *
 * Dynamic action set per file type:
 *   - dir       → Open / Paste-into / standard ops
 *   - image     → View, +standard
 *   - video     → Play, +standard
 *   - audio     → Play, +standard
 *   - text/code → Edit, Preview, +standard
 *   - archive   → Extract, Preview-content, +standard
 *   - other     → Download as primary, +standard
 *
 * Protected items (isProtected) lose destructive operations entirely (cut,
 * rename, duplicate, archive, chmod, delete). They still get viewer / copy
 * / properties — those are non-destructive.
 *
 * Backwards-compatible API surface:
 *   - v-model:show              (legacy) — when false, menu hides
 *   - props.show, x, y, item    legacy
 *   - props.canPaste            legacy (clipboard has content)
 *   - props.isProtected         NEW — drives readonly UI
 *   - props.inClipboard         NEW — currently cut/copied (subtle hint)
 *   - emit('update:show', false) on close
 *   - emit('close')             NEW alias
 *   - emit('action', name, item) legacy fire-once
 *   - emit('<action>')          NEW per-action emits (open, edit, preview,
 *       rename, download, copy, cut, paste, delete, duplicate, archive,
 *       extract, chmod, copy-path, properties, move)
 */
const props = defineProps({
    show: { type: Boolean, default: false },
    x: { type: Number, default: 0 },
    y: { type: Number, default: 0 },
    item: { type: Object, default: null },
    canPaste: { type: Boolean, default: false },
    isProtected: { type: Boolean, default: false },
    inClipboard: { type: Boolean, default: false },
})

const emit = defineEmits([
    'update:show', 'close', 'action',
    'open', 'edit', 'preview', 'rename', 'download',
    'copy', 'cut', 'paste', 'delete', 'duplicate',
    'archive', 'extract', 'chmod', 'copy-path', 'properties', 'move',
])

const { isImage, isVideo, isAudio, isText, isArchive } = useFileIcon()

const menuEl = ref(null)
const adjustedPos = ref({ left: -9999, top: -9999 })

const isDir = computed(() => props.item?.type === 'dir' || props.item?.type === 'folder')
const ext = computed(() => (props.item?.name || '').split('.').pop()?.toLowerCase() || '')
const isCode = computed(() => ['php','js','mjs','ts','tsx','jsx','vue','py','rb','go','rs','java','c','cpp','cs','sh','bash','sql','json','xml','yml','yaml','toml','ini','conf','env','log','css','scss','less','html','htm','md'].includes(ext.value))

/**
 * Build the menu shape. Each section is an array of action items;
 * sections are visually separated by hairline dividers.
 */
const menuSections = computed(() => {
    const item = props.item
    if (!item) return []

    const ro = props.isProtected
    const sections = []

    // ─── Section 1 — Primary "open" verb (varies by type) ──────────────
    const openSection = []
    if (isDir.value) {
        openSection.push({ id: 'open', label: 'Klasörü Aç', icon: FolderOpenIcon, kbd: 'Enter' })
    } else if (isImage(item.name)) {
        openSection.push({ id: 'preview', label: 'Görüntüle', icon: PhotoIcon, kbd: 'Enter' })
    } else if (isVideo(item.name)) {
        openSection.push({ id: 'preview', label: 'Oynat', icon: PlayCircleIcon, kbd: 'Enter' })
    } else if (isAudio(item.name)) {
        openSection.push({ id: 'preview', label: 'Çal', icon: SpeakerWaveIcon, kbd: 'Enter' })
    } else if (isArchive(item.name)) {
        if (!ro) openSection.push({ id: 'extract', label: 'Çıkar (Extract)', icon: ArchiveBoxXMarkIcon })
        openSection.push({ id: 'preview', label: 'İçeriği Önizle', icon: EyeIcon })
    } else if (isText(item.name) && !isCode.value) {
        openSection.push({ id: 'edit', label: 'Düzenle', icon: PencilSquareIcon, kbd: 'Ctrl+E' })
        openSection.push({ id: 'preview', label: 'Önizle', icon: EyeIcon, kbd: 'Space' })
    } else if (isCode.value) {
        openSection.push({ id: 'edit', label: 'Düzenle (Kod)', icon: CodeBracketIcon, kbd: 'Ctrl+E' })
        openSection.push({ id: 'preview', label: 'Önizle', icon: EyeIcon, kbd: 'Space' })
    } else {
        // Binary / unknown → download as primary verb.
        openSection.push({ id: 'download', label: 'İndir', icon: ArrowDownTrayIcon, kbd: 'Ctrl+D' })
    }
    sections.push({ id: 'open', items: openSection, primary: true })

    // ─── Section 2 — Edit (rename, duplicate) ──────────────────────────
    const editSection = []
    if (!ro) {
        editSection.push({ id: 'rename', label: 'Yeniden Adlandır', icon: PencilSquareIcon, kbd: 'F2' })
    }
    if (!ro && !isDir.value) {
        editSection.push({ id: 'duplicate', label: 'Çoğalt (Kopya Oluştur)', icon: DocumentDuplicateIcon })
    }
    if (editSection.length) sections.push({ id: 'edit', items: editSection })

    // ─── Section 3 — Clipboard (cut/copy/paste/move) ───────────────────
    const clipSection = []
    if (!ro) {
        clipSection.push({ id: 'cut', label: 'Kes', icon: ScissorsIcon, kbd: 'Ctrl+X' })
    }
    clipSection.push({ id: 'copy', label: 'Kopyala', icon: DocumentDuplicateIcon, kbd: 'Ctrl+C' })
    if (isDir.value && props.canPaste) {
        clipSection.push({ id: 'paste', label: 'Klasöre Yapıştır', icon: ClipboardDocumentIcon, kbd: 'Ctrl+V' })
    }
    if (!ro) {
        clipSection.push({ id: 'move', label: 'Taşı...', icon: ArrowsRightLeftIcon })
    }
    if (clipSection.length) sections.push({ id: 'clip', items: clipSection })

    // ─── Section 4 — Transfer (download, archive) ──────────────────────
    const transferSection = []
    if (!isDir.value) {
        // Already in section 1 for binaries — skip double entry there.
        const alreadyPrimary = openSection.some(a => a.id === 'download')
        if (!alreadyPrimary) {
            transferSection.push({ id: 'download', label: 'İndir', icon: ArrowDownTrayIcon, kbd: 'Ctrl+D' })
        }
    } else {
        transferSection.push({ id: 'download', label: 'Klasörü ZIP olarak indir', icon: ArrowDownTrayIcon })
    }
    if (!ro) {
        transferSection.push({ id: 'archive', label: 'Sıkıştır (ZIP)', icon: ArchiveBoxIcon })
    }
    if (transferSection.length) sections.push({ id: 'transfer', items: transferSection })

    // ─── Section 5 — Meta (chmod, copy-path, properties) ───────────────
    const metaSection = []
    if (!ro) {
        metaSection.push({ id: 'chmod', label: 'İzinler (chmod)', icon: LockClosedIcon })
    }
    metaSection.push({ id: 'copy-path', label: 'Yolu Kopyala', icon: LinkIcon })
    metaSection.push({ id: 'properties', label: 'Özellikler', icon: InformationCircleIcon })
    sections.push({ id: 'meta', items: metaSection })

    // ─── Section 6 — Danger zone (delete) ──────────────────────────────
    if (!ro) {
        sections.push({
            id: 'danger',
            items: [{
                id: 'delete',
                label: isDir.value ? 'Klasörü Sil' : 'Sil',
                icon: TrashIcon,
                danger: true,
                kbd: 'Del',
            }],
        })
    }

    return sections
})

// ── Viewport-aware position ────────────────────────────────────────────
const reposition = async () => {
    await nextTick()
    if (!menuEl.value) return
    const rect = menuEl.value.getBoundingClientRect()
    const vw = window.innerWidth
    const vh = window.innerHeight
    let left = props.x
    let top = props.y
    if (left + rect.width > vw - 4) left = Math.max(4, vw - rect.width - 8)
    if (top + rect.height > vh - 4) top = Math.max(4, vh - rect.height - 8)
    adjustedPos.value = { left, top }
}

watch(() => [props.show, props.x, props.y, props.item], async ([show]) => {
    if (show) {
        // Hide off-screen first so we don't flash at top-left while measuring.
        adjustedPos.value = { left: -9999, top: -9999 }
        await reposition()
    }
})

// ── Close handlers ─────────────────────────────────────────────────────
const close = () => {
    emit('update:show', false)
    emit('close')
}

const fire = (id) => {
    if (!props.item) return close()
    // Legacy single 'action' emit (for back-compat with handleCtxAction).
    emit('action', id, props.item)
    // New per-action emits (no payload — caller already knows the item).
    emit(id)
    close()
}

const handleOutsideClick = (e) => {
    if (!menuEl.value?.contains(e.target)) close()
}

const handleEsc = (e) => {
    if (e.key === 'Escape') close()
}

onMounted(() => {
    document.addEventListener('mousedown', handleOutsideClick)
    document.addEventListener('keydown', handleEsc)
})

onBeforeUnmount(() => {
    document.removeEventListener('mousedown', handleOutsideClick)
    document.removeEventListener('keydown', handleEsc)
})

// Pick a header icon — folder vs first-section primary icon vs document.
const headerIcon = computed(() => {
    if (isDir.value) return FolderOpenIcon
    const first = menuSections.value[0]?.items?.[0]
    return first?.icon ?? DocumentIcon
})
</script>

<template>
    <Teleport to="body">
        <div v-if="show && item"
             ref="menuEl"
             role="menu"
             class="fixed z-[9999] min-w-[230px] max-w-[300px] overflow-hidden rounded-xl border border-slate-200 bg-white py-1 shadow-2xl ring-1 ring-black/5 dark:border-slate-700 dark:bg-slate-900 dark:ring-white/10"
             :style="{ left: adjustedPos.left + 'px', top: adjustedPos.top + 'px' }"
             @click.stop
             @contextmenu.prevent>
            <!-- Header (filename + lock badge) -->
            <div class="flex items-center gap-2 border-b border-slate-100 bg-slate-50/70 px-3 py-2 dark:border-slate-800 dark:bg-slate-800/50">
                <component :is="headerIcon" class="h-4 w-4 shrink-0 text-slate-500 dark:text-slate-400" />
                <span class="flex-1 truncate font-mono text-xs font-semibold text-slate-700 dark:text-slate-200"
                      :title="item.name">
                    {{ item.name }}
                </span>
                <span v-if="inClipboard"
                      class="shrink-0 rounded bg-indigo-100 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-300"
                      title="Panoda">
                    Pano
                </span>
                <LockClosedIcon v-if="isProtected"
                                class="h-3.5 w-3.5 shrink-0 text-amber-500"
                                title="Sistem klasörü — bazı işlemler engellenir" />
            </div>

            <!-- Action sections -->
            <template v-for="(section, sIdx) in menuSections" :key="section.id">
                <div v-if="sIdx > 0" class="my-1 border-t border-slate-100 dark:border-slate-800"></div>
                <button v-for="action in section.items"
                        :key="action.id"
                        type="button"
                        role="menuitem"
                        @click="fire(action.id)"
                        :class="[
                            'group flex w-full items-center gap-2.5 px-3 py-1.5 text-left text-sm transition-colors',
                            action.danger
                                ? 'text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-950/40'
                                : 'text-slate-700 hover:bg-slate-100 dark:text-slate-200 dark:hover:bg-slate-800',
                        ]">
                    <component :is="action.icon"
                               :class="[
                                   'h-4 w-4 shrink-0',
                                   action.danger ? 'text-red-500' : 'text-slate-500 group-hover:text-slate-700 dark:text-slate-400 dark:group-hover:text-slate-200',
                               ]" />
                    <span class="flex-1">{{ action.label }}</span>
                    <kbd v-if="action.kbd"
                         class="ml-2 rounded bg-slate-100 px-1 py-0.5 font-mono text-[10px] text-slate-500 dark:bg-slate-800 dark:text-slate-400">
                        {{ action.kbd }}
                    </kbd>
                </button>
            </template>

            <!-- Protected footer -->
            <div v-if="isProtected"
                 class="border-t border-amber-200 bg-amber-50 px-3 py-1.5 text-[11px] text-amber-700 dark:border-amber-900 dark:bg-amber-950/30 dark:text-amber-300">
                Sistem dosyası — silme/taşıma/yeniden adlandırma engellendi
            </div>
        </div>
    </Teleport>
</template>
