import {
    ref,
    reactive,
    watch,
    isRef,
    nextTick
} from 'vue'

export function usePagination(
    requestFn,
    transformFn,
    options = {}
) {
    const list = ref([])
    const loading = ref(false)
    const error = ref(false)
    const finished = ref(false)
    const firstLoading = ref(true)
    const empty = ref(false)

    const {
        pageSize = 10,
            search = {},
            autoWatchSearch = false,
            debounceTime = 300,
            autoFetch = false,

            // 字段映射
            dataKey = 'rows',
            totalKey = 'total',

            // 分页字段名映射
            pageField = 'current',
            sizeField = 'pageSize',

            onBeforeRequest,
            onAfterRequest
    } = options

    const pageState = reactive({
        page: 1,
        pageSize: isRef(pageSize) ? pageSize.value : pageSize,
        total: 0,
        maxPage: 1,
        search: isRef(search) ? search.value : search
    })

    let debounceTimer = null

    const fetchData = async (type = 'refresh') => {
        if (loading.value) return Promise.resolve()
        console.log(type)
        loading.value = true
        error.value = false

        if (typeof onBeforeRequest === 'function') {
            try {
                onBeforeRequest(type, pageState)
            } catch (err) {
                console.warn('onBeforeRequest 执行异常:', err)
            }
        }

        if (type === 'refresh') {
            pageState.page = 1
            finished.value = false
            if (list.value.length === 0) {
                firstLoading.value = true
            }
        } else if (type === 'loadMore') {
            if (pageState.page >= pageState.maxPage) {
                loading.value = false
                finished.value = true
                return Promise.resolve('no more')
            }
            pageState.page += 1
        }

        const params = {
            ...pageState.search,
            [pageField]: pageState.page,
            [sizeField]: pageState.pageSize,
        }

        try {
            const res = await requestFn(params)

            const rawData = res[dataKey]
            
            const data = typeof transformFn === 'function' ? transformFn(rawData) : rawData

            if (type === 'refresh') {
                list.value = data
            } else {
                list.value.push(...data)
            }

            const total = res[totalKey] || list.value?.length
            pageState.total = total
            pageState.maxPage = Math.ceil(total / pageState.pageSize)
            finished.value = list.value.length >= total
            empty.value = list.value.length === 0
        } catch (err) {
            console.error('分页请求失败:', err)
            error.value = true
        } finally {
            loading.value = false
            firstLoading.value = false

            if (typeof onAfterRequest === 'function') {
                try {
                    onAfterRequest(type, pageState, {
                        error: error.value
                    })
                } catch (err) {
                    console.warn('onAfterRequest 执行异常:', err)
                }
            }
        }
    }

    const refresh = () => fetchData('refresh')
    const loadMore = () => fetchData('loadMore')

    const resetPagination = () => {
        list.value = []
        pageState.page = 1
        pageState.total = 0
        pageState.maxPage = 1
        finished.value = false
        error.value = false
        firstLoading.value = true
        empty.value = false
    }

    if (autoWatchSearch && isRef(search)) {
        watch(search, (newVal) => {
            pageState.search = newVal
            clearTimeout(debounceTimer)
            debounceTimer = setTimeout(() => {
                refresh()
            }, debounceTime)
        }, {
            deep: true
        })
    }

    watch(pageSize, (newVal) => {
        pageState.pageSize = newVal
    }, {
        deep: true
    })

    if (autoFetch) {
        nextTick(() => {
            refresh()
        })
    }

    return {
        list,
        loading,
        error,
        finished,
        firstLoading,
        empty,
        pageState,
        refresh,
        loadMore,
        resetPagination
    }
}