<template>
    <!-- 树+表格选择弹层 -->
    <Dialog
        v-model="isShowDialog"
        :top="top"
        :width="width"
        v-bind="attrs"
        @closed="closed"
        @open="open"
    >
        <div :style="{ height }" class="super-table-selector-dialog">
            <!-- 树形区域 -->
            <div v-if="isShowTree" class="tree-module">
                <TreeSide
                    ref="treeSideRef"
                    :activeName="treeActiveTabName"
                    :data-loading="treeLoading"
                    :default-expand-all="false"
                    :defaultProps="treeOptions"
                    :nodeKey="treeKey"
                    :tabList="treeTabList"
                    :treeData="treeData"
                    isDeselect
                    v-bind="attrs"
                    @currentChange="currentChange"
                    @tabChange="treeTabChange"
                />
            </div>

            <!-- 表格区域 -->
            <div class="table-module">
                <div v-if="isShowTableSearch" class="search-content">
                    <el-button
                        v-if="isShowAddButton"
                        icon="el-icon-plus"
                        size="small"
                        type="primary"
                        @click="handleAdd"
                        >添加
                    </el-button>
                    <CommonSearch
                        ref="commonSearchRef"
                        :optionList="searchOption"
                        @search="handleSearch"
                    />
                </div>
                <div class="table-content">
                    <div class="table-content-inner">
                        <el-table
                            ref="tableRef"
                            v-loading="tableLoading"
                            :data="enhancedTableData"
                            :row-class-name="rowClassName"
                            :row-key="(row) => row[selectKey]"
                            border
                            element-loading-background="rgba(10 ,38 ,61, 0.9)"
                            height="100%"
                            stripe
                            @row-click="(row) => tableRowClick(row, !row.checked)"
                            @sort-change="(e) => emit('sortChange', e)"
                        >
                            <el-table-column
                                v-if="!isSingleChoice && isShowTableCheckbox"
                                align="center"
                                width="70"
                            >
                                <template v-slot:header>
                                    <el-checkbox
                                        v-model="tableCheckAll"
                                        :disabled="
                                            isSingleChoice ||
                                            enhancedTableData.every((i) => i.disabled)
                                        "
                                        :indeterminate="tableIsIndeterminate"
                                        @change="tableHandleCheckAllChange"
                                    />
                                </template>
                                <template v-slot:default="{ row }">
                                    <el-checkbox
                                        v-model="row.checked"
                                        :disabled="row.disabled"
                                        @change="tableRowClick(row, !row.checked)"
                                    />
                                </template>
                            </el-table-column>
                            <el-table-column
                                :index="
                                    (index) =>
                                        index +
                                        1 +
                                        (tableParams.pageBean.page - 1) *
                                            tableParams.pageBean.pageSize
                                "
                                align="center"
                                label="序号"
                                type="index"
                                width="70"
                            />
                            <el-table-column
                                v-for="item in tableOptions"
                                :key="item.prop"
                                :formatter="
                                    (row) => (item.formatter ? item.formatter(row) : row[item.prop])
                                "
                                :label="item.label"
                                :min-width="item.minWidth"
                                :prop="item.prop"
                                :sortable="item.sortable ? 'custom' : false"
                                align="center"
                                show-overflow-tooltip
                            />
                            <slot name="tableHandler"></slot>
                        </el-table>
                    </div>
                    <div v-if="!isShowSelect" class="table-content-bottom">
                        <Pagination
                            v-if="!isShowSelect && isShowPagination"
                            :pageResult="tableParams.pageBean"
                            @size-change="handleSizeChange"
                            @current-change="handleCurrentChange"
                        />
                        <div class="btn-box">
                            <el-button @click="isShowDialog = false"> 取 消 </el-button>
                            <el-button :disabled="tableLoading" type="primary" @click="confirm">
                                确 定
                            </el-button>
                        </div>
                    </div>
                    <Pagination
                        v-if="isShowSelect && isShowPagination"
                        :pageResult="tableParams.pageBean"
                        @size-change="handleSizeChange"
                        @current-change="handleCurrentChange"
                    />
                </div>
            </div>

            <!-- 选择区域 -->
            <div v-if="isShowSelect" class="select-module">
                <div class="select-title">
                    <div class="title-box-left">
                        <el-checkbox
                            v-if="!isSingleChoice"
                            v-model="checkAll"
                            :indeterminate="isIndeterminate"
                            @change="handleCheckAllChange"
                        />
                        <span>{{ selectTitleName }}</span>
                    </div>
                    <div class="title-box-right">
                        {{ checkboxSelect.length }}/{{ checkboxOpt.length }}
                    </div>
                </div>
                <div class="select-content">
                    <el-checkbox-group v-model="checkboxSelect">
                        <el-checkbox
                            v-for="(item, index) in checkboxOpt"
                            :key="item[selectKey]"
                            :class="[
                                'select-item',
                                checkboxSelect.includes(item[selectKey]) ? ' active' : ''
                            ]"
                            :label="item[selectKey]"
                            border
                            @change="(status) => handleCheckedChange(status, item, checkboxSelect)"
                        >
                            <span :title="item[selectLabel]">
                                {{ isSingleChoice ? '' : `${index + 1}. ` }}{{ item[selectLabel] }}
                            </span>
                        </el-checkbox>
                    </el-checkbox-group>
                </div>
                <div class="select-footer">
                    <el-button @click="isShowDialog = false"> 取 消</el-button>
                    <el-button type="primary" @click="confirm"> 确定</el-button>
                </div>
            </div>
        </div>
    </Dialog>
