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

const props = defineProps<{
  open: boolean;
  title?: string;
  size?: 'sm' | 'md' | 'lg';
}>();

const emit = defineEmits<{ close: [] }>();

function handleKeydown(e: KeyboardEvent) {
  if (e.key === 'Escape') emit('close');
}

watch(() => props.open, (val) => {
  document.body.style.overflow = val ? 'hidden' : '';
});

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

<template>
  <Teleport to="body">
    <Transition name="modal">
      <div v-if="open" class="modal-backdrop" @click.self="emit('close')" role="dialog" aria-modal="true" :aria-label="title">
        <div class="modal" :class="`modal--${size ?? 'md'}`">
          <div v-if="title || $slots.header" class="modal__header">
            <h2 v-if="title" class="modal__title">{{ title }}</h2>
            <slot name="header" />
            <button class="modal__close" @click="emit('close')" aria-label="Закрыть">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M18 6L6 18M6 6l12 12"/></svg>
            </button>
          </div>
          <div class="modal__body">
            <slot />
          </div>
          <div v-if="$slots.footer" class="modal__footer">
            <slot name="footer" />
          </div>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<style scoped lang="scss">
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  background: var(--color-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.modal {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-modal);
  width: 100%;
  max-height: 90dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;

  &--sm { max-width: 400px; }
  &--md { max-width: 560px; }
  &--lg { max-width: 800px; }

  &__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px 24px;
    border-bottom: 1px solid var(--color-border);
    flex-shrink: 0;
  }

  &__title {
    font-family: var(--font-display);
    font-size: 1.25rem;
    color: var(--color-cream);
    margin: 0;
  }

  &__close {
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--color-muted);
    cursor: pointer;
    border-radius: var(--radius-sm);
    transition: color var(--transition-fast);
    flex-shrink: 0;

    &:hover { color: var(--color-cream); }

    svg { width: 18px; height: 18px; }
  }

  &__body {
    flex: 1;
    overflow-y: auto;
    padding: 24px;
  }

  &__footer {
    padding: 16px 24px;
    border-top: 1px solid var(--color-border);
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    flex-shrink: 0;
  }
}

.modal-enter-active, .modal-leave-active {
  transition: opacity var(--transition-base);
  .modal { transition: transform var(--transition-spring), opacity var(--transition-base); }
}
.modal-enter-from, .modal-leave-to {
  opacity: 0;
  .modal { transform: scale(0.95) translateY(8px); opacity: 0; }
}
</style>
