<template>
    <view class="wrapper" v-if="webviewUrl || value">
        <view class="close" @click="close">
			<uni-icons v-if="!$slots.close" class="close-icon" type="close" size="40" style="color: #999999;"></uni-icons>	
        </view>
        <view class="wg-h5-preview-file-container" :style="containerStyle">
            <view class="webview">
                <!-- #ifdef H5 -->
                <iframe
                    class="wg-h5-preview-file-iframe"
                    :webview-styles="webviewStyles"
                    :src="iframeUrl" />
                <!-- #endif -->
            </view>
        </view>
    </view>
</template>

<script>
const urlMap = {
    word: "/static/hybrid/word.html?file=",
    pdf: "/static/hybrid/pdf/web/viewer.html?file=",
    excel: "/static/hybrid/excel.html?file=",
    txt: "/static/hybrid/txt.html?file=",
    pptx: "/static/hybrid/pptx.html?file=",
};
export default {
    name: "WgH5PreviewFile",
    props: {
        value: {
            type: String,
            required: true,
        },
        type: {
            type: String,
            required: true,
            validator(v) {
                return ["excel", "pdf", "word", "txt", "pptx"].includes(v);
            },
        },
    },
    computed: {
        iframeUrl() {
            return (
                this.webviewUrl || this.buildPreviewUrl(this.type, this.value)
            );
        },
        containerStyle() {
            // 动态设置容器的实际可视高度，避免 100vh 在移动端地址栏收起/展开导致的遮挡问题
            const style = {
                height:
                    this.containerHeight > 0
                        ? `${this.containerHeight}px`
                        : "100vh",
            };
            // 当不支持 CSS env/constant(safe-area-inset-bottom) 时，用内联 padding 兜底
            if (!this.cssSafeAreaSupported && this.safeBottom > 0) {
                style.paddingBottom = `${this.safeBottom}px`;
            }
            return style;
        },
    },
    data() {
        return {
            safeBottom: 0,
            webviewUrl: null,
            webviewStyles: {
                zIndex: "9999",
            },
            // 实际可视区域高度（px）
            containerHeight: 0,
            // 是否支持 CSS 安全区变量
            cssSafeAreaSupported: false,
        };
    },
    methods: {
        preview({ url, type }) {
            this.webviewUrl = this.buildPreviewUrl(type, url);
        },
        buildPreviewUrl(fileType, url = "") {
            const relativePath = urlMap[fileType] || urlMap.word;
            const sanitizedPath = relativePath.replace(/^\//, "");
            const basePath = this.getPreviewBasePath();
            return `${basePath}${sanitizedPath}${encodeURIComponent(
                url || this.value
            )}&safeBottom=${this.safeBottom}`;
        },
        getPreviewBasePath() {
            if (typeof window !== "undefined") {
                const configBase =
                    (window.__uniConfig &&
                        window.__uniConfig.router &&
                        window.__uniConfig.router.base) ||
                    (window.__uniConfig && window.__uniConfig.publicPath);
                if (configBase && configBase !== "./" && configBase !== ".") {
                    return configBase.endsWith("/")
                        ? configBase
                        : `${configBase}/`;
                }
                const pathname = window.location.pathname || "/";
                if (pathname === "/") {
                    return "/";
                }
                if (pathname.endsWith("/")) {
                    return pathname;
                }
                const lastSlashIndex = pathname.lastIndexOf("/");
                const lastSegment = pathname.slice(lastSlashIndex + 1);
                const looksLikeFile = lastSegment.includes(".");
                if (looksLikeFile) {
                    return pathname.replace(/\/[^/]*$/, "/");
                }
                return `${pathname}/`;
            }

            return "/";
        },
        updateViewportHeight() {
            if (typeof window === "undefined") {
                this.containerHeight = 0;
                return;
            }
            let height = 0;
            if (
                window.visualViewport &&
                typeof window.visualViewport.height === "number"
            ) {
                height = Math.round(window.visualViewport.height);
            } else {
                height = window.innerHeight;
            }
            // 计算安全区底部像素，用于 iframe 参数传递与不支持 env 的兜底
            this.safeBottom = this.getSafeAreaInsetBottomPx();
            this.containerHeight = height;
        },
        addViewportListeners() {
            if (typeof window === "undefined") return;
            // 绑定一次，便于移除
            this._boundUpdateViewportHeight =
                this._boundUpdateViewportHeight ||
                this.updateViewportHeight.bind(this);
            window.addEventListener("resize", this._boundUpdateViewportHeight, {
                passive: true,
            });
            window.addEventListener(
                "orientationchange",
                this._boundUpdateViewportHeight,
                { passive: true }
            );
            if (window.visualViewport) {
                window.visualViewport.addEventListener(
                    "resize",
                    this._boundUpdateViewportHeight,
                    { passive: true }
                );
            }
        },
        removeViewportListeners() {
            if (
                typeof window === "undefined" ||
                !this._boundUpdateViewportHeight
            )
                return;
            window.removeEventListener(
                "resize",
                this._boundUpdateViewportHeight
            );
            window.removeEventListener(
                "orientationchange",
                this._boundUpdateViewportHeight
            );
            if (window.visualViewport) {
                window.visualViewport.removeEventListener(
                    "resize",
                    this._boundUpdateViewportHeight
                );
            }
        },
        checkCssSafeAreaSupport() {
            if (typeof window === "undefined" || !window.CSS || !CSS.supports)
                return false;
            // 支持 env 或老版本 constant
            return (
                CSS.supports("padding-bottom: env(safe-area-inset-bottom)") ||
                CSS.supports("padding-bottom: constant(safe-area-inset-bottom)")
            );
        },
        getSafeAreaInsetBottomPx() {
            if (typeof window === "undefined" || !document || !document.body)
                return 0;
            let value = 0;
            try {
                const probe = document.createElement("div");
                probe.style.position = "absolute";
                probe.style.visibility = "hidden";
                probe.style.pointerEvents = "none";
                probe.style.paddingBottom = "env(safe-area-inset-bottom)";
                document.body.appendChild(probe);
                const v1 = parseFloat(
                    window.getComputedStyle(probe).paddingBottom || "0"
                );
                document.body.removeChild(probe);
                if (v1 > 0) return Math.round(v1);
                // 尝试旧语法 constant()
                const probe2 = document.createElement("div");
                probe2.style.position = "absolute";
                probe2.style.visibility = "hidden";
                probe2.style.pointerEvents = "none";
                probe2.style.paddingBottom = "constant(safe-area-inset-bottom)";
                document.body.appendChild(probe2);
                const v2 = parseFloat(
                    window.getComputedStyle(probe2).paddingBottom || "0"
                );
                document.body.removeChild(probe2);
                value = v2 > 0 ? Math.round(v2) : 0;
            } catch (e) {
                value = 0;
            }
            return value;
        },
        close() {
            this.webviewUrl = null;
			this.$emit('CloseDialog');
            // uni.navigateBack();
        },
    },
    mounted() {
        this.safeBottom = 0;
        this.cssSafeAreaSupported = this.checkCssSafeAreaSupport();
        this.updateViewportHeight();
        this.addViewportListeners();
    },
    beforeDestroy() {
        this.removeViewportListeners();
    },
};
</script>

<style lang="scss">
.wrapper {
    position: relative;
    .close {
        position: fixed;
        top: 44px;
        right: 20px;
        z-index: 9999;
    }
    .close-icon {
        width: 46px;
        height: 46px;
    }
}
iframe {
    z-index: 9999 !important;
    top: 0 !important;
}
.wg-h5-preview-file-iframe {
    width: 100vw;
    height: 100% !important;
}
.wg-h5-preview-file-container {
    position: fixed;
    left: 0px;
    bottom: 0;
    overflow: hidden;
    z-index: 998;
    width: 100vw;
    height: 100%;
    // iOS 刘海屏底部安全区
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
    background-color: #fff;
}

.webview {
    height: 100% !important;
}
</style>
