<template>
    <!-- 粘性容器 -->
    <view v-if="sticky" ref="stickyRef" :class="['im-tabs-sticky', { 'im-tabs-sticky-fixed': isSticky }]"
        :style="stickyStyle">
        <navigation :currentIndex="currentIndex" />
    </view>

    <!-- 主容器 -->
    <view ref="containerRef" :class="[
        'im-tabs',
        customClass,
        `im-tabs-${position}`,
        `im-tabs-${type}`,
        {
            'im-tabs-border': border,
            'im-tabs-scrollable': scrollable,
            'im-tabs-centered': centered
        }
    ]" :style="containerStyle" @scroll="onContainerScroll">
        <!-- 非粘性模式下的导航 -->
        <tabs-navigation :currentIndex="currentIndex" v-if="!sticky" @scroll="onNavScroll" />

        <!-- 标签内容区域 -->
        <view v-if="position === 'top' || position === 'bottom'" ref="contentRef" class="im-tabs-content"
            :class="contentClass" :style="contentStyle" @touchstart="onTouchStart" @touchmove="onTouchMove"
            @touchend="onTouchEnd" @touchcancel="onTouchEnd">
            <!-- 内容滑动容器 -->
            <view ref="swipeRef" class="im-tabs-swipe" :class="{ 'im-tabs-swipe-transition': !isSwiping }"
                :style="swipeStyle">
                <slot />
            </view>
        </view>

        <!-- 垂直布局的内容区域 -->
        <view v-else ref="contentRef" class="im-tabs-content im-tabs-content-vertical" :class="contentClass"
            :style="contentStyle">
            <slot />
        </view>
    </view>
</template>

<script lang="ts" setup>
import {
    ref,
    computed,
    watch,
    onMounted,
    onUnmounted,
    provide,
    reactive,
    getCurrentInstance
} from 'vue'
import type { TabsProps, TabsEmits, TabItem } from '../../types/components/tabs'
import Navigation from './navigation.vue'
import { safeRequestAnimationFrame } from './utils/compatibility'

const props = withDefaults(defineProps<TabsProps>(), {
    modelValue: 0,
    items: () => [],
    position: 'top',
    type: 'line',
    swipeable: true,
    showSlider: true,
    sliderWidth: 'auto',
    sliderHeight: 2,
    sliderColor: '#1989fa',
    border: true,
    background: '#ffffff',
    height: 44,
    minTabWidth: 0,
    maxTabWidth: 0,
    sticky: false,
    stickyOffsetTop: 0,
    scrollable: false,
    centered: false,
    keepAlive: true,
    lazy: false,
    duration: 300,
    scrollOnInit: true,
    gutter: 0,
    showIcon: false,
    iconPosition: 'left',
    animation: 'slide'
})

const emit = defineEmits<TabsEmits>()
const instance = getCurrentInstance()

// 响应式数据
const currentIndex = ref(props.modelValue)
const isSwiping = ref(false)
const startX = ref(0)
const deltaX = ref(0)
const sliderLeft = ref(0)
const sliderWidth = ref(0)
const isSticky = ref(false)
const scrollLeft = ref(0)
const changeTimer = ref<number | null>(null)
const updateTimer = ref<number | null>(null)

// 计算属性
const currentActiveKey = computed(() => {
    const tab = props.items[currentIndex.value]
    return tab?.id ?? currentIndex.value
})

const containerStyle = computed(() => {
    const style: Record<string, any> = {}

    if (props.background) {
        style.backgroundColor = props.background
    }

    if (props.height) {
        style.height = `${props.height}px`
    }

    if (props.position === 'left' || props.position === 'right') {
        style.display = 'flex'
        style.flexDirection = props.position === 'left' ? 'row' : 'row-reverse'
    }

    // 如果是可滚动模式，添加滚动相关样式
    if (props.scrollable) {
        style.overflowX = 'scroll'
        style['-webkit-overflow-scrolling'] = 'touch'
        style.whiteSpace = 'nowrap'
    }

    return style
})

const contentStyle = computed(() => {
    const style: Record<string, any> = {}

    if (props.position === 'top' || props.position === 'bottom') {
        if (props.swipeable) {
            style.overflow = 'hidden'
        }
    } else {
        style.flex = 1
        style.overflow = props.swipeable ? 'hidden' : 'auto'
    }

    return style
})

