<template>
    <div class="filter flex items-center" ref="filterEl">
        <slot name="filter"></slot>
    </div>
    <ElConfigProvider :size="size ? size : isMobile ? '' : 'small'">
        <ElTable :data="tableData" :height="tableHeight" stripe v-loading="loading">
            <slot></slot>
        </ElTable>
    </ElConfigProvider>
    <div class="mt-4 flex justify-center">
        <ElPagination
            ref="paginEl"
            :layout="isMobile ? 'total, pager' : 'total, sizes, prev, pager, next, jumper'"
            v-model:page-size="pageConfig.pageSize"
            v-model:current-page="page"
            :total="total"
            :small="!isMobile"
        />
    </div>
</template>
<script setup>
import { ref, onMounted, computed, watch, inject } from 'vue'
import { http } from '@/plugins/http'
import { ElMessage } from 'element-plus'
import { useStorage, useElementBounding, useWindowSize } from '@vueuse/core'
import { useDebounceFn } from '@vueuse/core'

const props = defineProps({
    url: {
        type: String,
        required: true
    },
    query: {
        type: Object,
        default: () => ({})
    },
    order: {
        type: String,
        default: () => 'createdAt,desc'
    },
    size: {
        type: String,
        default: () => ''
    }
})
const search = computed(() => {
    const query = { ...(props.query || {}) }
    Object.keys(query).forEach((key) => {
        if (query[key] === null) {
            delete query[key]
        }
    })
    return {
        ...query,
        order: props.order
    }
})

const filterEl = ref(null)
const paginEl = ref(null)
const { height: filterHeight } = useElementBounding(filterEl)
const { height: paginHeight } = useElementBounding(paginEl)
const { height: windowHeight } = useWindowSize()
const tableHeight = computed(() => windowHeight.value - 120 - filterHeight.value - paginHeight.value)
const isMobile = inject('isMobile')

const tableData = ref([])
const page = ref(1)
const pageConfig = useStorage('pageConfig', {
    pageSize: 20
})

const total = ref(0)
const loading = ref(false)
const getData = useDebounceFn(async (reset = false) => {
    if (reset) {
        page.value = 1
    }
    try {
        loading.value = true
        const res = await http.get(props.url, {
            page: page.value,
            pageSize: pageConfig.value.pageSize,
            ...search.value
        })
        loading.value = false
        tableData.value = res.data
        total.value = res.meta.total
    } catch (e) {
        loading.value = false
        ElMessage.error(e.message)
    }
}, 100)

onMounted(() => {
    getData()
})
watch(search, () => {
    console.log('search changed')
    if (page.value !== 1) {
        page.value = 1
    } else {
        getData()
    }
})
watch([page, pageConfig], () => {
    console.log('page changed')
    getData()
})
defineExpose({
    refresh: getData
})
</script>
<style lang="less" scoped>
.filter {
    :deep(> *) {
        margin-bottom: 15px;
        margin-right: 15px;
    }
}
</style>
