import {computed, nextTick, reactive, Ref, ref, watch, onMounted} from 'vue'
import type {VxePagerProps, VxeTableProps} from "vxe-table";
import {VxePager, VxeTable, VxeColumn} from "vxe-table";
import {TablePublicMethods, VxeTableEventProps} from "vxe-table/types/table";
import XEUtils from "xe-utils";
import {stringIsBlank, stringNotBlank} from "@/utils/blank-utils";
import {TableExportMethods} from "vxe-table/types/export";
import {BizException, ExceptionEnum} from "@/utils/BizException";
import {eachAndReturnList} from "@/utils/cyRefList";
import {ElButton, ElPopover} from "element-plus";
import setDialogToJs from "@/components/js-dialog-comp/useDialogToJs";
import CyDialog from "@/components/cy/dialog/src/CyDialog.vue";
import {IsCyDialog} from "@/components/cy/dialog/src/useCyDialog";
import CyFlex from "@/components/cy/flex/src/CyFlex.vue";

declare type PageQuery = {
    currentPage?: number,
    pageSize?: number,
}

declare type SimplifiedConfiguration<D> = {
    rowHeight?: number,
    keyField?: string,
    currentKey?: string | number,
    remoteSearch?: (data?: PageQuery & any) => Promise<D[]>,
    tableProps?: VxeTableEventProps<D> & VxeTableProps<D>,
    showPage?: boolean,
    result?: string,
    total?: string,
    pagesProps?: VxePagerProps,
    showCheckbox?: boolean,
    mountedQuery?: boolean,
    dialogProps?: IsCyDialog,
    dialogHeader?: () => any
}


function tsxVModel(modelValue: object, name: string, modelName?: string) {
    const updateName = modelName || name
    return {
        // @ts-ignore
        [updateName]: modelValue[name],
        ['onUpdate:' + updateName]: (el: any) => {
            // @ts-ignore
            modelValue[name] = el
        }
    }
}