</template>

<script setup>
import { computed, nextTick, onBeforeUnmount, onMounted, ref, useAttrs, watch } from 'vue'
import Dialog from '@/components/Dialog/index.vue'
import TreeSide from '@/components/TreeSide/index.vue'
import CommonSearch from '@/components/CommonSearch/index.vue'
import Pagination from '@/components/Pagination/index.vue'
import { setQueryValue } from '@/utils/requestWrappers'

import _ from 'lodash'

const attrs = useAttrs()

const props = defineProps({
    isShow: Boolean,
    selectedContent: {
        default: () => [],
        type: [Array, Object]
    },
    top: {
        type: String,
        default: '14vh'
    },
    width: {
        type: String,
        default: '80%'
    },
    height: {
        type: String,
        default: '65vh'
    },
    isShowTree: {
        type: Boolean,
        default: true
    },
    treeOptions: {
        default: () => ({ children: 'children', label: 'name' }),
        type: Object
    },
    treeTabList: {
        default: () => [],
        type: Array
    },
    treeActiveTabName: {
        default: '',
        type: String
    },
    treeLoading: {
        default: false,
        type: Boolean
    },
    treeItem: {
        default: () => ({}),
        type: Object
    },
    tableLoading: {
        default: false,
        type: Boolean
    },
    tableParams: {
        default: () => ({
            pageBean: { pageSize: 0, page: 0, total: 0 },
            querys: [],
            sorter: []
        }),
        type: Object
    },
    tableData: {
        default: () => [],
        type: Array
    },
    treeData: {
        default: () => [],
        type: Array
    },
    searchOption: {
        default: () => [],
        type: Array
    },
    tableOptions: {
        default: () => [],
        type: Array
    },
    treeKey: {
        default: 'id',
        type: String
    },
    selectKey: {
        default: 'id',
        type: String
    },
    selectLabel: {
        default: 'name',
        type: String
    },
    selectTitleName: {
        default: '已选择',
        type: String
    },
    treeValueKey: {
        default: '',
        type: String
    },
    defaultTreeExpandLevel: {
        default: -1,
        type: Number
    },
    isSingleChoice: {
        default: false,
        type: Boolean
    },
    isShowSelect: {
        default: true,
        type: Boolean
    },
    isShowTableCheckbox: {
        default: true,
        type: Boolean
    },
    confirmCloseDialog: {
        default: true,
        type: Boolean
    },
    isShowPagination: {
        default: true,
        type: Boolean
    },
    isShowTableSearch: {
        default: true,
        type: Boolean
    },
    isShowAddButton: {
        default: false,
        type: Boolean
    }
})

const emit = defineEmits([
    'update:isShow',
    'update:selectedContent',
    'update:treeActiveTabName',
    'treeTabChange',
    'nodeClick',
    'search',
    'sizeChange',
    'rowClick',
    'selectionChange',
    'confirm',
    'add',
    'clearRow',
    'open',
    'closed',
    'treeChange',
    'tableRefresh',
    'sortChange'
])

