<script setup lang="ts">
    import { computed, ref, onMounted, nextTick, onBeforeUnmount } from 'vue';
    import { type IModal } from '@/UI-kit/store';
    import { ModalPositionTypes } from '@/UI-kit/types';

    const props = defineProps<{ modal: IModal }>();

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

    const popoverGlobal = ref<HTMLElement | null>(null);
    const modalContent = ref<HTMLElement | null>(null);
    const modalBox = ref<HTMLElement | null>(null);
    let resizeObserver: ResizeObserver | null = null;

    const isBottomPosition = computed(
        () => modalProps.value?.position === ModalPositionTypes.BOTTOM,
    );

    const modalProps = computed(() => props.modal?.modalProps || {});
    const listeners = computed(() => props.modal?.listeners || {});

    const classList = computed(() => ({
        '--center': modalProps.value?.position === ModalPositionTypes.CENTER,
        '--bottom': isBottomPosition,
        '--link-style': modalProps.value?.linkStyle,
        ...modalProps.value?.classList,
    }));

    const observeContentResize = () => {
        if (!modalContent.value || modalProps.value?.position !== ModalPositionTypes.BOTTOM) return;

        resizeObserver = new ResizeObserver(() => {
            setTimeout(() => {
                setModalHeight();
            }, 50);
        });

        resizeObserver.observe(modalContent.value);
    };

    const setModalHeight = () => {
        if (
            !popoverGlobal.value ||
            !modalContent.value ||
            modalProps.value?.position !== ModalPositionTypes.BOTTOM
        )
            return;

        const headerEl = popoverGlobal.value.querySelector(
            '.ui-modal__header',
        ) as HTMLElement | null;
        const headerHeight = headerEl?.offsetHeight || 0;
        const contentScrollHeight = modalContent.value.scrollHeight;

        const safePadding = Math.max(
            window.innerHeight - document.documentElement.clientHeight,
            20,
        );
        const windowHeight = window.innerHeight;
        const maxHeight = windowHeight * 0.8 - safePadding;

        const totalHeight = headerHeight + contentScrollHeight;

        if (totalHeight > maxHeight) {
            popoverGlobal.value.style.height = `${maxHeight}px`;
        } else {
            popoverGlobal.value.style.height = '';
        }

        popoverGlobal.value.classList.add('ui-modal--show');
    };

    const dismiss = async (isSendEventClose = false) => {
        if (!popoverGlobal.value?.style || !modalProps.value?.isHaveCloseModal) {
            return;
        }

        popoverGlobal.value.classList.remove('ui-modal--show');
        modalBox.value?.classList.add('ui-modal__box--closing');

        if (resizeObserver && modalContent.value) {
            resizeObserver.unobserve(modalContent.value);
            resizeObserver.disconnect();
        }

        if (isSendEventClose && listeners.value.close) {
            listeners.value.close();
        }

        setTimeout(() => {
            emit('close');
        }, 350);
    };

    const onResize = () => {
        if (isBottomPosition.value) {
            setModalHeight();
        }
    };

    onMounted(() => {
        document.body.style.overflow = 'hidden';
        window.addEventListener('resize', onResize);

        nextTick(() => {
            modalBox.value?.classList.add('ui-modal__box--opening');

            if (isBottomPosition.value) {
                // setTimeout(() => {
                observeContentResize();
                // }, 50);
            }
        });
    });

    onBeforeUnmount(() => {
        document.body.style.overflow = '';
        window.removeEventListener('resize', onResize);
    });
</script>

