<template>
  <Teleport to="body">
    <div
      v-if="isOpen"
      :id="componentId"
      class="fixed inset-0 z-50"
      v-bind="attrs"
    >
      <Transition name="drawer-backdrop">
        <div
          v-if="isOpen"
          class="absolute inset-0 bg-black/40"
          data-test="backdrop"
          @click="close"
        />
      </Transition>

      <Transition name="drawer-panel">
        <div
          v-if="isOpen"
          :class="twMerge(
            'absolute right-0 top-0 h-full w-full max-w-md bg-white shadow-xl',
            drawerClass,
          )"
          role="dialog"
          :aria-modal="true"
          :aria-labelledby="titleId"
          data-test="panel"
        >
          <div class="flex items-center justify-between px-5 pb-8 pt-8">
            <h2
              :id="titleId"
              class="text-[32px] font-semibold text-m-primary"
            >
              {{ title }}
            </h2>
            <button
              v-if="showClose"
              type="button"
              aria-label="Fermer"
              class="flex h-8 w-8 cursor-pointer items-center justify-center rounded-full transition-colors hover:bg-m-surface"
              data-test="close-button"
              @click="close"
            >
              <IconifyIcon
                icon="mdi:close"
                :width="24"
                :height="24"
              />
            </button>
          </div>

          <div
            class="overflow-y-auto px-5"
            style="max-height: calc(100% - 96px)"
          >
            <slot />
          </div>
        </div>
      </Transition>
    </div>
  </Teleport>
</template>

<script setup lang="ts">
import { computed, ref, useAttrs, useId } from 'vue'
import { Icon as IconifyIcon } from '@iconify/vue'
import { twMerge } from 'tailwind-merge'

defineOptions({ name: 'MalioDrawer', inheritAttrs: false })

const props = withDefaults(
  defineProps<{
    id?: string
    modelValue?: boolean
    title?: string
    showClose?: boolean
    drawerClass?: string
  }>(),
  {
    id: '',
    modelValue: undefined,
    title: '',
    showClose: true,
    drawerClass: '',
  },
)

const emit = defineEmits<{
  (e: 'update:modelValue', value: boolean): void
}>()

const attrs = useAttrs()
const generatedId = useId()

const componentId = computed(() => props.id || `malio-drawer-${generatedId}`)
const titleId = computed(() => `${componentId.value}-title`)

const isControlled = computed(() => props.modelValue !== undefined)
const localValue = ref(false)

const isOpen = computed(() =>
  isControlled.value ? props.modelValue! : localValue.value,
)

function close() {
  if (!isControlled.value) {
    localValue.value = false
  }
  emit('update:modelValue', false)
}
</script>

<style scoped>
.drawer-backdrop-enter-active,
.drawer-backdrop-leave-active {
  transition: opacity 0.2s ease;
}

.drawer-backdrop-enter-from,
.drawer-backdrop-leave-to {
  opacity: 0;
}

.drawer-panel-enter-active,
.drawer-panel-leave-active {
  transition: transform 0.2s ease, opacity 0.2s ease;
}

.drawer-panel-enter-from,
.drawer-panel-leave-to {
  transform: translateX(100%);
  opacity: 0;
}
</style>