// 状态定义
const initializeRendering = ref(false)
const tableRef = ref(null)
const commonSearchRef = ref(null)
const checkAll = ref(false)
const isIndeterminate = ref(false)
const allSelection = ref([])
const checkboxSelect = ref([])
const checkboxOpt = ref([])
const enhancedTableData = ref([])
const tableCheckAll = ref(false)
const tableIsIndeterminate = ref(false)

const isShowDialog = computed({
    get: () => {
        return props.isShow
    },
    set: (val) => {
        emit('update:isShow', val)
    }
})

// 方法定义
const treeTabChange = (treeActiveTabName) => {
    emit('update:treeActiveTabName', treeActiveTabName)
    emit('treeTabChange', treeActiveTabName)
}

const open = () => {
    // 初始化逻辑
    if (!initializeRendering.value) emit('initializeRendering')
    let allSelection_
    if (props.isSingleChoice) {
        if (
            Object.prototype.toString.call(props.selectedContent) === '[object Object]' &&
            Object.keys(props.selectedContent).length
        ) {
            allSelection_ = [_.cloneDeep(props.selectedContent)] || []
        } else {
            allSelection_ = []
        }
    } else {
        allSelection_ = _.cloneDeep(props.selectedContent) || []
    }

    allSelection.value = allSelection_.map((i) => {
        return { ...i, checked: true }
    })

    console.log(allSelection.value, '999')

    updateCheckboxOpt()

    // 初始化首次打开弹层选中效果,
    if (props.isShowTree && !initializeRendering.value) {
        nextTick((_) => {
            setCurrentKey(props.treeItem?.[props.treeKey] || '')
            expandHandle(true, props.defaultTreeExpandLevel)
        })
    }

    emit('open', initializeRendering.value)
    initializeRendering.value = true
}

const closed = () => {
    // 关闭逻辑
    // 重置打开弹层选中效果,
    nextTick((_) => {
        if (props.isShowTree) {
            setCurrentKey(props.treeItem?.[props.treeKey] || '')
            expandHandle(true, props.defaultTreeExpandLevel)
        }
        // commonSearchRef.value && commonSearchRef.value?.deleteChoose('all', false) // 清空搜索选中
        tableRef.value && tableRef.value?.clearSort() // 用于清空排序条件，数据会恢复成未排序的状态
    })
    emit('closed')
}

const rowClassName = ({ row }) => {
    // 行样式逻辑
    const classArr = []
    if (allSelection.value.some((i) => i[props.selectKey] === row[props.selectKey])) {
        classArr.push('current-row')
    }
    if (row.disabled) {
        classArr.push('disabled-row')
    }
    return classArr.join(' ')
}

const currentChange = (nodeItem) => {
    props.tableParams.pageBean.page = 1
    // 为了避免左侧树勾选的参数用于表格查询中的方式有不确定性，则把修改查询项功能留给父组件自己做
    emit('update:treeItem', nodeItem || {})
    emit('treeChange', nodeItem)
}

const handleSearch = (data) => {
    props.tableParams.pageBean.page = 1
    data.forEach((item) => {
        if (Array.isArray(item.prop) && item.prop.length) {
            item.prop.forEach((prop) => {
                setQueryValue(props.tableParams, prop, item.value)
            })
        } else if (typeof item.prop === 'string') {
            setQueryValue(props.tableParams, item.prop, item.value)
        }
        console.log(props.tableParams.querys)
    })
    console.log(data, props.tableParams.querys)

    emit('tableRefresh', props.tableParams)
}

const handleCurrentChange = (page) => {
    props.tableParams.pageBean.page = page
    emit('tableRefresh', props.tableParams)
}

const handleSizeChange = (pageSize) => {
    props.tableParams.pageBean.pageSize = pageSize
    emit('tableRefresh', props.tableParams)
}

const tableRowClick = (row, status) => {
    tableSelection(row, status)
    updateCheckboxOpt()
}

