<template>
    <teleport to="body">
        <transition name="fade">
            <div
                v-if="show"
                class="modal-overlay"
                @click.self="close"
            >
                <transition name="scale">
                    <div
                        v-if="show"
                        ref="modalRef"
                        class="modal-content"
                        tabindex="-1"
                        :style="{ width: width }"
                    >

                        <div class="modal-header">
                            <div class="title"><label>{{ title }}</label>
                                <span @click="close" class="dashicons dashicons-dismiss modal-close"></span>
                            </div>
                        </div>

                        <div class="modal-body">
                            <slot />
                        </div>
                    </div>
                </transition>
            </div>
        </transition>
    </teleport>
</template>

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

const props = defineProps({
    show: Boolean,
    title: { type: String, default: 'Modal' },
    width: { type: String, default: '1200px' },
})
const emit = defineEmits(['close'])

const modalRef = ref(null)

function close() {
    emit('close')
}

function handleKeyDown(e) {
    if (e.key === 'Escape') {
        close()
    }

    if (e.key === 'Tab' && modalRef.value) {
        const focusable = modalRef.value.querySelectorAll(
            'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
        )
        if (focusable.length === 0) return

        const first = focusable[0]
        const last = focusable[focusable.length - 1]

        if (e.shiftKey && document.activeElement === first) {
            e.preventDefault()
            last.focus()
        } else if (!e.shiftKey && document.activeElement === last) {
            e.preventDefault()
            first.focus()
        }
    }
}

watch(
    () => props.show,
    async (newVal) => {
        if (newVal) {
            document.body.style.overflow = 'hidden'
            await nextTick()
            modalRef.value?.focus()
        } else {
            document.body.style.overflow = ''
        }
    }
)

onMounted(() => {
    window.addEventListener('keydown', handleKeyDown)
})
onUnmounted(() => {
    window.removeEventListener('keydown', handleKeyDown)
    document.body.style.overflow = ''
})
</script>

<style scoped>
.modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 9999;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 10px;
}
.modal-content {
    background: white;
    border-radius: 12px;

    max-width: 1200px;
    width: 90%;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
    outline: none;
}

.modal-body {
    max-height: 80vh;
    overflow: auto;
}

/* Animation */
.fade-enter-active,
.fade-leave-active {
    transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
    opacity: 0;
}
.scale-enter-active,
.scale-leave-active {
    transition: transform 0.25s ease, opacity 0.25s ease;
}
.scale-enter-from,
.scale-leave-to {
    transform: scale(0.95);
    opacity: 0;
}

/* ─── Tablet ─── */
@media (max-width: 1023px) {
    .modal-content {
        width: 95% !important;
        max-width: 95vw;
    }

    .modal-body {
        max-height: 70vh;
    }
}

/* ─── Smartphone ─── */
@media (max-width: 639px) {
    .modal-overlay {
        align-items: flex-end;
        padding: 0;
    }

    .modal-content {
        width: 100% !important;
        max-width: 100% !important;
        border-radius: 16px 16px 0 0;
    }

    .modal-body {
        max-height: 75vh;
    }
}
</style>
