<template>
    <div class="swiper-container">
        <div class="swiper-wrapper">
            <slot></slot>
        </div>
        <div class="swiper-button-prev" v-if="showNavigation"></div>
        <div class="swiper-button-next" v-if="showNavigation"></div>
        <div class="swiper-pagination" v-if="showPagination"></div>
    </div>
</template>

<script>
// Vue 2 compatible Swiper wrapper using Swiper 8 core
import Swiper, {Navigation, Pagination, Autoplay, Thumbs, EffectFade} from 'swiper';

// Enable modules globally
Swiper.use([Navigation, Pagination, Autoplay, Thumbs, EffectFade]);

export default {
    name: 'SwiperCompat',
    props: {
        // Commonly used props in the project
        slidesPerView: [Number, String],
        slidesPerGroup: [Number, String],
        spaceBetween: [Number, String],
        loop: {type: Boolean, default: false},
        width: [Number, String],
        effect: String,
        speed: [Number, String],
        autoplay: [Boolean, Object],
        navigation: {type: [Boolean, Object], default: false},
        pagination: {type: [Boolean, Object], default: false},
        allowTouchMove: {type: Boolean, default: true},
        breakpoints: {type: Object, default: () => ({})},
        // thumbs: expects { swiper: SwiperInstance }
        thumbs: {type: Object, default: null},
        // Additional props used in some components
        watchSlidesProgress: {type: Boolean, default: false},
        fadeEffect: {type: Object, default: null}
    },
    data() {
        return {
            swiper: null,
            slideObserver: null
        };
    },
    computed: {
        showNavigation() {
            return !!this.navigation;
        },
        showPagination() {
            return !!this.pagination;
        },
        swiperOptions() {
            const slideCount = this.$el ? this.$el.querySelectorAll('.swiper-slide').length : 0;
            const slidesPerView = this.coerceNumber(this.slidesPerView, 1);
            const enableLoop = slideCount >= 2 && this.loop;

            const options = {
                slidesPerView: slidesPerView,
                slidesPerGroup: this.coerceNumber(this.slidesPerGroup, undefined),
                spaceBetween: this.coerceNumber(this.spaceBetween, 0),
                // Disable loop automatically if there are fewer than 2 slides
                loop: enableLoop,
                allowTouchMove: this.allowTouchMove,
                watchSlidesProgress: this.watchSlidesProgress,
                breakpoints: this.breakpoints || {},
                // Help with dynamic content and Vite HMR
                observer: true,
                observeParents: true
            };

            // Loop mode: ensure enough duplicate slides to prevent classList errors
            if (enableLoop) {
                // Add extra slides to buffer for multi-slide views
                options.loopAdditionalSlides = Math.ceil(slidesPerView) + 1;
                // Automatically add blank slides if needed to match requirements
                options.loopAddBlankSlides = true;
            }

            if (this.width != null) options.width = this.coerceNumber(this.width, undefined);

            if (this.effect) options.effect = this.effect;

            if (this.speed != null) options.speed = this.coerceNumber(this.speed, undefined);

            // Navigation
            if (this.navigation) {
                options.navigation = Object.assign(
                    {
                        nextEl: this.$el ? this.$el.querySelector('.swiper-button-next') : '.swiper-button-next',
                        prevEl: this.$el ? this.$el.querySelector('.swiper-button-prev') : '.swiper-button-prev'
                    },
                    typeof this.navigation === 'object' ? this.navigation : {}
                );
            }

            // Pagination
            if (this.pagination) {
                options.pagination = Object.assign(
                    {
                        el: this.$el ? this.$el.querySelector('.swiper-pagination') : '.swiper-pagination',
                        clickable: true
                    },
                    typeof this.pagination === 'object' ? this.pagination : {}
                );
            }

            // Autoplay
            if (this.autoplay) {
                options.autoplay = typeof this.autoplay === 'object' ? this.autoplay : {
                    delay: 5000,
                    disableOnInteraction: false
                };
            }

            // Thumbs
            if (this.thumbs && this.thumbs.swiper) {
                options.thumbs = {swiper: this.thumbs.swiper};
            }

            // Fade Effect
            if (this.effect === 'fade') {
                options.effect = 'fade';
                if (this.fadeEffect) {
                    options.fadeEffect = Object.assign(
                        { crossFade: true },
                        this.fadeEffect
                    );
                } else {
                    options.fadeEffect = { crossFade: true };
                }
            }

            return options;
        }
    },
    methods: {
        coerceNumber(val, fallback) {
            if (val === undefined || val === null || val === '') return fallback;
            const n = Number(val);
            return isNaN(n) ? fallback : n;
        },
        initSwiper() {
            const tryInit = (attempt = 0) => {
                this.$nextTick(() => {
                    const slides = this.$el ? this.$el.querySelectorAll('.swiper-slide') : [];
                    const count = slides ? slides.length : 0;

                    // Also check pagination element exists if pagination is enabled
                    const needsPagination = this.pagination && this.$el;
                    const paginationEl = needsPagination ? this.$el.querySelector('.swiper-pagination') : true;

                    if (!count || (needsPagination && !paginationEl)) {
                        if (attempt < 20) {
                            return setTimeout(() => tryInit(attempt + 1), 100);
                        }
                        // As a fallback, observe for slide additions and init once present
                        if (!this.slideObserver && this.$el) {
                            this.slideObserver = new MutationObserver(() => {
                                const slidesNow = this.$el.querySelectorAll('.swiper-slide');
                                if (slidesNow && slidesNow.length) {
                                    try {
                                        this.slideObserver.disconnect();
                                    } catch (e) {
                                    }
                                    this.slideObserver = null;
                                    tryInit(0);
                                }
                            });
                            this.slideObserver.observe(this.$el.querySelector('.swiper-wrapper') || this.$el, {
                                childList: true,
                                subtree: true
                            });
                        }
                        return;
                    }

                    if (this.swiper) {
                        try {
                            this.swiper.destroy(true, true);
                        } catch (e) {
                        }
                        this.swiper = null;
                    }

                    const opts = this.swiperOptions;

                    try {
                        this.swiper = new Swiper(this.$el, opts);

                        // If loop mode and autoplay are enabled, wait for loop slides to be created
                        if (opts.loop && opts.autoplay) {
                            // Temporarily stop autoplay to let loop slides render
                            if (this.swiper.autoplay) {
                                this.swiper.autoplay.stop();
                                // Restart after a brief delay to ensure loop duplicates exist
                                setTimeout(() => {
                                    if (this.swiper && this.swiper.autoplay) {
                                        this.swiper.autoplay.start();
                                    }
                                }, 100);
                            }
                        }
                    } catch (e) {
                        // Suppress pagination classList errors - Swiper bug with rapid multi-instance init
                        if (e.message && e.message.includes('classList')) {
                            // Retry init after brief delay
                            setTimeout(() => {
                                try {
                                    this.swiper = new Swiper(this.$el, opts);
                                    // Same loop+autoplay handling for retry
                                    if (opts.loop && opts.autoplay && this.swiper.autoplay) {
                                        this.swiper.autoplay.stop();
                                        setTimeout(() => {
                                            if (this.swiper && this.swiper.autoplay) {
                                                this.swiper.autoplay.start();
                                            }
                                        }, 100);
                                    }
                                } catch (retryErr) {
                                    console.warn('Swiper init failed:', retryErr);
                                }
                            }, 100);
                        } else {
                            throw e;
                        }
                    }

                    if (this.slideObserver) {
                        try {
                            this.slideObserver.disconnect();
                        } catch (e) {
                        }
                        this.slideObserver = null;
                    }
                    this.$emit('swiper', this.swiper);
                });
            };

            tryInit();
        }
    },
    mounted() {
        this.initSwiper();
    },
    beforeDestroy() {
        if (this.swiper && this.swiper.destroy) {
            this.swiper.destroy(true, true);
        }
        this.swiper = null;
        if (this.slideObserver) {
            try {
                this.slideObserver.disconnect();
            } catch (e) {
            }
            this.slideObserver = null;
        }
    },
    watch: {
        // Re-init when core props change. Keep minimal to avoid excessive re-inits
        slidesPerView: 'initSwiper',
        slidesPerGroup: 'initSwiper',
        spaceBetween: 'initSwiper',
        loop: 'initSwiper',
        navigation: 'initSwiper',
        pagination: 'initSwiper',
        autoplay: 'initSwiper',
        breakpoints: {
            handler: 'initSwiper',
            deep: true
        },
        effect: 'initSwiper',
        speed: 'initSwiper',
        allowTouchMove: 'initSwiper',
        thumbs: {
            handler: 'initSwiper',
            deep: true
        }
    }
};
</script>

<style scoped>
/* The project already imports Swiper CSS globally. This component only provides structure. */
</style>