const tableSelection = (item, status) => {
    if (item.disabled) return
    const tableIndex = enhancedTableData.value.findIndex(
        (i) => i[props.selectKey] === item[props.selectKey]
    )
    const findIndex = allSelection.value.findIndex(
        (i) => i[props.selectKey] === item[props.selectKey]
    )
    if (tableIndex !== -1) enhancedTableData.value[tableIndex].checked = status
    if (status) {
        if (props.isSingleChoice) {
            allSelection.value = [item]
            enhancedTableData.value.forEach((i) => {
                if (i[props.selectKey] !== item[props.selectKey]) i.checked = false
            })
        } else {
            if (findIndex === -1) allSelection.value.push(item)
        }
    } else {
        if (findIndex !== -1) allSelection.value.splice(findIndex, 1)
    }

    tableCheckAll.value = enhancedTableData.value.every((i) => i.checked)
    tableIsIndeterminate.value =
        enhancedTableData.value.some((i) => i.checked) && tableCheckAll.value
}

const checkboxScrollBottom = () => {
    // 滚动到底部逻辑
}

const tableTrScroll = (item) => {
    // 表格滚动逻辑
}

const updateCheckboxOpt = () => {
    // 更新复选框选项逻辑
    checkboxOpt.value = _.cloneDeep(allSelection.value)
    checkboxSelect.value = checkboxOpt.value.map((i) => i[props.selectKey])
    checkAll.value = !!checkboxSelect.value.length
    isIndeterminate.value = false
    checkboxScrollBottom()
}

// 表格全选逻辑
const tableHandleCheckAllChange = (val) => {
    enhancedTableData.value.forEach((i) => tableRowClick(i, val))
    isIndeterminate.value = false
}

// 已选列表
const handleCheckAllChange = (val) => {
    // 处理全选逻辑
    if (val) {
        checkboxSelect.value = checkboxOpt.value.map((i) => i[props.selectKey])
        allSelection.value = checkboxOpt.value
    } else {
        checkboxSelect.value = checkboxOpt.value.flatMap((i) =>
            i.disabled ? i[props.selectKey] : []
        )
        allSelection.value = allSelection.value.flatMap((i) => (i.disabled && i.checked ? i : []))
        isIndeterminate.value = !!checkboxSelect.value.length
    }
    checkboxOpt.value.forEach((i) => {
        const findItem = enhancedTableData.value.find(
            (_i) => _i[props.selectKey] === i[props.selectKey]
        )
        if (!findItem) return
        tableSelection(findItem, val)
    })
}

const handleCheckedChange = (status, item, value) => {
    // 处理选中变化逻辑
    tableTrScroll(item)
    tableSelection(item, status)
    let checkedCount = value.length
    checkAll.value = checkedCount === checkboxOpt.value.length
    isIndeterminate.value = checkedCount > 0 && checkedCount < checkboxOpt.value.length
}

const confirm = () => {
    let selectedContent = allSelection.value.filter((i) => {
        return checkboxSelect.value.some((selectKey) => selectKey === i[props.selectKey])
    })
    selectedContent = props.isSingleChoice ? selectedContent[0] || {} : selectedContent
    emit('update:selectedContent', selectedContent)
    emit('confirm', selectedContent)
    if (props.confirmCloseDialog) {
        isShowDialog.value = false
        emit('update:isShow', false)
    }
}

const handleAdd = () => {
    emit('add')
}

const handleClearRow = (row, status) => {
    tableRowClick(row, status)
}

// 生命周期
onMounted(() => {
    window.addEventListener('resize', handleResize)
})

onBeforeUnmount(() => {
    window.removeEventListener('resize', handleResize)
})

const handleResize = () => {
    // 处理窗口大小变化逻辑
}

// 监听器
watch(
    () => props.treeData,
    (newVal) => {
        // 树数据变化逻辑
        if (!props.isShowTree) return
        nextTick((_) => {
            setCurrentKey(props.treeItem?.[props.treeKey] || '')
            expandHandle(true, props.defaultTreeExpandLevel)
        })
    },
    {
        immediate: true
    }
)

watch(
    () => props.tableData,
    (newVal) => {
        // 表格数据变化逻辑
        enhancedTableData.value = newVal.map((item) => ({
            ...item,
            checked: allSelection.value.some((i) => i[props.selectKey] === item[props.selectKey]),
            disabled:
                allSelection.value.find((i) => i[props.selectKey] === item[props.selectKey])
                    ?.disabled ?? false
        }))
    },
    {
        immediate: true,
        deep: true
    }
)