const swipeStyle = computed(() => {
    const translateX = props.position === 'top' || props.position === 'bottom'
        ? -currentIndex.value * 100 + '%'
        : '0'

    const translateY = props.position === 'left' || props.position === 'right'
        ? -currentIndex.value * 100 + '%'
        : '0'

    const transition = isSwiping.value ? 'none' : `transform ${props.duration}ms`

    return {
        transform: `translate3d(${translateX}, ${translateY}, 0)`,
        transition: transition,
        flexDirection: props.position === 'top' || props.position === 'bottom' ? 'row' : 'column',
        display: 'flex'
    } as Record<string, any>
})

const stickyStyle = computed(() => {
    return {
        top: `${props.stickyOffsetTop}px`,
        zIndex: 1000
    }
})

const sliderStyle = computed(() => {
    const style: Record<string, any> = {
        backgroundColor: props.sliderColor,
        height: `${props.sliderHeight}px`,
        transform: `translate3d(${sliderLeft.value}px, 0, 0)`,
        transition: isSwiping.value ? 'none' : `transform ${props.duration}ms, width ${props.duration}ms`,
        width: `${sliderWidth.value}px`
    }

    if (props.sliderWidth !== 'auto') {
        style.width = typeof props.sliderWidth === 'number'
            ? `${props.sliderWidth}px`
            : props.sliderWidth
    }

    return style
})



// 处理标签点击
const handleTabClick = async (index: number, tab: TabItem) => {
    if (tab.disabled) {
        emit('disabled', index, tab)
        return
    }

    emit('click', index, tab)

    // beforeChange 回调
    if (props.beforeChange) {
        try {
            const result = await props.beforeChange(index, tab)
            if (result === false) {
                return
            }
        } catch (error) {
            console.error('beforeChange 回调出错:', error)
            return
        }
    }

    // 切换标签
    setActive(index)
}

// 提供数据给子组件
provide('tabs', reactive({
    items: props.items,
    currentIndex,
    type: props.type,
    showSlider: props.showSlider,
    sliderStyle,
    scrollable: props.scrollable,
    centered: props.centered,
    gutter: props.gutter,
    showIcon: props.showIcon,
    iconPosition: props.iconPosition,
    minTabWidth: props.minTabWidth,
    maxTabWidth: props.maxTabWidth,
    onTabClick: handleTabClick
}))

// 设置激活标签
const setActive = (index: number) => {
    if (index === currentIndex.value) {
        return
    }

    const oldIndex = currentIndex.value
    console.log('im-tabs: 切换标签', oldIndex, '->', index)

    currentIndex.value = index

    // 触发事件
    emit('update:modelValue', index)
    emit('update:activeKey', currentActiveKey.value)
    emit('change', index, props.items[index])

    // 延迟更新滑动条位置
    if (updateTimer.value) {
        clearTimeout(updateTimer.value)
    }
    updateTimer.value = Number(setTimeout(() => {
        updateSliderPosition()
    }, 50))

    // 延迟滚动到激活标签
    if (props.scrollable) {
        setTimeout(() => {
            scrollToActiveTab()
        }, 100)
    }
}

// 更新滑动条位置
const updateSliderPosition = () => {
    if (!props.showSlider || props.items.length === 0) {
        return
    }

    // 清除之前的定时器
    if (updateTimer.value) {
        clearTimeout(updateTimer.value)
    }

    // 延迟执行
    updateTimer.value = Number(setTimeout(() => {
        updateSliderPositionImpl()
    }, 50))
}

// 实际的更新逻辑
const updateSliderPositionImpl = () => {
    try {
        const query = uni.createSelectorQuery().in(instance)

        // 使用不同的选择器避免冲突
        const selector = `.im-tabs-nav .im-tabs-tab:nth-child(${currentIndex.value + 1})`

        query.select(selector).boundingClientRect((res: any) => {
            if (!res) {
                // 如果获取失败，设置默认值
                sliderLeft.value = 0
                sliderWidth.value = typeof props.sliderWidth === 'number'
                    ? props.sliderWidth
                    : 50
                return
            }

            // 使用新的查询实例获取导航容器
            const navQuery = uni.createSelectorQuery().in(instance)
            navQuery.select('.im-tabs-nav').boundingClientRect((navRes: any) => {
                if (!navRes) {
                    sliderLeft.value = res.left
                    sliderWidth.value = props.sliderWidth === 'auto' ? res.width :
                        (typeof props.sliderWidth === 'number' ? props.sliderWidth : res.width)
                    return
                }



                // 计算滑动条位置
                const left = res.left - navRes.left
                sliderLeft.value = left

                // 计算滑动条宽度
                if (props.sliderWidth === 'auto') {
                    sliderWidth.value = res.width
                } else {
                    sliderWidth.value = typeof props.sliderWidth === 'number'
                        ? props.sliderWidth
                        : parseInt(props.sliderWidth as string) || res.width
                }
            }).exec()
        }).exec()
    } catch (error) {
        console.error('更新滑动条位置失败:', error)
        // 设置默认值
        sliderLeft.value = 0
        sliderWidth.value = 50
    }
}

