<script setup>
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';

const props = defineProps({
    align: {
        type: String,
        default: 'right',
    },
    width: {
        type: String,
        default: '48',
    },
    contentClasses: {
        type: Array,
        default: () => ['py-1', 'bg-white'],
    },
    closeOnContentClick: {
        type: Boolean,
        default: true,
    },
});

let open = ref(false);
const triggerEl = ref(null);
const panelEl = ref(null);
const panelStyle = ref({ top: '0px', left: '0px' });

const closeOnEscape = (e) => {
    if (open.value && e.key === 'Escape') {
        open.value = false;
    }
};

const updatePosition = () => {
    const t = triggerEl.value;
    const p = panelEl.value;
    if (!t || !p) return;
    const rect = t.getBoundingClientRect();
    // Ensure we have updated width
    const pw = p.offsetWidth || 0;
    const ph = p.offsetHeight || 0;
    const margin = 8; // small spacing from trigger
    let left = rect.left;
    if (props.align === 'right') {
        left = rect.right - pw;
    } else if (props.align === 'left') {
        left = rect.left;
    }
    // Clamp within viewport
    const maxLeft = Math.max(0, window.innerWidth - pw - margin);
    left = Math.min(Math.max(margin, left), maxLeft);
    let top = rect.bottom + margin;
    // If not enough space below, place above the trigger
    if (top + ph > window.innerHeight) {
        top = Math.max(margin, rect.top - ph - margin);
    }
    panelStyle.value = { top: `${top}px`, left: `${left}px` };
};

const onWindowChange = () => {
    updatePosition();
};

watch(open, async (val) => {
    if (val) {
        await nextTick();
        updatePosition();
        window.addEventListener('resize', onWindowChange);
        window.addEventListener('scroll', onWindowChange, true);
    } else {
        window.removeEventListener('resize', onWindowChange);
        window.removeEventListener('scroll', onWindowChange, true);
    }
});

onMounted(() => document.addEventListener('keydown', closeOnEscape));
onUnmounted(() => {
    document.removeEventListener('keydown', closeOnEscape);
    window.removeEventListener('resize', onWindowChange);
    window.removeEventListener('scroll', onWindowChange, true);
});

const widthClass = computed(() => {
    const map = {
        '48': 'w-48', // 12rem
        '64': 'w-64', // 16rem
        '72': 'w-72', // 18rem
        '80': 'w-80', // 20rem
        '96': 'w-96', // 24rem
        'wide': 'w-[34rem] max-w-[90vw]',
        'auto': '',
    };
    return map[props.width.toString()] ?? '';
});

const alignmentClasses = computed(() => {
    if (props.align === 'left') {
        return 'ltr:origin-top-left rtl:origin-top-right start-0';
    }

    if (props.align === 'right') {
        return 'ltr:origin-top-right rtl:origin-top-left end-0';
    }

    return 'origin-top';
});
const onContentClick = () => {
    if (props.closeOnContentClick) {
        open.value = false;
    }
};
</script>

<template>
    <div class="relative" ref="triggerEl">
        <div @click="open = ! open">
            <slot name="trigger" />
        </div>

        <teleport to="body">
            <!-- Full Screen Dropdown Overlay at body level -->
            <div v-show="open" class="fixed inset-0 z-[2147483646]" @click="open = false" />

            <transition
                enter-active-class="transition ease-out duration-200"
                enter-from-class="transform opacity-0 scale-95"
                enter-to-class="transform opacity-100 scale-100"
                leave-active-class="transition ease-in duration-75"
                leave-from-class="transform opacity-100 scale-100"
                leave-to-class="transform opacity-0 scale-95"
            >
                <div
                    v-show="open"
                    ref="panelEl"
                    class="fixed z-[2147483647] rounded-md shadow-lg"
                    :class="[widthClass]"
                    :style="[panelStyle]"
                >
                    <div class="rounded-md ring-1 ring-black ring-opacity-5" :class="contentClasses" @click="onContentClick">
                        <slot name="content" />
                    </div>
                </div>
            </transition>
        </teleport>
    </div>
</template>
