<template>
  <Teleport to="body">
    <div
      v-if="modelValue"
      class="modal fade show d-block app-modal-root"
      tabindex="-1"
      role="dialog"
      aria-modal="true"
      @keydown.esc.prevent="close"
    >
      <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" :class="dialogClass" @click.stop>
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title">{{ title }}</h5>
            <button
              type="button"
              class="btn-close"
              aria-label="Cerrar"
              :disabled="busy"
              @click="close"
            />
          </div>
          <div class="modal-body">
            <slot />
          </div>
          <div v-if="$slots.footer" class="modal-footer">
            <slot name="footer" :close="close" :busy="busy" />
          </div>
        </div>
      </div>
      <div class="modal-backdrop fade show" @click="onBackdrop" />
    </div>
  </Teleport>
</template>

<script setup>
import { computed, onBeforeUnmount, watch } from 'vue'

const props = defineProps({
  modelValue: { type: Boolean, default: false },
  title: { type: String, default: '' },
  size: { type: String, default: 'lg' }, // sm | md | lg | xl
  busy: { type: Boolean, default: false },
  closeOnBackdrop: { type: Boolean, default: true },
})

const emit = defineEmits(['update:modelValue', 'close'])

const dialogClass = computed(() => {
  if (props.size === 'sm') return 'modal-sm'
  if (props.size === 'xl') return 'modal-xl'
  if (props.size === 'md') return ''
  return 'modal-lg'
})

function close() {
  if (props.busy) return
  emit('update:modelValue', false)
  emit('close')
}

function onBackdrop() {
  if (props.closeOnBackdrop) close()
}

function lockBody(lock) {
  if (typeof document === 'undefined') return
  document.body.classList.toggle('modal-open', lock)
  document.body.style.overflow = lock ? 'hidden' : ''
}

watch(
  () => props.modelValue,
  (open) => lockBody(open),
  { immediate: true },
)

onBeforeUnmount(() => lockBody(false))
</script>

<style scoped>
.app-modal-root {
  z-index: 1055;
}
.modal-backdrop {
  z-index: -1;
  position: absolute;
  inset: 0;
}
.app-modal-root :deep(.modal-dialog) {
  z-index: 1;
  position: relative;
}
</style>
