(() => {
    const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

    const selectors = [
        ".section__head",
        ".info-card",
        ".feature-card",
        ".object-card",
        ".service-card",
        ".gallery__item",
        ".review-card",
        ".stats article",
        ".booking__form",
        ".contacts-card",
        ".hours-card",
    ];

    const elements = Array.from(document.querySelectorAll(selectors.join(",")));
    if (!elements.length) return;

    const siblingCounters = new WeakMap();

    elements.forEach((element) => {
        element.classList.add("scroll-reveal");
        const parent = element.parentElement;
        let offsetIndex = 0;

        if (parent) {
            offsetIndex = siblingCounters.get(parent) ?? 0;
            siblingCounters.set(parent, offsetIndex + 1);
        }

        element.style.setProperty("--reveal-delay", `${(offsetIndex % 4) * 80}ms`);
    });

    if (reduceMotion || !("IntersectionObserver" in window)) {
        elements.forEach((element) => element.classList.add("is-visible"));
        return;
    }

    const observer = new IntersectionObserver(
        (entries, currentObserver) => {
            entries.forEach((entry) => {
                if (!entry.isIntersecting) return;
                entry.target.classList.add("is-visible");
                currentObserver.unobserve(entry.target);
            });
        },
        {
            threshold: 0.18,
            rootMargin: "0px 0px -12% 0px"
        }
    );

    elements.forEach((element) => observer.observe(element));
})();

(() => {
    const counters = Array.from(document.querySelectorAll(".js-counter"));
    if (!counters.length) return;

    const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

    const formatCounter = (counter, value) => {
        const suffix = counter.dataset.suffix || "";
        counter.textContent = `${value}${suffix}`;
    };

    const setFinalValue = (counter) => {
        const target = Number(counter.dataset.target || 0);
        formatCounter(counter, Number.isFinite(target) ? target : 0);
    };

    const animateCounter = (counter) => {
        const target = Number(counter.dataset.target || 0);
        const duration = Number(counter.dataset.duration || 1300);

        if (!Number.isFinite(target) || target <= 0) {
            setFinalValue(counter);
            return;
        }

        let startTime = null;

        const tick = (timestamp) => {
            if (startTime === null) startTime = timestamp;

            const progress = Math.min((timestamp - startTime) / duration, 1);
            const currentValue = Math.floor(progress * target);
            formatCounter(counter, currentValue);

            if (progress < 1) {
                window.requestAnimationFrame(tick);
                return;
            }

            setFinalValue(counter);
        };

        window.requestAnimationFrame(tick);
    };

    if (reduceMotion || !("IntersectionObserver" in window)) {
        counters.forEach(setFinalValue);
        return;
    }

    const observer = new IntersectionObserver(
        (entries, currentObserver) => {
            entries.forEach((entry) => {
                if (!entry.isIntersecting) return;
                animateCounter(entry.target);
                currentObserver.unobserve(entry.target);
            });
        },
        { threshold: 0.45 }
    );

    counters.forEach((counter) => {
        formatCounter(counter, 0);
        observer.observe(counter);
    });
})();

