import { ref, onMounted, nextTick } from 'vue';
import { ElMessageBox } from 'element-plus';
import { message } from '@/utils/message';

/**
 * @FileDescription: el-table 函数式组件hooks--实现一个表格的数据加载、分页、搜索、删除等操作,
 * @function:useTable(config)
 * @param {object} config                               useTable(配置项)
 * @param {function} config.requestDataFN               分页列表接口函数
 * @param {object} config.searchForm                    搜索表单配置
 * @param {function} config.deleteItemFN                删除某一项接口函数
 *
 * @param {object} config.pagination                    分页配置对象
 * @param {string} config.pagination.currentPage        当前页数
 * @param {string} config.pagination.pageSize           每页显示条数
 * @param {string} config.pagination.total              总条数
 * @param {string} config.pagination.pageSizes          每页显示条数选项[10, 20, 30, 40, 50]
 * @param {string} config.pagination.layout             布局方式'total, sizes, prev, pager, next, jumper'
 * @param {string} config.pagination.background         页码背景色true/false
 * ...其他参考element-plus分页组件参数
 *
 * @param {object} config.options                       其他配置项
 * @param {boolean} config.options.immediate            是否默认执行
 *
 * @returns {boolean} lodding                           表格加载状态（包含请求数据，删除数据等）
 * @returns {array} tableData                           表格数据
 * @returns {object} pagination                         表格分页数据
 * @returns {function} handleRequestDataFN              请求数据函数
 * @returns {function} handleSearchFN                   搜索函数
 * @returns {function} handlePaginationChangeFN         页码或者每页显示条数变化函数
 * @returns {function} handleDeleteItemFN               删除函数
 * */
export function useTable(config) {
    const {
        searchForm,
        requestDataFN,
        deleteItemFN,
        options = {
            immediate: true,
        },
    } = config;

    const tableData = ref([]);
    const loading = ref(false);
    const defaultPagination = {
        currentPage: 1,
        pageSize: 10,
        total: 0,
        pageSizes: [10, 20, 30, 40, 50],
        layout: 'total, sizes, prev, pager, next, jumper',
        background: true,
    };
    const pagination = ref({ ...defaultPagination, ...(config.pagination || {}) });

    // 请求表格数据
    const handleRequestDataFN = () => {
        /** 这里必须判断loading状态，防止重复请求数据，有一个场景就会重复触发
         * 比如：当前分页不是第一页，此时用户点击查询按钮触发handleSearchFN，会先改变页码，然后请求一次数据，
         * 但是页码改变又会触发一次handlePaginationChangeFN，重新设置页码，再请求一次数据，此时因为loading状态为true，
         * 所以不会再请求数据，导致数据重复
         */
        if (loading.value || !requestDataFN) return;
        loading.value = true;
        requestDataFN({
            ...searchForm,
            pageNumber: pagination.value.currentPage,
            psgeSize: pagination.value.pageSize,
        })
            .then((result) => {
                const { list, total } = result.data;
                tableData.value = list;
                pagination.value.total = total;
            })
            .finally(() => {
                loading.value = false;
            });
    };

    // 点击搜索按钮请求表格数据
    const handleSearchFN = () => {
        pagination.value.currentPage = 1;
        handleRequestDataFN();
    };

    // 页码或者每页显示条数变化请求表格数据
    const handlePaginationChangeFN = (currentPage, pageSize) => {
        pagination.value.currentPage = currentPage;
        pagination.value.pageSize = pageSize;
        handleRequestDataFN();
    };

    // 删除某一项
    const handleDeleteItemFN = (params, callback) => {
        if (loading.value || !deleteItemFN) return;
        ElMessageBox.confirm('您确认要确认删除选中的数据吗？', '删除数据')
            .then(() => {
                loading.value = true;
                deleteItemFN(params)
                    .then(() => {
                        if (callback) {
                            callback();
                        } else {
                            message('删除数据成功', { type: 'success' });
                            /* 这里使用nextTick是因为loading状态还是true，
                             * handleRequestDataFN会因为loading状态为true而不执行,
                             * finally执行顺序在then之后
                             */
                            nextTick(() => handleRequestDataFN());
                        }
                    })
                    .finally(() => {
                        loading.value = false;
                    });
            })
            .catch(() => {});
    };

    onMounted(() => {
        if (options?.immediate === undefined || options.immediate === true) {
            handleRequestDataFN();
        }
    });

    return {
        loading,
        tableData,
        pagination,
        handleRequestDataFN,
        handleSearchFN,
        handlePaginationChangeFN,
        handleDeleteItemFN,
    };
}
