<template>
    <u-popup v-model="showPopup" mode="bottom" safe-area-inset-bottom border-radius="24" closeable @close="handleClose">
        <view class="match-live-popup">
            <view class="match-live-popup__header">
                <text class="match-live-popup__title">{{ lineTitle }}</text>
                <text class="match-live-popup__desc">{{ lineMetaText }}</text>
            </view>

            <view class="match-live-popup__section">
                <text class="match-live-popup__section-title">直播线路</text>
                <view v-if="streamOptions.length" class="match-live-popup__options">
                    <view
                        v-for="item in streamOptions"
                        :key="item.key"
                        class="match-live-popup__option"
                        :class="{ 'match-live-popup__option--active': item.key === selectedStreamKey }"
                        @tap="selectOption(item)"
                    >
                        <view class="match-live-popup__option-main">
                            <text class="match-live-popup__option-title">{{ item.label }}</text>
                            <text class="match-live-popup__option-url">{{ item.url }}</text>
                        </view>
                        <text v-if="item.key === selectedStreamKey" class="match-live-popup__option-tag">当前</text>
                    </view>
                </view>
                <view v-else class="match-live-popup__empty">
                    <text>暂无可用直播线路</text>
                </view>
            </view>

            <view class="match-live-popup__actions">
                <u-button type="primary" shape="circle" @click="openSelected">打开当前线路</u-button>
                <u-button shape="circle" plain @click="openSource">打开源站</u-button>
            </view>
        </view>
    </u-popup>
</template>

<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
import type { MatchLiveLineItem, MatchLiveStreamOption } from '@/api/match'

type PopupStreamOption = MatchLiveStreamOption & {
    key: string
    label: string
    url: string
}

const props = defineProps<{
    show: boolean
    line: MatchLiveLineItem | null
}>()

const emit = defineEmits(['update:show', 'close'])

const showPopup = computed({
    get: () => props.show,
    set: (value: boolean) => emit('update:show', value),
})

const selectedStreamKey = ref('')

const normalizeText = (value: unknown) => String(value || '').trim()

const normalizeUrl = (value: unknown) => {
    const text = normalizeText(value)
    return text
}

const getFetchStatusText = (value: unknown) => {
    const text = normalizeText(value)
    if (!text) return ''
    const normalized = text.toLowerCase()
    if (normalized === 'pending' || normalized === '0') return '待抓取'
    if (normalized === 'success' || normalized === '1') return '已抓取'
    if (normalized === 'failed' || normalized === 'error' || normalized === '2') return '抓取失败'
    return text
}

const formatMetaTime = (value: unknown) => {
    const text = normalizeText(value)
    if (!text) return ''
    const hhmmss = text.match(/(\d{2}:\d{2}:\d{2})$/)
    if (hhmmss) return hhmmss[1]
    const hhmm = text.match(/(\d{2}:\d{2})$/)
    if (hhmm) return hhmm[1]
    if (/^\d{10,13}$/.test(text)) {
        const raw = text.length === 13 ? Number(text) : Number(text) * 1000
        const date = new Date(raw)
        if (!Number.isNaN(date.getTime())) {
            const hour = String(date.getHours()).padStart(2, '0')
            const minute = String(date.getMinutes()).padStart(2, '0')
            return `${hour}:${minute}`
        }
    }
    return text
}

const lineTitle = computed(() => {
    const line = props.line || {}
    return (
        normalizeText(line.title) ||
        normalizeText(line.name) ||
        normalizeText(line.label) ||
        normalizeText(line.live_tag) ||
        normalizeText(line.source_name) ||
        '直播线路'
    )
})

const lineMetaText = computed(() => {
    const line = props.line || {}
    const parts = [
        getFetchStatusText(line.fetch_status),
        formatMetaTime(line.last_fetch_at || line.update_time),
    ].filter(Boolean)
    return parts.length ? parts.join(' · ') : '请选择可用直播线路后打开'
})

const sourceUrl = computed(() => normalizeUrl(props.line?.source_url))

const buildStreamOption = (option: MatchLiveStreamOption | undefined, index: number) => {
    if (!option) return null
    const url = (
        [
            option.default_play_url,
            option.play_url_m3u8,
            option.play_url_hd_m3u8,
            option.play_url_flv,
            option.play_url_hd_flv,
            option.play_url,
            option.url,
            option.live_url,
        ].map((item) => normalizeUrl(item)).find(Boolean) || ''
    )
    if (!url) return null
    return {
        ...option,
        key: `${index}-${url}`,
        label:
            normalizeText(option.title) ||
            normalizeText(option.name) ||
            normalizeText(option.label) ||
            normalizeText(option.source_name) ||
            normalizeText(option.quality) ||
            `线路${index + 1}`,
        url,
    } satisfies PopupStreamOption
}

