<template>
  <transition name="modal-fade">
    <div v-if="modelValue" class="modal-overlay" @click="handleOverlayClick">
      <transition name="modal-slide">
        <div
          v-if="modelValue"
          class="modal-container"
          :class="sizeClasses"
          @click.stop
        >
          <!-- Header -->
          <div v-if="!hideHeader" class="modal-header">
            <div class="modal-title-section">
              <h3 class="modal-title">{{ title }}</h3>
              <p v-if="description" class="modal-description">{{ description }}</p>
            </div>
            <button
              v-if="!hideClose"
              @click="close"
              class="modal-close-btn"
              aria-label="Close modal"
            >
              <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
                <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
              </svg>
            </button>
          </div>

          <!-- Body -->
          <div class="modal-body" :class="{ 'py-6': !noPadding }">
            <slot></slot>
          </div>

          <!-- Footer -->
          <div v-if="$slots.footer" class="modal-footer">
            <slot name="footer"></slot>
          </div>
        </div>
      </transition>
    </div>
  </transition>
</template>

<script setup lang="ts">
import { computed, watch } from 'vue'

interface Props {
  modelValue: boolean
  title?: string
  description?: string
  size?: 'sm' | 'md' | 'lg' | 'xl' | 'full'
  hideHeader?: boolean
  hideClose?: boolean
  closeOnOverlay?: boolean
  noPadding?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  size: 'md',
  hideHeader: false,
  hideClose: false,
  closeOnOverlay: true,
  noPadding: false
})

const emit = defineEmits<{
  'update:modelValue': [value: boolean]
  close: []
}>()

const sizeClasses = computed(() => {
  const sizes = {
    sm: 'max-w-md',
    md: 'max-w-2xl',
    lg: 'max-w-4xl',
    xl: 'max-w-6xl',
    full: 'max-w-full mx-4'
  }
  return sizes[props.size]
})

const close = () => {
  emit('update:modelValue', false)
  emit('close')
}

const handleOverlayClick = () => {
  if (props.closeOnOverlay) {
    close()
  }
}

// Prevent body scroll when modal is open
watch(() => props.modelValue, (isOpen) => {
  if (isOpen) {
    document.body.style.overflow = 'hidden'
  } else {
    document.body.style.overflow = ''
  }
})
</script>

<style scoped>
.modal-overlay {
  @apply fixed inset-0 z-50 flex items-center justify-center;
  @apply bg-black/60 backdrop-blur-sm;
  @apply p-4;
}

.modal-container {
  @apply bg-base-100 rounded-2xl shadow-strong;
  @apply w-full max-h-[90vh] overflow-hidden;
  @apply flex flex-col;
}

.modal-header {
  @apply flex items-start justify-between gap-4;
  @apply px-6 py-5 border-b border-base-300;
}

.modal-title-section {
  @apply flex-1;
}

.modal-title {
  @apply text-2xl font-bold text-base-content;
}

.modal-description {
  @apply text-sm text-base-content/60 mt-1;
}

.modal-close-btn {
  @apply flex-shrink-0 w-8 h-8 rounded-lg;
  @apply flex items-center justify-center;
  @apply hover:bg-base-200 transition-colors;
  @apply text-base-content/60 hover:text-base-content;
}

.modal-body {
  @apply flex-1 overflow-y-auto px-6;
}

.modal-footer {
  @apply px-6 py-4 border-t border-base-300;
  @apply flex items-center justify-end gap-3;
}

/* Transitions */
.modal-fade-enter-active,
.modal-fade-leave-active {
  transition: opacity 0.3s ease;
}

.modal-fade-enter-from,
.modal-fade-leave-to {
  opacity: 0;
}

.modal-slide-enter-active,
.modal-slide-leave-active {
  transition: all 0.3s ease;
}

.modal-slide-enter-from {
  opacity: 0;
  transform: translateY(-20px) scale(0.95);
}

.modal-slide-leave-to {
  opacity: 0;
  transform: translateY(20px) scale(0.95);
}
</style>
