<template>
    <div class="default-main pd10">
        <div class="elButton">
            <el-button type="primary" icon="el-icon-Check" @click="onSubmit">保存</el-button>
            <back-component />
        </div>
        <div style="display: flex">
            <el-tabs v-model="tableName" v-if="treeComponents.length > 0" type="border-card" @tab-change="changeTab">
                <el-tab-pane v-for="item in treeComponents" :key="item.name" :label="item.name" :name="item.name">
                    <el-tabs v-model="tableName1" tab-position="top">
                        <el-tab-pane v-for="k in item?.children" :key="k.name" :label="k.name" :name="k.name">
                            <div :style="indicatorHeight" style="overflow-y: auto; overflow-x: hidden">
                                <el-row :gutter="10" class="pl5 pr5 pt5" style="width: 520px">
                                    <el-col :span="8" v-for="component in k.children" :key="component.id" class="mb10">
                                        <el-card
                                            class="box-card"
                                            shadow="hover"
                                            @drag="drag(component)"
                                            @dragend="dragEnd(component)"
                                        >
                                            <div slot="header" class="clearfix">
                                                <span style="display: flex; align-items: center">
                                                    {{ component.name }}
                                                </span>
                                            </div>
                                            <img v-if="component.image" :src="component.image" class="image xiaoshou" />
                                        </el-card>
                                    </el-col>
                                </el-row>
                            </div>
                        </el-tab-pane>
                    </el-tabs>
                </el-tab-pane>
            </el-tabs>
            <el-empty v-else description="当前角色未绑定系统" style="width: 520px" />
            <div style="flex: 1" ref="wrapper" class="ml10">
                <el-tabs type="border-card" class="mb10">
                    <el-tab-pane label="基础信息">
                        <el-form ref="formRef" inline :rules="rules" :model="form" label-width="auto" class="form-four">
                            <el-form-item label="页面名称" prop="pageName">
                                <el-input maxlength="32" show-word-limit 
                                    style="width: 100%"
                                    
                                    
                                    v-model.trim="form.pageName"
                                    placeholder="请输入页面名称"
                                ></el-input>
                            </el-form-item>
                            <el-form-item label="图标">
                                <IconSelector v-model.trim="form.icon" placeholder="请选择图标" />
                            </el-form-item>
                            <el-form-item label="页面排序" prop="sort">
                                <el-input-number
                                    style="width: 100%"
                                    v-model.trim="form.sort"
                                    :min="0"
                                    :max="10000"
                                    :step="1"
                                />
                            </el-form-item>

                            <el-form-item label="是否激活">
                                <el-switch
                                    v-model="form.state"
                                    inline-prompt
                                    width="60px"
                                    :disabled="form.pagePath == 'dashboard/index'"
                                    :active-value="1"
                                    :inactive-value="0"
                                    active-text="是  "
                                    inactive-text="否  "
                                />
                            </el-form-item>
                            <el-form-item label="是否全局" v-if="hasAdmin">
                                <el-switch
                                    v-model="form.scope"
                                    inline-prompt
                                    width="60px"
                                    :active-value="1"
                                    :inactive-value="0"
                                    :disabled="form.pagePath == 'dashboard/index'"
                                    active-text="是  "
                                    inactive-text="否  "
                                />
                            </el-form-item>
                            <el-form-item label="备注" class="top">
                                <el-input  show-word-limit 
                                    maxlength="300"
                                    
                                    style="width: 100%"
                                    type="textarea"
                                    :rows="1"
                                    placeholder="请输入内容"
                                    v-model.trim="form.remark"
                                ></el-input>
                            </el-form-item>
                            <el-form-item></el-form-item>
                        </el-form>
                    </el-tab-pane>
                </el-tabs>
                <div ref="PaneRef">
                    <el-tabs type="border-card">
                        <el-tab-pane label="画布" :style="height">
                            <GridLayout
                                class="GridLayout"
                                ref="gridLayout"
                                v-model:layout="layout"
                                style="width: 100%"
                                :style="{ height: GridHeight + 'px' }"
                                :row-height="rowHeight"
                                :col-num="12"
                                prevent-collision
                                :is-bounded="true"
                                :vertical-compact="false"
                            >
                                <template #item="{ item }">
                                    <div class="imgBox">
                                        <div class="textName">{{ item.name }}</div>

                                        <img
                                            :src="getImg(item.path)"
                                            :style="{
                                                height:
                                                    item.h * rowHeight -
                                                    (item.h == 1
                                                        ? 30
                                                        : item.h == 2
                                                        ? 20
                                                        : item.h == 3
                                                        ? 10
                                                        : item.h == 4
                                                        ? -0
                                                        : item.h == 5
                                                        ? -10
                                                        : -20) +
                                                    'px'
                                            }"
                                        />

                                        <CloseBold class="remove" @click="removeItem(item.i)" />
                                    </div>
                                    <!-- <span class="text">{{ `${item?.name}` }}</span>
                            -->
                                </template>
                            </GridLayout>
                        </el-tab-pane>
                    </el-tabs>
                </div>
            </div>
        </div>
    </div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import BackComponent from '@/components/icon/back/index.vue'