function useVxeTable<D = any>(simplifiedConfiguration: SimplifiedConfiguration<D>) {
    const tableRef: Ref<TablePublicMethods<D> & TableExportMethods<D> | undefined> = ref()
    const props: VxeTableProps<D> & VxeTableEventProps<D> & SimplifiedConfiguration<D> = reactive({
        height: '100%',
        rowConfig: {
            isHover: true,
            isCurrent: true,
            height: simplifiedConfiguration?.rowHeight || 48,
            useKey: true,
            keyField: simplifiedConfiguration?.keyField || '',
        },
        scrollY: {
            enabled: true,
            gt: 0
        },
        columnConfig: {
            resizable: true
        },
        scrollX: {
            enabled: false,
        },
        exportConfig: {},
        showOverflow: true,
        currentKey: '',
        menuConfig: {
            enabled: true
        },
        loading: false,
        loadingConfig: {
            text: '加载中...',
            icon: '',
        },
        checkboxConfig: {
            reserve: true,
            highlight: true,
            range: true,
        },
        data: [],
    })

    if (simplifiedConfiguration.showPage) {
        delete props.rowConfig?.height
        props.scrollY!.enabled = false
        props!.showOverflow = false
        props!.checkboxConfig!.reserve = true
        if (stringIsBlank(props.rowConfig?.keyField)) {
            BizException(ExceptionEnum.MESSAGE_ERROR, '请先设置行id')
        }
    }

    const pageVO = reactive({
        currentPage: 1,
        pageSize: 30,
        total: 0
    })

    const pagerProps: VxePagerProps = reactive({
        loading: false,
    })

    watch(() => props.currentKey, () => {
        if (stringNotBlank(defaultProps.value.rowConfig?.keyField)) {
            const findData = XEUtils.find(tableRef.value?.getData(), (item) => {
                // @ts-ignore
                return item[defaultProps.value.rowConfig?.keyField] === props.currentKey;
            })
            if (findData) {
                tableRef.value?.scrollToRow(findData)
                tableRef.value?.setCurrentRow(findData)
            }
        }
    }, {flush: 'post'})

    const defaultProps = computed(() => {
        return {
            ...simplifiedConfiguration?.tableProps,
            ...props
        } as VxeTableProps<D>
    })

    const CyVxeTable = (props: VxeTableProps<D>, {slots}: any) => {

        mutation.setTableDefaultSlots = () => {
            return slots.default ? slots.default() : null
        }

        const TempVxeTable = () => {
            return <VxeTable
                ref={tableRef}
                {...defaultProps.value}
                {...props}
            >

                {{
                    default: () => {
                        function renderIcon(checked: boolean, indeterminate: boolean) {
                            if (indeterminate) {
                                return <i class="vxe-icon-square-minus-fill"></i>
                            } else if (checked) {
                                return <i class="vxe-icon-square-checked-fill"></i>
                            } else {
                                return <i class="vxe-icon-checkbox-unchecked"></i>
                            }
                        }

                        function checkboxHeader(checked: boolean, indeterminate: boolean) {
                            return <ElPopover placement="right">
                                {{
                                    default: () => {
                                        return [
                                            `当前选中${pageMemory.size}条`,
                                            <div style="text-align: right;margin-top: 5px;">
                                                <ElButton
                                                    type="primary"
                                                    onClick={(el) => {
                                                        if (pageMemory.size > 0)
                                                            handelLookCheckBox()
                                                    }}
                                                >{{default: () => '详情'}}
                                                </ElButton>
                                                <ElButton
                                                    type="danger"
                                                    onClick={(el) => {
                                                        mutation.clearCheckboxRow()
                                                    }}
                                                >{{default: () => '清空'}}
                                                </ElButton>
                                            </div>
                                        ]
                                    },
                                    reference: () => {
                                        return <span
                                            style={"font-size: 1.1em;cursor: pointer;"}
                                            onClick={(el) => {
                                                el.preventDefault()
                                                el.stopPropagation()
                                                handelCheckboxAll()
                                            }}>{renderIcon(checked, indeterminate)}</span>
                                    }
                                }}
                            </ElPopover>
                        }

                        return [
                            simplifiedConfiguration.showCheckbox ?
                                <VxeColumn type="checkbox" width={"max-content"}>
                                    {{
                                        // @ts-ignore
                                        header({checked, indeterminate}) {
                                            return checkboxHeader(checked, indeterminate)
                                        },
                                        // @ts-ignore
                                        checkbox({row, checked, indeterminate}) {
                                            return <span style={"font-size: 1.1em;cursor: pointer;"}
                                                         onClick={(el) => {
                                                             el.preventDefault()
                                                             el.stopPropagation()
                                                             handelCheckboxChange({row, checked: !checked})
                                                         }}>
                                                 {renderIcon(checked, indeterminate)}
                                            </span>
                                        }
                                    }}
                                </VxeColumn> : null,
                            ...slots.default ? slots.default() : null,
                        ];
                    }
                }}
            </VxeTable>
        }

        if (simplifiedConfiguration.showPage) {
            return <div class="cy_display_flex_y">
                <div class="cy_flex_1-y">
                    <TempVxeTable/>
                </div>
                <div style="height:max-content">
                    <VxePager
                        onPageChange={(data) => {
                            pageChange()
                        }}
                        size={"small"}
                        {...tsxVModel(pageVO, 'currentPage')}
                        {...tsxVModel(pageVO, 'pageSize')}
                        total={pageVO.total}
                        {...simplifiedConfiguration.pagesProps}
                        {...pagerProps}
                    />
                </div>
            </div>

        } else {
            return <TempVxeTable/>
        }
    }

    function exportExcel(filename: string = '', sheetName: string = 'sheet1') {
        if (!XEUtils.isString(filename)) {
            filename = ''
        }
        tableRef.value?.openExport({
            filename,
            sheetName,
            types: ['xlsx', 'csv', 'html', 'xml', 'txt'],
            type: 'xlsx',
            useStyle: true,
            original: true,
        })
    }

    let queryParamsCache = {}

    function pageChange() {
        if (XEUtils.isEmpty(queryParamsCache)) {
            return
        }
        const data = {
            ...queryParamsCache,
            ...pageVO
        }
        props.loading = true
        pageQuery(data, false)
    }

    function pageQuery(data: any, clearCurrentPage: boolean = true) {
        pagerProps.loading = true
        // @ts-ignore
        simplifiedConfiguration.remoteSearch(data).then(res => {
            // @ts-ignore
            const data: D[] = XEUtils.get(res, simplifiedConfiguration!.result || 'result') as D[]
            // @ts-ignore
            const total: number = XEUtils.get(res, simplifiedConfiguration!.total || 'total') as number
            props.data = data
            pageVO.total = total
        }).catch((e) => {
            props.data = []
            pageVO.total = 0
            console.error(e)
        }).finally(() => {
            if (clearCurrentPage) {
                pageVO.currentPage = 1
                pageMemory.clear()
            }
            props.loading = false
            pagerProps.loading = false
            handelPageCheckBox()
        })
    }

    const pageMemory = reactive(new Map<any, D>());

    function getCheckboxRecords() {
        // @ts-ignore
        return eachAndReturnList(pageMemory, (item) => {
            return item
        })
    }

    function handelCheckbox() {
        const data = tableRef.value!.getCheckboxRecords()
        if (data.length > 0) {
            XEUtils.arrayEach(tableRef.value!.getCheckboxRecords(), (item) => {
                // @ts-ignore
                pageMemory.set(item[simplifiedConfiguration.keyField], item)
            })
        } else {
            XEUtils.arrayEach(tableRef.value!.getData(), (item) => {
                // @ts-ignore
                pageMemory.delete(item[simplifiedConfiguration.keyField])
            })
        }
    }

    function handelPageCheckBox() {
        nextTick().then(() => {
            // @ts-ignore
            XEUtils.arrayEach(pageMemory, (item) => {
                tableRef.value?.setCheckboxRow(item, true)
            })
        })
    }

    function handelCheckboxChange({row, checked}: { row: any, checked: boolean }) {
        mutation.setCheckboxRow(row, checked)
    }

    async function handelCheckboxAll() {
        await tableRef.value?.toggleAllCheckboxRow()
        nextTick().then(() => {
            handelCheckbox()
        })
    }

    function querySearch() {
        props.loading = true
        // @ts-ignore
        if (simplifiedConfiguration.showPage) {
            const pageData = {
                ...pageVO,
                total: 0,
                currentPage: 1
            }
            queryParamsCache = pageData
            pageQuery(pageData)
        } else {
            // @ts-ignore
            simplifiedConfiguration.remoteSearch({...pageVO}).then(res => {
                props.data = res
            }).catch(() => {
                props.data = []
            }).finally(() => {
                props.loading = false
            })
        }
    }


    function handelLookCheckBox() {

        const dialog = (
            <CyDialog title="选中详情"
                      ignore-error
                      body-width="70%"
                      {...simplifiedConfiguration.dialogProps}>
                {{
                    default: () => {
                        const data = getCheckboxRecords()
                        return <CyFlex>
                            {{
                                header: () => {
                                    try {
                                        if (simplifiedConfiguration.dialogHeader) {
                                            const Scc = simplifiedConfiguration?.dialogHeader();
                                            if (typeof Scc !== 'undefined') {
                                                return <Scc/>
                                            } else {
                                                console.error('dialogHeader需要返回一个组件')
                                            }
                                        }

                                    } catch (e) {
                                        console.error('dialogHeader需要返回一个组件', e)
                                        return null
                                    }
                                },
                                default: () => {
                                    return <VxeTable data={data}
                                                     rowConfig={{
                                                         keyField: simplifiedConfiguration.keyField,
                                                         isCurrent: true,
                                                         isHover: true,
                                                         useKey: true,
                                                     }}
                                                     scrollY={{enabled: true, gt: 100}}
                                                     showOverflow={data.length > 100}
                                                     height={"100%"}>
                                        {{
                                            default: () => {
                                                return [
                                                    <VxeColumn title={"删除"} width={80} fixed="left">
                                                        {{
                                                            default({row}: any) {
                                                                return <ElButton
                                                                    type="danger"
                                                                    onClick={(el) => {
                                                                        handelCheckboxChange({row, checked: false})
                                                                    }}
                                                                >{{default: () => '删除'}}
                                                                </ElButton>
                                                            }
                                                        }}
                                                    </VxeColumn>,
                                                    mutation.setTableDefaultSlots()
                                                ]
                                            }
                                        }}
                                    </VxeTable>

                                }
                            }}

                        </CyFlex>
                    }
                }}
            </CyDialog>
        )

        setDialogToJs(dialog, null).then(() => {
        })
    }

    const mutation = {
        updateByIndex: function updateByIndex(data: D | any, index: number) {
            const tableData = tableRef.value?.getData()
            // @ts-ignore
            tableData[index] = data
            // @ts-ignore
            tableRef.value?.loadData(tableData)
        },
        setCheckboxRow: async function (row: D, checked: boolean) {
            await tableRef.value?.setCheckboxRow(row, checked)
            // @ts-ignore
            const key = XEUtils.get(row, simplifiedConfiguration!.keyField, null) as string | null
            if (key === null) return
            if (checked) {
                pageMemory.set(key, row)
            } else {
                pageMemory.delete(key)
            }
        },
        clearCheckboxRow() {
            tableRef.value?.clearCheckboxRow()
            pageMemory.clear()
        },
        setTableDefaultSlots(): any {

        }
    }

    onMounted(() => {
        if (simplifiedConfiguration.mountedQuery) {
            nextTick().then(() => {
                querySearch()
            })
        }
    })


    return {
        tableRef,
        CyVxeTable: CyVxeTable,
        tableProps: props,
        exportExcel,
        mutation,
        querySearch,
        getCheckboxRecords
    }
}

export default useVxeTable