// 滚动到激活标签
const scrollToActiveTab = () => {
    if (!props.scrollable) return

    // 使用 requestAnimationFrame
    safeRequestAnimationFrame(() => {
        scrollToActiveTabImpl()
    })
}

const scrollToActiveTabImpl = () => {
    try {
        const query = uni.createSelectorQuery().in(instance)

        query.select(`.im-tabs-nav .im-tabs-tab:nth-child(${currentIndex.value + 1})`).boundingClientRect((res) => {
            if (!res) return

            // 在小程序环境中，可以使用 scroll-into-view
            // #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-QQ
            // 这里可以设置 scroll-into-view 属性
            // 导航组件中已经处理了
            // #endif

            // 在 H5 环境中
            // #ifdef H5
            // H5 中的滚动由 CSS 控制
            // #endif
        }).exec()
    } catch (error) {
        console.error('滚动到激活标签失败:', error)
    }
}

// 触摸事件处理
const onTouchStart = (event: TouchEvent) => {
    if (!props.swipeable || props.items.length <= 1) return

    isSwiping.value = true
    startX.value = event.touches[0].clientX
    deltaX.value = 0
}

const onTouchMove = (event: TouchEvent) => {
    if (!isSwiping.value || !props.swipeable) return

    const touch = event.touches[0]
    deltaX.value = touch.clientX - startX.value

    // 阻止页面滚动
    if (Math.abs(deltaX.value) > 10) {
        event.preventDefault()
    }
}

const onTouchEnd = () => {
    if (!isSwiping.value || !props.swipeable) return

    isSwiping.value = false

    // 判断是否需要切换标签
    const threshold = 50 // 使用固定阈值，避免依赖 contentWidth
    const absDeltaX = Math.abs(deltaX.value)

    if (absDeltaX > threshold) {
        const direction = deltaX.value > 0 ? -1 : 1
        const newIndex = currentIndex.value + direction

        if (newIndex >= 0 && newIndex < props.items.length) {
            const tab = props.items[newIndex]
            if (!tab.disabled) {
                handleTabClick(newIndex, tab)
            }
        }
    }

    deltaX.value = 0
}

// 导航滚动事件
const onNavScroll = (event: any) => {
    if (props.scrollable) {
        scrollLeft.value = event.detail?.scrollLeft || 0
        emit('scroll', event)
    }
}

// 容器滚动事件
const onContainerScroll = (event: any) => {
    if (props.scrollable) {
        scrollLeft.value = event.detail?.scrollLeft || 0
        emit('scroll', event)
    }
}

// 监听滚动事件（粘性布局）
const onPageScroll = (event: any) => {
    if (!props.sticky) return

    try {
        const scrollTop = event.scrollTop || 0

        safeRequestAnimationFrame(() => {
            const query = uni.createSelectorQuery().in(instance)

            query.select('.im-tabs-sticky').boundingClientRect((res: any) => {
                if (!res) return

                const newIsSticky = scrollTop >= res.top - props.stickyOffsetTop
                if (newIsSticky !== isSticky.value) {
                    isSticky.value = newIsSticky
                    emit('sticky', newIsSticky)
                }
            }).exec()
        })
    } catch (error) {
        console.error('监听滚动事件失败:', error)
    }
}

// 监听外部值变化
watch(() => props.modelValue, (newVal) => {
    if (newVal !== currentIndex.value) {
        if (changeTimer.value) {
            clearTimeout(changeTimer.value)
        }
        changeTimer.value = Number(setTimeout(() => {
            setActive(newVal)
        }, 50))
    }
})

watch(() => props.activeKey, (newVal) => {
    const index = props.items.findIndex(item =>
        (item.id !== undefined && item.id === newVal) ||
        item.title === newVal
    )

    if (index !== -1 && index !== currentIndex.value) {
        if (changeTimer.value) {
            clearTimeout(changeTimer.value)
        }
        changeTimer.value = Number(setTimeout(() => {
            setActive(index)
        }, 50))
    }
})

watch(() => props.items, () => {
    // 确保当前索引在有效范围内
    if (currentIndex.value >= props.items.length) {
        const newIndex = Math.max(0, props.items.length - 1)
        if (newIndex !== currentIndex.value) {
            if (changeTimer.value) {
                clearTimeout(changeTimer.value)
            }
            changeTimer.value = Number(setTimeout(() => {
                setActive(newIndex)
            }, 50))
        }
    }

    // 延迟更新滑动条位置
    setTimeout(() => {
        updateSliderPosition()
    }, 100)
}, { deep: true })