import { mainHeight } from '@/utils/layout'
import type { CollapseIconPositionType } from 'element-plus'
import IconSelector from '@/components/baInput/components/iconSelector.vue'
import { componentTree } from '@/api/user-boot/user'
import { GridLayout, GridItem } from 'grid-layout-plus'
import { throttle } from 'lodash-es'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Tools, CloseBold } from '@element-plus/icons-vue'
import { addDashboard, updateDashboard, queryById } from '@/api/system-boot/csstatisticalset'
import html2canvas from 'html2canvas'
import { useRoute } from 'vue-router'
import { getMenu } from '@/utils/router'
import { useAdminInfo } from '@/stores/adminInfo'
const tableName = ref('')
const tableName1 = ref('')
import { useNavTabs } from '@/stores/navTabs'
import { getSystemByRoleId } from '@/api/user-boot/roleFuction'
import { forEach } from 'jszip'
import { id } from 'element-plus/es/locale'
// defineOptions({
//     name: 'cockpit/popup'
// })
const adminInfo = useAdminInfo()
const hasAdmin =
    adminInfo.roleCode.some(item => item.includes('operation_manager') || item.includes('root')) ||
    adminInfo.userType == 1

const { go } = useRouter()
const navTabs = useNavTabs()
const { query } = useRoute()
const router = useRouter()
const height = mainHeight(265)
const indicatorHeight = mainHeight(180)
const rowHeight = ref(0)
const pageList: any = ref([])
const GridHeight = ref(0)
const position = ref<CollapseIconPositionType>('left')
const form: any = reactive({
    pageName: '',
    thumbnail: '',
    containerConfig: [],
    sort: '100',
    id: '',
    state: 1,
    scope: 0,
    icon: '',
    pagePath: '',
    remark: '',
    routeName: '/src/views/pqs/cockpit/homePage/index.vue'
})
const activeNames = ref([])
const activeNames1 = ref([])
const rules = {
    pageName: [{ required: true, message: '请输入页面名称', trigger: 'blur' }],
    projectIds: [{ required: true, message: '请选择工程页面', trigger: 'change' }],
    sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
const formRef = ref()
const layout: any = ref([
    // { x: 0, y: 0, w: 4, h: 2, i: '0', name: '', path: '' },
    // { x: 4, y: 0, w: 4, h: 2, i: '1', name: '', path: '' },
    // { x: 8, y: 0, w: 4, h: 2, i: '2', name: '', path: '' },
    // { x: 0, y: 0, w: 4, h: 2, i: '3', name: '', path: '' },
    // { x: 4, y: 0, w: 4, h: 2, i: '4', name: '', path: '' },
    // { x: 8, y: 0, w: 4, h: 2, i: '5', name: '', path: '' },
    // { x: 0, y: 0, w: 4, h: 2, i: '6', name: '', path: '' },
    // { x: 4, y: 0, w: 4, h: 2, i: '7', name: '', path: '' },
    // { x: 8, y: 0, w: 4, h: 2, i: '8', name: '', path: '' }
])
const treeComponents: any = ref([]) //组件树
const treeComponentsCopy: any = ref([]) //组件树
const info = async () => {
    pageList.value = router
        .getRoutes()
        .filter(item => item?.meta?.component == '/src/views/pqs/cockpit/homePage/index.vue')
        .map(item => {
            return { name: item?.meta?.title, path: item?.meta?.path }
        })

    activeNames.value = []
    activeNames1.value = []

    let systemList: any[] = []
    await adminInfo.roleList.forEach((item: any) => {
        getSystemByRoleId({ id: item }).then(res => {
            systemList = [...new Set([...systemList, ...res.data.systemIds])]
        })
    })

    await componentTree().then(res => {
        let list = res.data.filter(item => systemList.includes(item.id))
        treeComponents.value = list
        tableName.value = tableName.value == '' ? treeComponents.value[0].name : tableName.value
        tableName1.value = tableName1.value == '' ? treeComponents.value[0].children[0].name : tableName1.value
        activeNames.value = treeComponents.value.map(item => item.id)
        list.forEach(item => {
            item.children.forEach(k => {
                activeNames1.value.push(k.id)
            })
        })
        treeComponentsCopy.value = tree2List(JSON.parse(JSON.stringify(list)), 0)
    })

    if (query.id) {
        queryById({ id: query.id }).then(res => {
            layout.value = JSON.parse(res.data.containerConfig)
            form.pageName = res.data.pageName
            form.pagePath = query.path || res.data.pagePath
            form.sort = res.data.sort
            form.remark = res.data.remark
            form.id = res.data.id
            form.state = res.data.state
            form.scope = res.data.userId == 0 ? 1 : 0
            form.icon = res.data.icon
        })
    } else {
        form.pagePath = query.path
    }
}

// 扁平化树
const tree2List = (list: any, id: any) => {
    //存储结果的数组
    let arr: any = []
    // 遍历 tree 数组
    list.forEach((item: any) => {
        item.uPid = id
        item.uId = Math.random() * 1000
        // 判断item是否存在children
        if (!item.children) return arr.push(item)
        // 函数递归，对children数组进行tree2List的转换
        const children = tree2List(item.children, item.uId)
        // 删除item的children属性
        delete item.children
        // 把item和children数组添加至结果数组
        //..children: 意思是把children数组展开
        arr.push(item, ...children)
    })
    // 返回结果数组
    return arr
}
const changeTab = (e: any) => {
    tableName1.value = treeComponents.filter(item => item.name == e)[0].children[0].name
}
// 删除拖拽
const removeItem = (id: string) => {
    const index = layout.value.findIndex(item => item.i === id)

    if (index > -1) {
        layout.value.splice(index, 1)
    }
}
const wrapper = ref<HTMLElement>()
const PaneRef = ref<HTMLElement>()
const gridLayout = ref<InstanceType<typeof GridLayout>>()

const mouseAt = { x: -1, y: -1 }

function syncMousePosition(event: MouseEvent) {
    mouseAt.x = event.clientX
    mouseAt.y = event.clientY
}

const dropId = 'drop'
const dragItem = { x: -1, y: -1, w: 4, h: 2, i: '' }

const drag = throttle(row => {
    // console.log("🚀 ~ drag ~ row:", row)

    const parentRect = wrapper.value?.getBoundingClientRect()

    if (!parentRect || !gridLayout.value) return

    const mouseInGrid =
        mouseAt.x > parentRect.left &&
        mouseAt.x < parentRect.right &&
        mouseAt.y > parentRect.top &&
        mouseAt.y < parentRect.bottom

    if (mouseInGrid && !layout.value.find(item => item.i === dropId)) {
        layout.value.push({
            x: (layout.value.length * 2) % 6,
            y: layout.value.length + 6, // puts it at the bottom
            w: 4,
            h: 2,
            i: dropId
        })
    }

    const index = layout.value.findIndex(item => item.i === dropId)

    if (index !== -1) {
        const item = gridLayout.value.getItem(dropId)

        if (!item) return

        try {
            item.wrapper.style.display = 'none'
        } catch (e) {}

        Object.assign(item.state, {
            top: mouseAt.y - parentRect.top - 300,
            left: mouseAt.x - parentRect.left - 180
        })

        const newPos = item.calcXY(mouseAt.y - parentRect.top - 300, mouseAt.x - parentRect.left - 180)

        if (mouseInGrid) {
            gridLayout.value.dragEvent('dragstart', dropId, newPos.x, newPos.y, dragItem.h, dragItem.w)
            dragItem.i = String(index)
            dragItem.x = layout.value[index].x
            dragItem.y = layout.value[index].y
        } else {
            gridLayout.value.dragEvent('dragend', dropId, newPos.x, newPos.y, dragItem.h, dragItem.w)
            layout.value = layout.value.filter(item => item.i !== dropId)
        }
    }
})

function dragEnd(row: any) {
    const parentRect = wrapper.value?.getBoundingClientRect()

    if (!parentRect || !gridLayout.value) return

    const mouseInGrid =
        mouseAt.x > parentRect.left &&
        mouseAt.x < parentRect.right &&
        mouseAt.y > parentRect.top &&
        mouseAt.y < parentRect.bottom

    if (mouseInGrid) {
        gridLayout.value.dragEvent('dragend', dropId, dragItem.x, dragItem.y, dragItem.h, dragItem.w)
        layout.value = layout.value.filter(item => item.i !== dropId)
    } else {
        return
    }

    layout.value.push({
        x: dragItem.x,
        y: dragItem.y,
        w: dragItem.w,
        h: dragItem.h,
        i: Math.random(), //dragItem.i,
        name: row.name,
        path: row.path,
        icon: row.icon,
        timeKeys: row.timeKeys
    })
    gridLayout.value.dragEvent('dragend', dragItem.i, dragItem.x, dragItem.y, dragItem.h, dragItem.w)
    const item = gridLayout.value.getItem(dropId)
    if (!item) return
    try {
        item.wrapper.style.display = ''
    } catch (e) {}
}
// 保存
const onSubmit = () => {
    layout.value = layout.value.filter(item => {
        return item.y <= 6 && item.x <= 12
    })

    if (layout.value.length == 0) {
        return ElMessage.warning('页面设计不能为空!')
    }
    let repeat = findDuplicateNames(layout.value) || []
    if (repeat.length > 0) {
        return ElMessage.warning(repeat.join('、') + ' 组件重复,请删除重复组件!')
    }

    // const maxValue = Math.max(...layout.value.map(item => item.y + item.h))
    // if (maxValue > 6) {
    //     return ElMessage.warning('组件不能超出当前容器!')
    // }

    formRef.value.validate(async (valid: boolean) => {
        let url = ''
        // await html2canvas(document.querySelector('.GridLayout'), {
        //     useCORS: true
        // }).then(canvas => {
        //     url = canvas.toDataURL('image/png')
        // })
        form.pagePath = form.pagePath || ''

        if (valid) {
            if (form.id == '') {
                await addDashboard({
                    ...form,
                    containerConfig: JSON.stringify(layout.value),
                    thumbnail: url,
                    userId: form.scope == 1 ? '0' : adminInfo.id
                }).then(async (res: any) => {
                    ElMessage.success('新增页面成功!')
                    // go(-1)
                    await getMenu()
                })
            } else {
                await updateDashboard({
                    ...form,
                    containerConfig: JSON.stringify(layout.value),
                    thumbnail: url,
                    userId: form.scope == 1 ? '0' : adminInfo.id
                }).then(async (res: any) => {
                    ElMessage.success('修改页面成功!')
                    // go(-1)
                    await getMenu()
                })
            }
            await setTimeout(() => {
                router.push({
                    name: form.state == 1 ? form.pagePath : 'dashboard/index'
                })
                navTabs.refresh()
            }, 500)
        }
    })
}
// 查找重复的name
// const findDuplicateNames = (arr: any) => {
//     // 用于记录每个name出现的次数
//     const nameCount = {}
//     // 用于存储重复的name
//     const duplicates = []

//     // 遍历数组统计每个name的出现次数
//     arr.forEach(item => {
//         const name = item.name
//         if (nameCount[name]) {
//             nameCount[name]++
//         } else {
//             nameCount[name] = 1
//         }
//     })

//     // 筛选出出现次数大于1的name
//     for (const name in nameCount) {
//         if (nameCount[name] > 1) {
//             duplicates.push(name)
//         }
//     }

//     return duplicates
// }
// 查找重复的path，并返回对应的重复name
const findDuplicateNames = (arr: any) => {
    // 用于记录每个path出现的次数
    const pathCount: any = {}
    // 用于存储path对应的name（避免重复存储）
    const pathToNameMap = new Map()
    // 用于存储重复path对应的name
    const duplicates = []

    // 遍历数组统计每个path的出现次数，并记录path和name的映射
    arr.forEach(item => {
        const path = item.path
        const name = item.name

        // 记录path和name的对应关系（只存第一次的，避免覆盖）
        if (!pathToNameMap.has(path)) {
            pathToNameMap.set(path, name)
        }

        // 统计path出现次数
        if (pathCount[path]) {
            pathCount[path]++
        } else {
            pathCount[path] = 1
        }
    })

    // 筛选出出现次数大于1的path，并获取对应的name
    for (const path in pathCount) {
        if (pathCount[path] > 1) {
            const name = pathToNameMap.get(path)
            // 避免重复添加相同的name（如果多个重复path对应同一个name）
            if (!duplicates.includes(name)) {
                duplicates.push(name)
            }
        }
    }

    return duplicates
}

const getImg = throttle((path: string) => {
    if (path != undefined) return treeComponentsCopy.value.filter(item => item.path == path)[0]?.image
})

onMounted(() => {
    info()
    nextTick(() => {
        GridHeight.value = PaneRef.value?.offsetHeight - 60 //wrapper.value?.offsetWidth / 1.77777
        setTimeout(() => {
        }, 500)
        rowHeight.value = GridHeight.value / 6 - 11.5
        document.documentElement.style.setProperty('--GridLayout-height', rowHeight.value + 10 + 'px')
        document.addEventListener('dragover', syncMousePosition)
    })
})

onBeforeUnmount(() => {
    document.removeEventListener('dragover', syncMousePosition)
})
// onMounted(() => {

//     // document.addEventListener('dragover', syncMousePosition)
// })
</script>
<style lang="scss" scoped>
.form-four {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    .el-form-item {
        display: flex;
        // flex: 1;
        // align-items: center;
        width: 32%;
        .el-form-item__content {
            width: 100%;
            flex: 1;
            .el-select,
            .el-cascader,
            .el-input__inner,
            .el-date-editor {
                width: 100%;
            }
        }
    }
}
:deep(.el-card__body) {
    padding: 20px 20px 12px;
}
.Box {
    display: flex;
    flex-wrap: wrap;
}
.imgBox {
    // padding: 10px;
    display: flex;
    flex-direction: column;

    box-shadow: var(--el-box-shadow-light);
    --el-card-border-color: var(--el-border-color-light);
    --el-card-border-radius: 4px;
    --el-card-padding: 20px;
    --el-card-bg-color: var(--el-fill-color-blank);
    background-color: var(--el-card-bg-color);
    border: 1px solid var(--el-card-border-color);
    border-radius: var(--el-card-border-radius);
    color: var(--el-text-color-primary);
    overflow: hidden;
    transition: var(--el-transition-duration) 0.3s;
    .textName {
        padding: 2px 5px;
        background-color: var(--el-color-primary);
        color: #fff;
    }
    user-select: none; /* 标准属性 */
    -webkit-user-select: none; /* Chrome/Safari */
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* IE/Edge */
}
.vgl-layout {
    background-color: #eee;
}
:deep(.el-input-group) {
    width: 90%;
}
.remove {
    position: absolute;
    top: 5px;
    right: 2px;
    width: 16px;
    color: #fff;
    cursor: pointer;
}

.vgl-layout::before {
    position: absolute;
    width: calc(100% - 5px);
    height: calc(100% - 5px);
    margin: 5px;
    content: '';
    background-image: linear-gradient(to right, lightgrey 1px, transparent 1px),
        linear-gradient(to bottom, lightgrey 1px, transparent 1px);
    background-repeat: repeat;
    background-size: calc(calc(100% - 5px) / 12) var(--GridLayout-height);
}

:deep(.vgl-item:not(.vgl-item--placeholder)) {
    background-color: #fff;
    border: 1px solid black;
}
:deep(.el-form--inline .el-form-item) {
    margin-right: 0px;
}
:deep(.el-card__header) {
    padding: 13px 20px;
    height: 44px;
}
:deep(.el-card__body) {
    padding: 10px;
}
.xiaoshou {
    cursor: pointer;
}
.image {
    display: block;
    width: 100%;
    height: 100px;
}
.box-card {
    width: 100%;
    // border: 1px solid #000;
    box-shadow: var(--el-box-shadow-light);
}
.elButton {
    position: absolute;
    right: 10px;
    top: 13px;
    z-index: 1;
}

:deep(.vgl-item__resizer) {
    width: 20px;
    height: 20px;
    background: linear-gradient(45deg, var(--el-color-primary));

    clip-path: polygon(100% 0, 100% 100%, 0 100%);
    /* 可选：添加阴影增强视觉效果 */
    box-shadow: 2px 2px 8px var(--el-color-primary);
}
</style>