(() => {
    const slider = document.querySelector("[data-reviews-slider]");
    if (!slider) return;

    const viewport = slider.querySelector("[data-reviews-viewport]");
    const track = slider.querySelector("[data-reviews-track]");
    const prevButton = slider.querySelector("[data-reviews-prev]");
    const nextButton = slider.querySelector("[data-reviews-next]");
    const dotsContainer = document.querySelector("[data-reviews-dots]");
    const cards = Array.from(track?.querySelectorAll(".review-card") ?? []);

    if (!viewport || !track || !prevButton || !nextButton || !dotsContainer || cards.length < 2) return;

    let currentIndex = 0;
    let touchStartX = 0;

    const readVisibleSlides = () => {
        const visibleValue = Number.parseInt(getComputedStyle(slider).getPropertyValue("--reviews-visible"), 10);
        return Number.isFinite(visibleValue) && visibleValue > 0 ? visibleValue : 1;
    };

    const readTrackGap = () => {
        const styles = getComputedStyle(track);
        const gapValue = styles.gap || styles.columnGap || "0";
        const parsedGap = Number.parseFloat(gapValue);
        return Number.isFinite(parsedGap) ? parsedGap : 0;
    };

    const maxIndex = () => Math.max(0, cards.length - readVisibleSlides());

    const renderDots = () => {
        const total = maxIndex() + 1;
        dotsContainer.innerHTML = "";

        for (let index = 0; index < total; index += 1) {
            const dot = document.createElement("button");
            dot.type = "button";
            dot.className = "reviews__dot";
            dot.setAttribute("aria-label", `Показать отзыв ${index + 1}`);
            dot.addEventListener("click", () => {
                currentIndex = index;
                update();
            });
            dotsContainer.appendChild(dot);
        }
    };

    const update = () => {
        const max = maxIndex();
        currentIndex = Math.min(Math.max(currentIndex, 0), max);

        const cardWidth = cards[0].getBoundingClientRect().width;
        const offset = (cardWidth + readTrackGap()) * currentIndex;
        track.style.transform = `translateX(${-offset}px)`;

        prevButton.disabled = currentIndex === 0;
        nextButton.disabled = currentIndex === max;

        const dots = Array.from(dotsContainer.querySelectorAll(".reviews__dot"));
        dots.forEach((dot, index) => {
            dot.classList.toggle("is-active", index === currentIndex);
            dot.setAttribute("aria-current", index === currentIndex ? "true" : "false");
        });
    };

    prevButton.addEventListener("click", () => {
        currentIndex -= 1;
        update();
    });

    nextButton.addEventListener("click", () => {
        currentIndex += 1;
        update();
    });

    viewport.addEventListener("touchstart", (event) => {
        touchStartX = event.changedTouches[0].clientX;
    }, { passive: true });

    viewport.addEventListener("touchend", (event) => {
        const deltaX = event.changedTouches[0].clientX - touchStartX;
        const threshold = 48;

        if (deltaX > threshold) {
            currentIndex -= 1;
            update();
            return;
        }

        if (deltaX < -threshold) {
            currentIndex += 1;
            update();
        }
    }, { passive: true });

    const handleResize = () => {
        renderDots();
        update();
    };

    let resizeRaf = null;
    window.addEventListener("resize", () => {
        if (resizeRaf) return;
        resizeRaf = window.requestAnimationFrame(() => {
            resizeRaf = null;
            handleResize();
        });
    });

    renderDots();
    update();
})();

(() => {
    const bookingForm = document.getElementById("booking-form");
    const successModal = document.getElementById("booking-success-modal");

    if (!bookingForm || !successModal) return;

    const closeTriggers = Array.from(successModal.querySelectorAll("[data-modal-close]"));

    const openModal = () => {
        successModal.classList.add("is-open");
        successModal.setAttribute("aria-hidden", "false");
    };

    const closeModal = () => {
        successModal.classList.remove("is-open");
        successModal.setAttribute("aria-hidden", "true");
    };

    const triggerAnalytics = () => {
        const eventName = "заявка";

        const metrikaIdRaw = bookingForm.dataset.metrikaId || document.body.dataset.metrikaId || window.YANDEX_METRIKA_ID;
        const metrikaId = Number(metrikaIdRaw);

        if (typeof window.ym === "function" && Number.isFinite(metrikaId) && metrikaId > 0) {
            window.ym(metrikaId, "reachGoal", eventName);
        }

        const legacyCounterKey = Object.keys(window).find((key) => {
            return key.startsWith("yaCounter") && typeof window[key]?.reachGoal === "function";
        });

        if (legacyCounterKey) {
            window[legacyCounterKey].reachGoal(eventName);
        }

        if (typeof window.gtag === "function") {
            window.gtag("event", eventName, {
                event_category: "lead",
                event_label: "booking_form"
            });
        }

        if (Array.isArray(window.dataLayer)) {
            window.dataLayer.push({
                event: eventName,
                event_category: "lead",
                event_label: "booking_form"
            });
        }
    };

    const triggerAutoReply = async (email) => {
        if (!email) return;

        const autoReplyEndpoint = bookingForm.dataset.autoreplyEndpoint || window.BOOKING_AUTOREPLY_ENDPOINT;
        if (!autoReplyEndpoint) return;

        try {
            await fetch(autoReplyEndpoint, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({
                    email,
                    source: "booking-form"
                })
            });
        } catch (error) {
            // Auto-reply is optional and should not block form success.
            console.error("Auto-reply request failed", error);
        }
    };

    bookingForm.addEventListener("submit", async (event) => {
        event.preventDefault();

        if (!bookingForm.checkValidity()) {
            bookingForm.reportValidity();
            return;
        }

        const formData = new FormData(bookingForm);
        const email = String(formData.get("email") || "").trim();

        triggerAnalytics();
        await triggerAutoReply(email);

        bookingForm.reset();
        openModal();
    });

    closeTriggers.forEach((trigger) => {
        trigger.addEventListener("click", closeModal);
    });

    document.addEventListener("keydown", (event) => {
        if (event.key === "Escape" && successModal.classList.contains("is-open")) {
            closeModal();
        }
    });
})();