// 初始化
onMounted(() => {
    // 延迟更新滑动条位置
    setTimeout(() => {
        updateSliderPosition()
    }, 200)

    // 监听页面滚动事件（粘性布局）
    if (props.sticky) {
        // #ifdef H5
        window.addEventListener('scroll', onPageScroll, { passive: true })
        // #endif

        // #ifdef MP-WEIXIN
        // 小程序中使用页面滚动事件
        const pages = getCurrentPages()
        if (pages.length) {
            const page = pages[pages.length - 1]
            if (page && page.onPageScroll) {
                const originalOnPageScroll = page.onPageScroll
                page.onPageScroll = function (e: any) {
                    originalOnPageScroll && originalOnPageScroll.call(this, e)
                    onPageScroll(e)
                }
            }
        }
        // #endif
    }

    // 初始化时滚动到激活标签
    if (props.scrollOnInit) {
        setTimeout(() => {
            scrollToActiveTab()
        }, 300)
    }
})

// 清理
onUnmounted(() => {
    // 清理定时器
    if (changeTimer.value) {
        clearTimeout(changeTimer.value)
    }

    if (updateTimer.value) {
        clearTimeout(updateTimer.value)
    }

    if (props.sticky) {
        // #ifdef H5
        window.removeEventListener('scroll', onPageScroll)
        // #endif
    }
})

// 暴露方法
defineExpose({
    setActive,
    getCurrentIndex: () => currentIndex.value,
    getCurrentKey: () => currentActiveKey.value,
    scrollToActiveTab,
    updateSliderPosition
})
</script>

<style lang="scss" scoped>
.im-tabs {
    position: relative;
    background-color: #ffffff;
    overflow: hidden;

    // 位置
    &-top,
    &-bottom {
        display: flex;
        flex-direction: column;
    }

    &-bottom {
        flex-direction: column-reverse;
    }

    &-left,
    &-right {
        display: flex;
    }

    &-left {
        .im-tabs-content {
            margin-left: 0;
        }
    }

    &-right {
        .im-tabs-content {
            margin-right: 0;
        }
    }

    // 边框
    &-border {
        border-bottom: 1px solid #ebedf0;

        &.im-tabs-bottom {
            border-top: 1px solid #ebedf0;
            border-bottom: none;
        }

        &.im-tabs-left {
            border-right: 1px solid #ebedf0;
            border-bottom: none;
        }

        &.im-tabs-right {
            border-left: 1px solid #ebedf0;
            border-bottom: none;
        }
    }

    // 滚动模式
    &-scrollable {
        .im-tabs-nav {
            flex-wrap: nowrap;
            overflow-x: auto;
            -webkit-overflow-scrolling: touch;

            &::-webkit-scrollbar {
                display: none;
            }
        }
    }

    // 居中模式
    &-centered {
        .im-tabs-nav {
            justify-content: center;
        }
    }
}

.im-tabs-nav {
    display: flex;
    position: relative;
    flex-shrink: 0;
    z-index: 1;
    overflow: hidden;

    .im-tabs-top &,
    .im-tabs-bottom & {
        flex-direction: row;
    }

    .im-tabs-left &,
    .im-tabs-right & {
        flex-direction: column;
        width: auto;
        min-width: 80px;
        max-width: 200px;
    }
}

.im-tabs-content {
    position: relative;
    flex: 1;
    min-height: 0;

    .im-tabs-top &,
    .im-tabs-bottom & {
        width: 100%;
    }

    .im-tabs-left &,
    .im-tabs-right & {
        flex: 1;
        overflow: auto;
    }
}

.im-tabs-swipe {
    width: 100%;
    height: 100%;

    &-transition {
        transition-property: transform;
    }

    .im-tabs-top &,
    .im-tabs-bottom & {
        display: flex;
    }

    .im-tabs-left &,
    .im-tabs-right & {
        display: flex;
        flex-direction: column;
    }
}