<template>
    <div ref="modalBox" class="ui-modal__box" @click="dismiss(true)">
        <div ref="popoverGlobal" class="ui-modal" :class="classList" @click.stop="">
            <div class="ui-modal__header">
                <div class="ui-modal__title-wrap">
                    <div class="ui-modal__title-inner">
                        <p v-if="modalProps?.title" class="ui-modal__title">
                            {{ modalProps?.title }}
                        </p>
                    </div>
                    <button
                        v-if="modalProps?.isHaveCloseModal && modalProps?.isShowXBtn"
                        class="ui-modal__btn-back"
                        @click="dismiss(true)"
                    >
                        <svg
                            width="28"
                            height="28"
                            viewBox="0 0 28 28"
                            fill="none"
                            xmlns="http://www.w3.org/2000/svg"
                        >
                            <rect width="28" height="28" rx="14" fill="#F4F4F4" />
                            <path
                                d="M10.0863 9.04245C9.79438 8.75799 9.32707 8.76407 9.04253 9.05591C8.75808 9.34779 8.76415 9.8151 9.05599 10.0996L13.056 13.9997L9.05599 17.8998C8.76415 18.1843 8.75808 18.6516 9.04253 18.9435C9.32707 19.2354 9.79438 19.2414 10.0863 18.957L13.9998 15.1415L17.9133 18.957C18.2052 19.2414 18.6725 19.2354 18.9571 18.9435C19.2415 18.6516 19.2354 18.1843 18.9436 17.8998L14.9441 13.9997L18.9436 10.0996C19.2354 9.8151 19.2415 9.34779 18.9571 9.05591C18.6725 8.76407 18.2052 8.758 17.9133 9.04245L13.9998 12.8575L10.0863 9.04245Z"
                                fill="#047BEF"
                            />
                        </svg>
                    </button>
                </div>
                <slot name="header" />
            </div>
            <div ref="modalContent" class="ui-modal__wrap">
                <component
                    :is="modal.component"
                    v-bind="modal.componentProps"
                    v-on="listeners"
                    @close="dismiss"
                />
            </div>
        </div>
    </div>
</template>

<style lang="scss" scoped>
    .ui-modal {
        position: absolute;
        width: 100%;
        background: var(--white);
        transition: all 0.35s ease;
        will-change: height, opacity;
        overflow: auto;
        max-height: 0;

        &__box {
            position: fixed;
            inset: 0;
            z-index: 5;
            background: rgb(0 0 0 / 0%);

            &--opening {
                animation: boxShow 0.3s ease forwards;
            }

            &--closing {
                animation: boxClose 0.3s ease forwards;
            }
        }

        &--show {
            max-height: 90vh;
            height: auto;
            opacity: 1;
            transition: all 0.3s;
            border-radius: 12px 12px 0 0;
        }

        &.--center {
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            max-width: 90%;
            width: auto;
            border-radius: 12px;
        }

        &.--bottom {
            inset: auto 0 0 0;
        }

        &.--link-style :deep(a) {
            text-decoration: underline;
            text-decoration-style: dotted;
            text-decoration-thickness: 2px;
            text-underline-offset: 3px;
            text-decoration-skip-ink: none;
            color: var(--blue);
            overflow-wrap: break-word;
        }

        &__wrap {
            position: relative;
            display: flex;
            padding: 0 16px 16px 16px;
            flex-direction: column;
            gap: 14px;
            overflow: auto;
        }

        &__title {
            margin: 0;
            color: var(--gray-900);
            font-weight: 600;
            font-size: 20px;
            line-height: 24px;

            &-inner {
                position: relative;
                z-index: 3;
            }

            &-wrap {
                position: sticky;
                top: 0;
                display: flex;
                justify-content: space-between;
                align-items: center;
                gap: 10px;
                padding: 16px;
                background: inherit;
                border-color: transparent;
            }
        }

        :slotted([slot='header']) {
            padding: 0 16px;
        }

        &__header {
            position: sticky;
            top: 0;
            z-index: 99;
            background: var(--white);
        }

        &__btn {
            &-back {
                width: 28px;
                height: 28px;
                background: transparent;
                border: none;
                outline: none;
                border-radius: 100%;
                cursor: pointer;
            }
        }
    }

    @keyframes boxShow {
        from {
            background: rgb(0 0 0 / 0%);
        }

        to {
            background: rgb(0 0 0 / 30%);
        }
    }

    @keyframes boxClose {
        from {
            background: rgb(0 0 0 / 30%);
        }

        to {
            background: rgb(0 0 0 / 0%);
        }
    }
</style>
