<template>
  <Teleport to="body">
    <Transition name="fade-scale" @after-enter="onOpened" @after-leave="onClosed">
      <div v-if="isOpen" class="basic-modal" @click="onBackdropClick">
        <div class="basic-modal__container" :style="containerStyle" @click.stop>
          <div class="basic-modal__card scrollbar-thin">
            <header v-if="hasHeader" class="basic-modal__header">
              <slot name="header">
                <LineTitleBlock v-if="title || titleEn" :title="title" :title-en="titleEn" />
                <span v-else />
              </slot>
              <button
                v-if="showCloseButton"
                type="button"
                class="basic-modal__close"
                aria-label="بستن"
                @click="close"
              >
                <SvgIcon name="close" :size="36" color="#B1B1B1" />
              </button>
            </header>
            <slot :data="modalData" :close="close" />
          </div>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<script setup>
import { useModalStore } from '@/store/modal'
import SvgIcon from '@/components/icons/SvgIcon.vue'
import LineTitleBlock from '@/components/LineTitleBlock.vue'
import { computed, getCurrentInstance, onBeforeUnmount, useSlots, watch } from 'vue'

const props = defineProps({
  name: { type: String, default: '' },
  title: { type: String, default: '' },
  titleEn: { type: String, default: '' },
  closable: { type: Boolean, default: true },
  closeOnEsc: { type: Boolean, default: true },
  showCloseButton: { type: Boolean, default: true },
  width: { type: String, default: '' },
  maxWidth: { type: String, default: '98%' },
  minWidth: { type: String, default: '85%' },
})

const emit = defineEmits(['open', 'close'])

const instance = getCurrentInstance()
const slots = useSlots()
const { isModal, getModal, closeModal } = useModalStore()

const modalName = computed(() => props.name || instance?.parent?.type?.name || '')

const isOpen = computed(() => !!modalName.value && isModal(modalName.value))
const modalData = computed(() => getModal(modalName.value)?.data)

const hasHeader = computed(
  () => props.showCloseButton || !!slots.header || !!props.title || !!props.titleEn
)

const containerStyle = computed(() => {
  const style = { maxWidth: props.maxWidth, minWidth: props.minWidth }
  if (props.width) style.width = props.width
  return style
})

const close = () => closeModal(modalName.value)

const onBackdropClick = () => {
  if (props.closable) close()
}

const onOpened = () => emit('open', modalData.value)
const onClosed = () => emit('close')

const onKeydown = (e) => {
  if (e.key === 'Escape' && props.closeOnEsc && props.closable && isOpen.value) {
    e.preventDefault()
    close()
  }
}

watch(
  isOpen,
  (open) => {
    if (open) {
      window.addEventListener('keydown', onKeydown)
    } else {
      window.removeEventListener('keydown', onKeydown)
    }
  },
  { immediate: true }
)

onBeforeUnmount(() => window.removeEventListener('keydown', onKeydown))
</script>

<style lang="scss" scoped>
.basic-modal {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, 5%);
  backdrop-filter: blur(12px);

  &__container {
    background: transparent;
    border-radius: 1.5rem;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    overflow-x: hidden;
    position: relative;
    transition: all 0.2s ease;
    max-height: calc(100dvh - 10%);
  }

  &__card {
    width: 100%;
    padding: 1rem 1.25rem 1.5rem;
    background: #fff;
    border-radius: 1.5rem;
    overflow-y: auto;
    position: relative;
  }

  &__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.5rem;
  }

  &__close {
    height: 2.75rem;
    width: 2.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    cursor: pointer;
    border-radius: 9999px;
    flex-shrink: 0;

    &:hover {
      opacity: 0.7;
    }
  }
}

.fade-scale-enter-active,
.fade-scale-leave-active {
  transition: all 0.25s ease;
}

.fade-scale-enter-from,
.fade-scale-leave-to {
  opacity: 0;
  transform: scale(0.95);
}
</style>
