<template>
    <view v-if="visible && current" class="global-popup-mask" @tap="handleMaskTap">
        <view class="global-popup-wrap" @tap.stop>
            <view v-if="showAutoCloseProgress" class="global-popup__progress">
                <view class="global-popup__progress-inner" :style="progressStyle"></view>
            </view>
            <view class="global-popup">
                <!-- 关闭按钮 -->
                <view v-if="current.is_closable !== 0" class="global-popup__close" @tap="handleClose">
                    <text>×</text>
                </view>

                <!-- 主体内容 -->
                <view class="global-popup__body" @tap="handleClick">
                    <image v-if="current.image" :src="current.image" class="global-popup__image" mode="widthFix" />

                    <view v-if="current.title || current.content" class="global-popup__text">
                        <text v-if="current.title" class="global-popup__title">{{ current.title }}</text>
                        <rich-text v-if="current.content" class="global-popup__content"
                            :nodes="current.content"></rich-text>
                    </view>

                    <view v-if="current.link_type !== 0" class="global-popup__btn">
                        <text>查看详情</text>
                    </view>
                </view>
            </view>
        </view>
    </view>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, computed } from 'vue'
import { getPopupList, reportPopupAction, type PagePopupItem } from '@/api/popup'
import { getOrCreateDeviceId, getPlatform } from '@/utils/device'
import { useAppStore } from '@/stores/app'

const props = defineProps<{
    pagePath?: string
    triggerTick?: number
}>()

const appStore = useAppStore()

