<template>
  <Teleport to="body">
    <Transition
      name="modal-fade"
      @after-enter="onOpened"
      @after-leave="onClosed"
    >
      <div
        v-if="modelValue"
        class="modal-backdrop"
        @click="handleBackdropClick"
      >
        <div
          class="modal-container"
          :class="['modal-container-' + size, { 'open': modelValue }]"
          role="dialog"
          aria-modal="true"
          :aria-labelledby="titleId"
          :aria-describedby="bodyId"
          @click.stop
        >
          <div v-if="$slots.header || title || !hideCloseButton" class="modal-header">
            <slot name="header">
              <h3 v-if="title" :id="titleId" class="modal-title">{{ title }}</h3>
              <button
                v-if="!hideCloseButton"
                type="button"
                class="close-button"
                @click="closeModal"
                aria-label="Close modal"
              >
                <VIcon name="close" />
              </button>
            </slot>
          </div>

          <div class="modal-body" :id="bodyId">
            <slot></slot>
          </div>

          <div v-if="$slots.footer" class="modal-footer">
            <slot name="footer"></slot>
          </div>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<script lang="ts" setup>
import { computed, watch, onMounted, onBeforeUnmount, ref } from 'vue';
import VIcon from './VIcon.vue'; // Assuming VIcon is available

const props = defineProps({
  modelValue: {
    type: Boolean,
    required: true,
  },
  title: {
    type: String,
    default: null,
  },
  hideCloseButton: {
    type: Boolean,
    default: false,
  },
  persistent: {
    type: Boolean,
    default: false,
  },
  size: {
    type: String, // 'sm', 'md', 'lg'
    default: 'md',
    validator: (value: string) => ['sm', 'md', 'lg'].includes(value),
  },
  idBase: {
    type: String,
    default: null,
  },
});

const emit = defineEmits(['update:modelValue', 'close', 'opened', 'closed']);

const uniqueComponentId = ref(`modal-${Math.random().toString(36).substring(2, 9)}`);

const titleId = computed(() => props.idBase ? `${props.idBase}-title` : `${uniqueComponentId.value}-title`);
const bodyId = computed(() => props.idBase ? `${props.idBase}-description` : `${uniqueComponentId.value}-description`);

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

const handleBackdropClick = () => {
  if (!props.persistent) {
    closeModal();
  }
};

const handleEscKey = (event: KeyboardEvent) => {
  if (event.key === 'Escape' && props.modelValue) {
    closeModal();
  }
};

watch(() => props.modelValue, (isOpen) => {
  if (isOpen) {
    document.body.classList.add('modal-open');
    document.addEventListener('keydown', handleEscKey);
  } else {
    document.body.classList.remove('modal-open');
    document.removeEventListener('keydown', handleEscKey);
  }
});

// Cleanup listener if component is unmounted while modal is open
onBeforeUnmount(() => {
  if (props.modelValue) {
    document.body.classList.remove('modal-open');
    document.removeEventListener('keydown', handleEscKey);
  }
});

const onOpened = () => {
  emit('opened');
};

const onClosed = () => {
  emit('closed');
};

</script>

<style lang="scss" scoped>
.modal-backdrop {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1050; // Ensure it's above most other content
}

.modal-container {
  background-color: #fff;
  border-radius: 0.375rem; // 6px
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
  display: flex;
  flex-direction: column;
  max-height: 90vh; // Prevent modal from being too tall
  overflow: hidden; // Needed for children with overflow (e.g. scrollable body)

  // Default size (md)
  width: 500px; // Example, adjust as needed
  max-width: 90%;

  &.modal-container-sm {
    width: 300px;
  }
  &.modal-container-lg {
    width: 800px;
  }
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid #e0e0e0; // Example border

  .modal-title {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 500;
  }

  .close-button {
    background: transparent;
    border: none;
    font-size: 1.5rem; // Make VIcon larger if it inherits font-size
    padding: 0.25rem;
    margin: -0.25rem; // Adjust for padding to align visual edge
    line-height: 1;
    cursor: pointer;
    color: #6c757d; // Muted color

    &:hover {
      color: #343a40;
    }
    // VIcon specific styling if needed, e.g., for stroke width or size
    // ::v-deep(.icon) { font-size: 1.2em; }
  }
}

.modal-body {
  padding: 1.25rem;
  overflow-y: auto; // Scrollable body if content exceeds max-height
  flex-grow: 1; // Allow body to take available space
}

.modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end; // Common: buttons to the right
  padding: 1rem 1.25rem;
  border-top: 1px solid #e0e0e0;
  gap: 0.5rem; // Space between footer items (buttons)
}

// Transitions
.modal-fade-enter-active,
.modal-fade-leave-active {
  transition: opacity 0.3s ease;
}
.modal-fade-enter-active .modal-container,
.modal-fade-leave-active .modal-container {
  transition: transform 0.3s ease-out; // Slightly different timing for container
}

.modal-fade-enter-from,
.modal-fade-leave-to {
  opacity: 0;
}
.modal-fade-enter-from .modal-container,
.modal-fade-leave-to .modal-container {
  transform: translateY(-50px) scale(0.95); // Example: slide down and scale
}

// This class is applied to <body>
// ::v-global(body.modal-open) {
//   overflow: hidden;
// }
// Note: ::v-global is not standard. This is typically handled in main CSS or via JS on body.
// The JS part `document.body.classList.add('modal-open')` is already there.
// The style for `body.modal-open` should be in a global stylesheet.
// For demo purposes, if it were here (which it shouldn't be):
// :global(body.modal-open) {
//   overflow: hidden;
// }
</style>