const streamOptions = computed(() => {
    const line = props.line || {}
    const options: PopupStreamOption[] = []
    const seen = new Set<string>()
    const fallbackFields: Array<{ field: keyof MatchLiveLineItem; label: string }> = [
        { field: 'default_play_url', label: '默认线路' },
        { field: 'play_url_m3u8', label: 'M3U8 线路' },
        { field: 'play_url_hd_m3u8', label: '高清 M3U8' },
        { field: 'play_url_flv', label: 'FLV 线路' },
        { field: 'play_url_hd_flv', label: '高清 FLV' },
        { field: 'play_url', label: '备用线路' },
        { field: 'live_url', label: '直播地址' },
    ]

    const pushOption = (option: MatchLiveStreamOption | undefined, index: number) => {
        const built = buildStreamOption(option, index)
        if (!built || seen.has(built.url)) return
        seen.add(built.url)
        options.push(built)
    }

    if (Array.isArray(line.stream_options)) {
        line.stream_options.forEach((item, index) => pushOption(item, index))
    }

    fallbackFields.forEach(({ field, label }) => {
        const value = normalizeUrl(line[field])
        if (!value || seen.has(value)) return
        pushOption({ label, [field]: value }, options.length)
    })

    return options
})

const selectedStream = computed(() => {
    return streamOptions.value.find((item) => item.key === selectedStreamKey.value) || streamOptions.value[0] || null
})

const resetSelected = () => {
    const defaultPlayUrl = normalizeUrl(props.line?.default_play_url)
    if (defaultPlayUrl) {
        const matched = streamOptions.value.find((item) => item.url === defaultPlayUrl)
        if (matched) {
            selectedStreamKey.value = matched.key
            return
        }
    }
    selectedStreamKey.value = streamOptions.value[0]?.key || ''
}

watch(
    () => [props.line, props.show],
    () => {
        resetSelected()
    },
    { immediate: true, deep: true }
)

const navigateToWebview = (url: string) => {
    uni.navigateTo({ url: `/pages/webview/webview?url=${encodeURIComponent(url)}` })
}

const selectOption = (item: PopupStreamOption) => {
    selectedStreamKey.value = item.key
}

const openSelected = () => {
    const url = selectedStream.value?.url || ''
    if (!url) {
        uni.showToast({ title: '暂无可用直播链接', icon: 'none' })
        return
    }
    navigateToWebview(url)
}

const openSource = () => {
    if (!sourceUrl.value) {
        uni.showToast({ title: '暂无源站链接', icon: 'none' })
        return
    }
    navigateToWebview(sourceUrl.value)
}

const handleClose = () => {
    emit('close')
}
</script>

<style lang="scss" scoped>
.match-live-popup {
    padding: 40rpx 28rpx calc(28rpx + env(safe-area-inset-bottom));
    background: #fff;

    &__header {
        display: flex;
        flex-direction: column;
        gap: 10rpx;
        margin-bottom: 28rpx;
    }

    &__title {
        font-size: 32rpx;
        font-weight: 700;
        color: #111827;
    }

    &__desc {
        font-size: 24rpx;
        color: #6b7280;
        line-height: 1.5;
    }

    &__section {
        margin-bottom: 32rpx;
    }

    &__section-title {
        display: block;
        margin-bottom: 18rpx;
        font-size: 26rpx;
        font-weight: 600;
        color: #1f2937;
    }

    &__options {
        display: flex;
        flex-direction: column;
        gap: 16rpx;
    }

    &__option {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 16rpx;
        padding: 22rpx 24rpx;
        border: 2rpx solid #e5e7eb;
        border-radius: 20rpx;
        background: #f9fafb;

        &--active {
            border-color: #185dff;
            background: rgba(24, 93, 255, 0.08);
        }
    }

    &__option-main {
        min-width: 0;
        display: flex;
        flex-direction: column;
        gap: 8rpx;
    }

    &__option-title {
        font-size: 28rpx;
        font-weight: 600;
        color: #111827;
    }

    &__option-url {
        font-size: 22rpx;
        color: #6b7280;
        line-height: 1.4;
        word-break: break-all;
    }

    &__option-tag {
        flex-shrink: 0;
        padding: 8rpx 16rpx;
        border-radius: 999rpx;
        background: #185dff;
        color: #fff;
        font-size: 22rpx;
        font-weight: 600;
    }

    &__empty {
        padding: 40rpx 0;
        text-align: center;
        font-size: 24rpx;
        color: #9ca3af;
    }

    &__actions {
        display: flex;
        flex-direction: column;
        gap: 18rpx;
    }
}
</style>