function getPagePathFromPages(): string {
    const pages = getCurrentPages()
    if (!pages.length) return ''
    const page = pages[pages.length - 1] as any
    let route = page.route || ''
    // #ifdef H5
    route = route.replace(/^\//, '')
    if (route.startsWith('mobile/')) {
        route = route.replace('mobile/', '')
    }
    // #endif
    return '/' + route
}

const effectivePath = computed(() => props.pagePath || appStore.popupPagePath || getPagePathFromPages())
const effectiveTick = computed(() => props.triggerTick ?? appStore.popupTick)

const visible = ref(false)
const current = ref<PagePopupItem | null>(null)
const showAutoCloseProgress = ref(false)
const progressPct = ref(100)
let autoCloseInterval: ReturnType<typeof setInterval> | null = null

function progressColor(pct: number): string {
    if (pct > 60) return '#4cd964'
    if (pct > 30) return '#ff9500'
    return '#ff3b30'
}

const progressStyle = computed(() => ({
    width: progressPct.value + '%',
    backgroundColor: progressColor(progressPct.value),
    transitionDuration: '200ms',
}))
const platform = getPlatform()
const deviceId = getOrCreateDeviceId()
let autoCloseTimer: ReturnType<typeof setTimeout> | null = null

// 频率控制存储 key
const FREQ_KEY_PREFIX = 'popup_shown_'

/** 同一 App 启动周期内已展示的弹窗 ID 集合（每会话一次） */
const sessionShown = new Set<number>()

/**
 * 检查频率是否允许展示
 * @returns true 表示可以展示
 */
function checkFrequency(item: PagePopupItem): boolean {
    const key = FREQ_KEY_PREFIX + item.id
    const now = Date.now()

    switch (item.frequency) {
        case 1: // 每次
            return true
        case 2: // 每会话一次
            return !sessionShown.has(item.id)
        case 3: {
            // 每天一次
            try {
                const last = uni.getStorageSync(key)
                if (!last) return true
                return now - Number(last) >= 24 * 60 * 60 * 1000
            } catch (e) {
                return true
            }
        }
        case 4: {
            // 仅一次
            try {
                return !uni.getStorageSync(key)
            } catch (e) {
                return true
            }
        }
        default:
            return true
    }
}

/** 标记已展示 */
function markShown(item: PagePopupItem) {
    sessionShown.add(item.id)
    if (item.frequency === 3 || item.frequency === 4) {
        try {
            uni.setStorageSync(FREQ_KEY_PREFIX + item.id, Date.now())
        } catch (e) {
            /* ignore */
        }
    }
}

/** 拉取弹窗并展示首个匹配项 */
async function checkAndShow() {
    if (!effectivePath.value) return
    try {
        const res: any = await getPopupList({
            page_path: effectivePath.value,
            platform,
        })
        const lists: PagePopupItem[] = res?.lists || []
        if (!lists.length) return

        // 取第一个频率允许展示的弹窗
        const target = lists.find((it) => checkFrequency(it))
        if (!target) return

        const showFn = () => {
            current.value = target
            visible.value = true
            markShown(target)
            startAutoClose(target)
            // 上报展示
            reportPopupAction({
                popup_id: target.id,
                action: 1,
                page_path: effectivePath.value,
                device_id: deviceId,
                platform,
            }).catch(() => { /* ignore */ })
        }

        if (target.delay_seconds && target.delay_seconds > 0) {
            setTimeout(showFn, target.delay_seconds * 1000)
        } else {
            showFn()
        }
    } catch (e) {
        console.warn('[GlobalPopup] 拉取弹窗失败:', e)
    }
}

function handleClick() {
    if (!current.value) return
    const item = current.value
    // 上报点击
    reportPopupAction({
        popup_id: item.id,
        action: 2,
        page_path: effectivePath.value,
        device_id: deviceId,
        platform,
    }).catch(() => { /* ignore */ })

    // 跳转
    if (item.link_type === 1 && item.link_url) {
        // 站内
        uni.navigateTo({
            url: item.link_url,
            fail: () => {
                uni.switchTab({
                    url: item.link_url,
                    fail: () => uni.reLaunch({ url: item.link_url }),
                })
            },
        })
        closeWithoutReport()
    } else if (item.link_type === 2 && item.link_url) {
        // 外部 H5
        // #ifdef APP-PLUS
        plus.runtime.openURL(item.link_url)
        // #endif
        // #ifdef H5
        window.open(item.link_url, '_blank')
        // #endif
        // #ifdef MP
        uni.setClipboardData({ data: item.link_url })
        uni.showToast({ title: '链接已复制', icon: 'none' })
        // #endif
        closeWithoutReport()
    } else if (item.link_type === 3 && item.link_url) {
        // 拨打电话
        uni.makePhoneCall({ phoneNumber: item.link_url })
        closeWithoutReport()
    }
}

function handleClose() {
    if (!current.value) return
    clearAutoClose()
    reportPopupAction({
        popup_id: current.value.id,
        action: 3,
        page_path: effectivePath.value,
        device_id: deviceId,
        platform,
    }).catch(() => { /* ignore */ })
    closeWithoutReport()
}

function handleMaskTap() {
    if (current.value && current.value.is_closable === 0) return
    handleClose()
}

function closeWithoutReport() {
    clearAutoClose()
    visible.value = false
    current.value = null
}

function closeWithReport() {
    if (!current.value) return
    reportPopupAction({
        popup_id: current.value.id,
        action: 3,
        page_path: effectivePath.value,
        device_id: deviceId,
        platform,
    }).catch(() => { /* ignore */ })
    closeWithoutReport()
}

function startAutoClose(item: PagePopupItem) {
    clearAutoClose()
    const seconds = Number(item.auto_close_seconds || 0)
    if (seconds <= 0) return
    const duration = seconds * 1000
    const step = 200
    const decrement = (100 * step) / duration
    progressPct.value = 100
    showAutoCloseProgress.value = true
    autoCloseInterval = setInterval(() => {
        progressPct.value = Math.max(0, progressPct.value - decrement)
    }, step)
    autoCloseTimer = setTimeout(() => {
        closeWithReport()
    }, duration)
}

function clearAutoClose() {
    if (autoCloseTimer) {
        clearTimeout(autoCloseTimer)
        autoCloseTimer = null
    }
    if (autoCloseInterval) {
        clearInterval(autoCloseInterval)
        autoCloseInterval = null
    }
    showAutoCloseProgress.value = false
    progressPct.value = 100
}

onMounted(() => {
    checkAndShow()
})

watch(effectiveTick, () => {
    if (!visible.value) checkAndShow()
})

watch(effectivePath, () => {
    if (!visible.value) checkAndShow()
})
</script>

<style lang="scss" scoped>
.global-popup-mask {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9998;
}

.global-popup-wrap {
    position: relative;
    width: 580rpx;
}

.global-popup {
    position: relative;
    width: 100%;
    background: #fff;
    border-radius: 24rpx;
    overflow: hidden;
    animation: globalPopupIn 0.25s ease-out;
}

@keyframes globalPopupIn {
    0% {
        transform: scale(0.85);
        opacity: 0;
    }

    100% {
        transform: scale(1);
        opacity: 1;
    }
}

.global-popup__close {
    position: absolute;
    top: 20rpx;
    right: 20rpx;
    width: 64rpx;
    height: 64rpx;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.35);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 5;

    text {
        font-size: 48rpx;
        color: #fff;
        line-height: 1;
    }
}

.global-popup__progress {
    width: 100%;
    height: 6rpx;
    margin-bottom: 16rpx;
    border-radius: 999rpx;
    background: rgba(255, 255, 255, 0.3);
    overflow: hidden;
}

.global-popup__progress-inner {
    height: 100%;
    border-radius: 999rpx;
    transition-property: width, background-color;
    transition-timing-function: linear;
}

.global-popup__body {
    width: 100%;
}

.global-popup__image {
    width: 100%;
    display: block;
}

.global-popup__text {
    padding: 32rpx 40rpx;
    display: flex;
    flex-direction: column;
}

.global-popup__title {
    font-size: 32rpx;
    font-weight: 600;
    color: #222;
    margin-bottom: 16rpx;
}

.global-popup__content {
    font-size: 26rpx;
    color: #666;
    line-height: 1.6;
}

.global-popup__btn {
    margin: 32rpx 40rpx 32rpx;
    background: #0b55eb;
    border-radius: 40rpx;
    padding: 24rpx 0;
    text-align: center;

    text {
        font-size: 28rpx;
        color: #fff;
        font-weight: 500;
    }
}
</style>
