<script setup lang="ts">
// Generic modal — for forms, wizards, and confirmations more elaborate than
// ConfirmDialog. Uses an explicit `size` token mapping to widths sm/md/lg.

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

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

const maxWidth = computed(() => ({ sm: 440, md: 600, lg: 880 })[props.size || 'md'])

// Close only when the press AND release both land on the backdrop. Without this,
// drag-selecting text inside an input and releasing on the backdrop fires a
// `click` on the backdrop (the common ancestor) and wrongly dismisses the modal.
const pressedOnBackdrop = ref(false)
function onBackdropMousedown(e: MouseEvent) {
  pressedOnBackdrop.value = e.target === e.currentTarget
}
function onBackdropClick() {
  if (pressedOnBackdrop.value) emit('close')
  pressedOnBackdrop.value = false
}

onMounted(() => {
  const onKey = (e: KeyboardEvent) => {
    if (e.key === 'Escape' && props.open) emit('close')
  }
  document.addEventListener('keydown', onKey)
  onBeforeUnmount(() => document.removeEventListener('keydown', onKey))
})
</script>

<template>
  <Teleport to="body">
    <Transition name="modal">
      <div v-if="open" class="backdrop" @mousedown="onBackdropMousedown" @click.self="onBackdropClick">
        <div class="modal" :style="{ maxWidth: maxWidth + 'px' }">
          <header v-if="title || eyebrow || $slots.header">
            <div class="lhs">
              <Eyebrow v-if="eyebrow">{{ eyebrow }}</Eyebrow>
              <h3 v-if="title">{{ title }}</h3>
              <slot name="header" />
            </div>
            <button class="close" @click="emit('close')" aria-label="Close">
              <UiIcon name="x" :size="18" />
            </button>
          </header>
          <div class="body">
            <slot />
          </div>
          <footer v-if="$slots.footer">
            <slot name="footer" />
          </footer>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<style scoped>
.backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 80;
}

.modal {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  width: 100%;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.4);
}

header {
  padding: 18px 24px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-shrink: 0;
}

h3 {
  margin: 4px 0 0 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 17px;
  letter-spacing: -0.015em;
}

.close {
  background: transparent;
  border: none;
  padding: 6px;
  border-radius: 4px;
  color: var(--text-dim);
  cursor: pointer;
}
.close:hover { background: var(--surface); }

.body {
  flex: 1;
  overflow-y: auto;
  padding: 22px 24px;
}

footer {
  padding: 14px 24px;
  border-top: 1px solid var(--border);
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  background: var(--surface);
  flex-shrink: 0;
}

.modal-enter-active, .modal-leave-active { transition: opacity 0.15s; }
.modal-enter-from, .modal-leave-to { opacity: 0; }
</style>
