import { defineStore } from 'pinia';
import type { Component } from 'vue';
import { computed, ref, shallowRef } from 'vue';
import { ModalPositionTypes } from '@/UI-kit/types';

export interface IModalProps {
    isHaveCloseModal?: boolean;
    isShowXBtn?: boolean;
    title?: string;
    position?: ModalPositionTypes;
    linkStyle?: boolean;
    fixedHeight?: boolean;
    classList?: any;
}

export interface IModalArg {
    modalProps?: IModalProps;
    component: Component | (() => Promise<Component>);
    componentProps?: Record<string, any>;
    listeners?: Record<string, (...args: any[]) => any>;
}

export interface IModal extends IModalArg {
    id: number;
    isOpen: boolean;
}

export interface IActiveModal {
    id: number;
    isOpen: boolean;
    component: Component;
    modalProps?: IModalProps;
}

type ComponentModule = { default: Component };

export const useUIModalStore = defineStore('ui-modal', () => {
    const modalList = ref<IModal[]>([]);

    const activeModal = computed<IActiveModal | undefined>(() => firstModal());

    const firstModal = () => modalList.value[modalList.value.length - 1];

    const findModal = (id?: number) => {
        return id ? modalList.value.find((modal) => modal.id === id) : firstModal();
    };

    const openModal = async (data: IModalArg) => {
        const id = Math.floor((1 + Math.random()) * 100000);

        let component = data.component;

        if (typeof component === 'function' && !('setup' in component)) {
            // ленивый компонент
            const resolved = await (component as () => Promise<ComponentModule>)();
            component = resolved.default;
        }

        modalList.value.push({
            ...data,
            modalProps: {
                isHaveCloseModal: true,
                isShowXBtn: true,
                title: '',
                position: ModalPositionTypes.BOTTOM,
                ...(data.modalProps ? data.modalProps : {}),
            },
            isOpen: true,
            id,
            component: shallowRef(component),
        });

        return id;
    };

    const closeModal = (id?: number) => {
        let modalId = id;

        if (!modalId) {
            modalId = activeModal.value?.id;
        }

        const findIndex = modalList.value.findIndex((item) => item.id === modalId);
        if (findIndex > -1) {
            modalList.value.splice(findIndex, 1);
        }
    };

    /** Закрыть все модалки в стеке (очистить список). */
    const closeAllModals = () => {
        modalList.value = [];
    };

    const isOpen = (id: number) => {
        const modal = findModal(id);

        if (!modal) {
            return false;
        }

        return modal.isOpen;
    };

    const updateModalProps = (props: IModalArg['modalProps'], id?: number) => {
        const modal = findModal(id);

        if (!modal) {
            return;
        }
        modal.modalProps = Object.assign(modal?.modalProps || {}, props);
        return modal;
    };

    const updateComponentProps = (props: IModalArg['componentProps'], id?: number) => {
        const modal = findModal(id);

        if (!modal) {
            return;
        }
        modal.componentProps = Object.assign(modal?.componentProps || {}, props);
        return modal;
    };

    return {
        modalList,
        activeModal,
        isOpen,
        openModal,
        closeModal,
        closeAllModals,
        updateModalProps,
        updateComponentProps,
    };
});