watch(
    () => props.selectedContent,
    (newVal) => {
        // 选中内容变化逻辑
        let allSelection
        if (props.isSingleChoice) {
            if (
                Object.prototype.toString.call(newVal) === '[object Object]' &&
                Object.keys(newVal).length
            ) {
                allSelection = [_.cloneDeep(newVal)] || []
            } else {
                allSelection = []
            }
        } else {
            allSelection = _.cloneDeep(newVal) || []
        }
        allSelection.value = allSelection.map((i) => ({
            ...i,
            checked: true
        }))
        updateCheckboxOpt()
    },
    { immediate: true, deep: true }
)

const treeSideRef = ref(null)

const expandHandle = (type, level = -1) => {
    treeSideRef.value && treeSideRef.value.expandHandle(type, level)
}
const setCheckedNodes = (nodes) => {
    treeSideRef.value && treeSideRef.value.setCheckedNodes(nodes)
}

const setCurrentKey = (key) => {
    treeSideRef.value && treeSideRef.value.setCurrentKey(key)
}
defineExpose({
    setCheckedNodes,
    setCurrentKey,
    expandHandle
})
</script>

<style lang="scss" scoped>
.super-table-selector-dialog {
    width: 100%;
    display: flex;
    column-gap: 16px;
    min-height: 50vh;

    .tree-module {
        width: 340px;
        height: 100%;
        border-radius: 8px;
        overflow: hidden;
        background-color: var(--theme-system-module-1);
    }

    .table-module {
        width: 0;
        height: 100%;
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 10px;

        .search-content {
            border-radius: 8px;
            padding: 16px;
            background-color: var(--theme-system-module-1);
            display: flex;
            gap: 12px;
        }

        .table-content {
            flex: 1;
            border-radius: 8px;
            padding: 16px;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            background-color: var(--theme-system-module-1);
            gap: 20px;
            box-sizing: border-box;
            overflow: hidden;

            :deep(.el-table) {
                .el-table__row {
                    cursor: pointer;

                    &.current-row {
                        cursor: pointer;

                        .el-table__cell {
                            background-color: var(--theme-box-color-3) !important;

                            .cell {
                                color: $system-hover-active-text;
                            }
                        }
                    }

                    &.disabled-row {
                        cursor: no-drop;

                        .el-table__cell {
                            background-color: var(--theme-system-disabled-bg) !important;

                            .cell {
                                color: $color-text-placeholder;
                            }
                        }
                    }
                }
            }
        }

        .table-content-inner {
            flex: 1;
            overflow: hidden;
        }

        .table-content-bottom {
            display: flex;
            justify-content: space-between;
            align-items: flex-end;
        }
    }

    .select-module {
        width: 280px;
        height: 100%;
        display: flex;
        flex-direction: column;
        border-radius: 8px;
        overflow: hidden;
        background-color: var(--theme-system-module-1);

        .select-title {
            padding: 12px 16px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            background-color: $system-module-color2;
            color: $color-white;
            border-bottom: 1px solid $system-border-color3;

            .title-box-left {
                display: flex;
                align-items: center;
                column-gap: 9px;
                font-size: 16px;
                color: $color-white;

                .el-checkbox {
                    margin-top: 2px;
                }
            }

            .title-box-right {
                font-size: 15px;
                color: $color-text-placeholder;
            }
        }

        .select-content {
            flex: 1;
            overflow-y: auto;
            padding: 8px;

            .select-item {
                display: flex;
                align-items: center;
                height: 36px !important;
                margin-right: 0;
                padding: 8px;
                margin-bottom: 8px;
                background-color: transparent;
                border: 1px solid $system-border-color3;
                border-radius: 4px;
                box-sizing: border-box;

                :deep(.el-checkbox__label) {
                    flex: 1;
                    overflow: hidden;

                    span {
                        display: block;
                        font-size: 14px;
                        overflow: hidden;
                        white-space: nowrap;
                        text-overflow: ellipsis;
                    }
                }
            }

            .select-item.active {
                background-color: var(--theme-system-bg);
                border: 1px solid $system-border-color1;
            }
        }

        .select-footer {
            padding: 12px;
            display: flex;
            justify-content: center;
            gap: 12px;
            background-color: $system-module-color2;
        }
    }
}
</style>
