// ==UserScript==
// @name         仿酷安回到顶部和底部
// @namespace    optimized-script
// @version      1.0
// @description  支持智能显示隐藏、平滑滚动
// @author       DeepSeek
// @match        *
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function() {
    "use strict";

    const CONFIG = {
        APPEAR_DELAY: 3000,
        MIN_SWIPE_DISTANCE: 40,
        BUTTON_SIZE: "clamp(40px, 8vw, 60px)",
        BUTTON_BOTTOM: "5vh",
        BUTTON_RIGHT: "45vw",
        BUTTON_COLOR: "rgba(250,250,250,0.9)",
        SHADOW: "0px 1px 1px rgba(0,0,0,0.4)",
        ANIMATION_DURATION: 360,
        SCROLL_THRESHOLD: 300,
        FONT_SIZE: "4vw",
        LINE_HEIGHT: "clamp(40px, 8vw, 60px)",
        Z_INDEX: 99999999999999999
    };

    class ScrollButton {
        constructor() {
            this.isActive = false;
            this.lastScroll = 0;
            this.touchStartY = 0;
            this.hideTimer = null;
            this.button = null;
            this.init();
        }

        init() {
            this.createStyles();
            this.createButton();
            this.setupEventListeners();
            this.setupIntersectionObserver();
            this.setupMutationObserver();
        }

        createStyles() {
            const style = document.createElement("style");
            style.textContent = `
                .scroll-button {
                    position: fixed;
                    right: ${CONFIG.BUTTON_RIGHT};
                    bottom: ${CONFIG.BUTTON_BOTTOM};
                    width: ${CONFIG.BUTTON_SIZE};
                    height: ${CONFIG.BUTTON_SIZE};
                    line-height: ${CONFIG.LINE_HEIGHT};
                    text-align: center;
                    background: ${CONFIG.BUTTON_COLOR};
                    border-radius: 100%;
                    box-shadow: ${CONFIG.SHADOW};
                    cursor: pointer;
                    opacity: 0;
                    transform: translateY(20px);
                    transition:
                        opacity 0.3s ease,
                        transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
                    pointer-events: none;
                    z-index: ${CONFIG.Z_INDEX};
                    font-size: ${CONFIG.FONT_SIZE};
                    color: #000;
                    display: none;
                    user-select: none;
                    -webkit-tap-highlight-color: transparent;
                }
                .scroll-button.visible {
                    opacity: 1;
                    transform: translateY(0);
                    pointer-events: auto;
                    display: block;
                }
                .scroll-button.pressed {
                    transform: scale(0.92) translateY(0);
                    background: rgba(240,240,240,0.96);
                }
            `;
            document.head.appendChild(style);
        }

        createButton() {
            this.button = document.createElement("div");
            this.button.className = "scroll-button";
            this.button.setAttribute("aria-label", "滚动操作按钮");
            this.button.setAttribute("role", "button");
            document.body.appendChild(this.button);
        }

        setupEventListeners() {
            const passiveOptions = { passive: true };
            const activeOptions = { capture: true };

            document.addEventListener("touchstart", this.handleTouchStart.bind(this), passiveOptions);
            document.addEventListener("touchmove", this.throttle(this.handleTouchMove.bind(this), 50), passiveOptions);
            document.addEventListener("touchend", this.handleTouchEnd.bind(this), passiveOptions);

            document.addEventListener("mousedown", this.handleMouseStart.bind(this), activeOptions);
            document.addEventListener("mousemove", this.throttle(this.handleMouseMove.bind(this), 50), activeOptions);
            document.addEventListener("mouseup", this.handleMouseEnd.bind(this), activeOptions);

            this.button.addEventListener("click", this.handleClick.bind(this));
            this.button.addEventListener("transitionend", () => {
                this.button.classList.remove("pressed");
            });
        }

        setupIntersectionObserver() {
                let ticking = false;
                let lastScroll = window.scrollY;

                const handleScroll = () => {
                        const currentScroll = window.scrollY;
                        const scrollDirection = currentScroll > lastScroll ? "down" : "up";
                        const scrollDelta = Math.abs(currentScroll - lastScroll);

                        if (scrollDelta > CONFIG.SCROLL_THRESHOLD) {
                                this.showButton(scrollDirection);
                        }

                        lastScroll = currentScroll;
                        ticking = false;
                };

                window.addEventListener("scroll", () => {
                        if (!ticking) {
                                requestAnimationFrame(handleScroll);
                                ticking = true;
                        }
                }, { passive: true });
        }

        setupMutationObserver() {
            const observer = new MutationObserver(() => {
                if (!document.querySelector(".scroll-button")) {
                    this.createButton();
                    this.setupEventListeners();
                }
            });

            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        throttle(fn, delay) {
            let lastCall = 0;
            return (...args) => {
                const now = Date.now();
                if (now - lastCall >= delay) {
                    fn.apply(this, args);
                    lastCall = now;
                }
            };
        }

        handleTouchStart(e) {
            this.touchStartY = e.touches[0].clientY;
            this.isActive = true;
        }

        handleTouchMove(e) {
            if (!this.isActive) return;
            this.updateButtonState(e.touches[0].clientY);
        }

        handleTouchEnd() {
            this.isActive = false;
            this.scheduleHide();
        }

        handleMouseStart(e) {
            this.touchStartY = e.clientY;
            this.isActive = true;
        }

        handleMouseMove(e) {
            if (!this.isActive) return;
            this.updateButtonState(e.clientY);
        }

        handleMouseEnd() {
            this.isActive = false;
            this.scheduleHide();
        }

        updateButtonState(currentY) {
            const deltaY = currentY - this.touchStartY;
            if (Math.abs(deltaY) < CONFIG.MIN_SWIPE_DISTANCE) return;

            const direction = deltaY > 0 ? "up" : "down";
            this.showButton(direction);
        }

        showButton(direction) {
            clearTimeout(this.hideTimer);
            this.button.textContent = direction === "up" ? "↑" : "↓";

            requestAnimationFrame(() => {
                this.button.classList.add("visible");
                this.button.style.transitionDuration = `${CONFIG.ANIMATION_DURATION}ms`;
            });
        }

        scheduleHide() {
            clearTimeout(this.hideTimer);
            this.hideTimer = setTimeout(() => {
                this.button.classList.remove("visible");
            }, CONFIG.APPEAR_DELAY);
        }

        handleClick() {
            const targetPosition = this.button.textContent === "↑"
                ? 0
                : document.documentElement.scrollHeight;

            window.scrollTo({
                top: targetPosition,
                behavior: "smooth"
            });

            this.button.classList.add("pressed");
            this.scheduleHide();
        }
    }

    if (!document.querySelector(".scroll-button")) {
        new ScrollButton();
    }
})();