// 标签项
.im-tabs-tab {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    cursor: pointer;
    transition: all 0.3s;
    user-select: none;
    padding: 0 12px;
    box-sizing: border-box;

    // 水平布局
    .im-tabs-top &,
    .im-tabs-bottom & {
        height: 100%;
    }

    // 垂直布局
    .im-tabs-left &,
    .im-tabs-right & {
        width: 100%;
        padding: 12px;
    }

    // 禁用状态
    &-disabled {
        cursor: not-allowed;
        opacity: 0.5;

        &:active {
            opacity: 0.5;
        }
    }

    // 激活状态
    &-active {
        font-weight: 600;
    }

    // 图标位置
    &-icon-left {
        flex-direction: row;

        .im-tabs-tab-icon {
            margin-right: 4px;
        }
    }

    &-icon-right {
        flex-direction: row-reverse;

        .im-tabs-tab-icon {
            margin-left: 4px;
        }
    }

    &-icon-top {
        flex-direction: column;

        .im-tabs-tab-icon {
            margin-bottom: 4px;
        }
    }

    &-icon-bottom {
        flex-direction: column-reverse;

        .im-tabs-tab-icon {
            margin-top: 4px;
        }
    }
}

// 标签内容
.im-tabs-tab-content {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    white-space: nowrap;
}

.im-tabs-tab-title {
    font-size: 14px;
    line-height: 1.4;
    transition: color 0.3s;

    .im-tabs-line & {
        color: #646566;
    }

    .im-tabs-tab-active & {
        color: #1989fa;
    }

    .im-tabs-card &,
    .im-tabs-button &,
    .im-tabs-segment & {
        color: #323233;
    }

    .im-tabs-card &-active,
    .im-tabs-button &-active,
    .im-tabs-segment &-active {
        color: #1989fa;
    }
}

.im-tabs-tab-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    transition: color 0.3s;

    .im-tabs-line & {
        color: #646566;
    }

    .im-tabs-tab-active & {
        color: #1989fa;
    }
}

// 徽标
.im-tabs-badge {
    position: absolute;
    top: 0;
    right: 0;
    transform: translate(50%, -50%);
    z-index: 1;

    &-dot {
        width: 6px;
        height: 6px;
        background-color: #ee0a24;
        border-radius: 50%;
    }

    &-number,
    &-text {
        padding: 0 4px;
        font-size: 10px;
        color: #ffffff;
        background-color: #ee0a24;
        border-radius: 10px;
        line-height: 14px;
        min-width: 14px;
        text-align: center;
        font-weight: 500;
    }
}

// 滑动条
.im-tabs-slider {
    position: absolute;
    bottom: 0;
    left: 0;
    z-index: 1;
    border-radius: 2px;

    .im-tabs-bottom & {
        top: 0;
        bottom: auto;
    }

    .im-tabs-left & {
        right: 0;
        left: auto;
        top: 0;
        width: 2px;
        height: auto;
    }

    .im-tabs-right & {
        left: 0;
        top: 0;
        width: 2px;
        height: auto;
    }
}

// 不同类型
.im-tabs {
    &-line {
        .im-tabs-tab {
            background-color: transparent;
        }
    }

    &-card {
        .im-tabs-nav {
            background-color: #f2f3f5;
            padding: 4px;
            border-radius: 8px;
        }

        .im-tabs-tab {
            background-color: transparent;
            border-radius: 6px;
            margin: 0 2px;

            &-active {
                background-color: #ffffff;
                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
            }
        }
    }

    &-button {
        .im-tabs-tab {
            border: 1px solid #ebedf0;
            margin: 0 4px;
            border-radius: 20px;

            &:first-child {
                margin-left: 0;
            }

            &:last-child {
                margin-right: 0;
            }

            &-active {
                border-color: #1989fa;
                background-color: #1989fa;
                color: #ffffff;
            }
        }
    }

    &-segment {
        .im-tabs-nav {
            background-color: #f2f3f5;
            border-radius: 20px;
            padding: 2px;
        }

        .im-tabs-tab {
            flex: 1;
            border-radius: 18px;

            &-active {
                background-color: #ffffff;
                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
            }
        }
    }
}

// 粘性布局
.im-tabs-sticky {
    position: relative;
    z-index: 1000;

    &-fixed {
        position: fixed;
        left: 0;
        right: 0;
    }
}

// 动画
@keyframes im-tabs-fade-in {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes im-tabs-fade-out {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;
    }
}

.im-tabs-content {
    &-fade {
        .im-tabs-tab-pane {
            animation-duration: 0.3s;
            animation-fill-mode: both;

            &-enter-active {
                animation-name: im-tabs-fade-in;
            }

            &-leave-active {
                animation-name: im-tabs-fade-out;
            }
        }
    }
}

// 响应式
@media (max-width: 768px) {
    .im-tabs-tab-title {
        font-size: 13px;
    }

    .im-tabs {
        height: 40px;
    }

    .im-tabs-left,
    .im-tabs-right {
        .im-tabs-nav {
            min-width: 70px;
        }
    }
}
</style>