<template>
  <Teleport
    v-if="Object.values(props).some((x) => isNotNil(x))"
    to="#__nuxt > div"
  >
    <div
      class="modal is-active has-text-text-20"
      @click="doClick"
    >
      <div
        class="modal-background"
        :style="`opacity:${count === 0 ? 0.7 : 0.3} !important;`"
      ></div>
      <div
        class="modal-card"
        :id="docid"
        :style="{
          width: $store.viewport <= 2 ? 'calc(100% - 2rem)' : width || '60%',
        }"
      >
        <header
          v-if="title"
          class="modal-card-head px-4 py-3"
        >
          <div class="w-full">
            <div class="field is-grouped is-align-items-center">
              <div class="control is-expanded has-text-left">
                <p
                  class="fs-17 font-semibold has-text-primary"
                  v-html="title"
                ></p>
              </div>
              <div class="control has-text-right">
                <button
                  class="delete is-medium"
                  @click="closeModal()"
                ></button>
              </div>
            </div>
          </div>
        </header>
        <section
          class="modal-card-body p-4"
          :style="{
            minHeight: height || '750px',
          }"
        >
          <component
            :is="resolvedComponent"
            v-bind="vbind"
            @modalevent="modalEvent"
            @close="closeModal"
          />
        </section>
        <footer class="modal-card-foot pt-0 px-4 pb-4"></footer>
      </div>
    </div>
  </Teleport>
</template>

<script setup>
import { onMounted, defineAsyncComponent, shallowRef, watchEffect } from "vue";
import { isNotNil } from "es-toolkit";

const emit = defineEmits(["close", "remove", "select", "dataevent", "update"]);
const { $id, $store } = useNuxtApp();

const props = defineProps({
  component: String,
  width: String,
  height: String,
  vbind: Object,
  title: String,
});

const componentFiles = import.meta.glob("@/components/**/*.vue");

const resolvedComponent = shallowRef(null);

function loadDynamicComponent() {
  if (!props.component) {
    resolvedComponent.value = null;
    return;
  }

  const fullPath = `/components/${props.component}.vue`;

  const componentPath = Object.keys(componentFiles).find((path) => path.endsWith(fullPath));

  if (componentPath) {
    resolvedComponent.value = defineAsyncComponent(componentFiles[componentPath]);
  } else {
    console.error(`Không tìm thấy component tại: ${fullPath}`);
    resolvedComponent.value = null;
  }
}

// Theo dõi sự thay đổi của props.component để load lại nếu cần
watchEffect(() => {
  loadDynamicComponent();
});

const docid = $id();
let count = 0;
const lock = false;

const closeModal = function () {
  if (!lock) emit("close");
};

const modalEvent = function (ev) {
  if (ev.name === "select") {
    emit("select", ev.data);
  } else if (ev.name === "dataevent") {
    emit("dataevent", ev.data);
  } else if (ev.name === "update") {
    emit("update", ev.data);
  } else {
    emit(ev.name, ev.data);
  }
};

const doClick = function (e) {
  if (!e.srcElement.offsetParent) return;
  const el = document.getElementById(docid);
  if (el && !el.contains(e.target)) {
    closeModal();
  }
};

onMounted(() => {
  if (Object.values(props).some((x) => isNotNil(x))) {
    document.documentElement.classList.add("is-clipped");
    window.addEventListener("keydown", (e) => {
      if (e.key === "Escape") closeModal();
    });
    const collection = document.getElementsByClassName("modal-background");
    count = collection.length;
  }
});

onUnmounted(() => {
  count--;
  if (count === 0) document.documentElement.classList.remove("is-clipped");
});
</script>
<style scoped>
footer:empty {
  display: none;
}
</style>
