<template>
    <!-- 预置位配置 -->
    <DialogModal
        @onHandleCloseModal="onHandleCloseModal"
        :modalTitle="modalTitle"
        :width="`90vw`"
        style="position: relative"
    >
        <!-- 平面图操作区域 -->
        <div
            class="plane-map-container"
            ref="planeMapContainer"
            :class="{ 'can-drag': canDrag() }"
            :style="{ height: INITIAL_HEIGHT + 'px' }"
            @mousemove="handleMouseMove"
        >
            <svg
                ref="svgMapRef"
                class="svg-map-container"
                :width="svgWidth"
                :height="svgHeight"
                @wheel.passive="handleWheel"
                @click="handleMapClick"
                :style="{ transform: `translate(${offsetX}px, ${offsetY}px)` }"
            >
                <!-- 图片，宽高 100% 跟随 SVG -->
                <image
                    width="100%"
                    height="100%"
                    :href="mapInfo.mapBase64"
                    preserveAspectRatio="none"
                />

                <!-- 标记的点位 -->
                <circle
                    v-for="(point, index) in devicePoints"
                    :key="index"
                    :cx="point.markerX * scale + offsetX / scale"
                    :cy="point.markerY1 * scale + offsetY / scale"
                    r="8"
                    fill="red"
                    @click="handlePointClick(point, index)"
                    :ref="(el) => setItemRef(el, index)"
                    @contextmenu.prevent="handlePointRightClick($event, point, index)"
                />
            </svg>

            <div v-if="showTooltip && mousePosition" class="coord-tooltip" :style="tooltipStyle">
                <!-- 数据向下取整 -->
                X: {{ Math.floor(mousePosition.x) * 2 }}, Y: {{ Math.floor(mousePosition.y) * 2 }}
            </div>

            <div v-if="showContextMenu" class="context-menu" :style="contextMenuStyle" @click.stop>
                <div class="menu-item" @click="handleModifyPoint">修改</div>
                <div class="menu-item" @click="handleDeletePoint">删除</div>
            </div>

            <!-- 操作按钮 -->
            <n-flex vertical class="operation-container">
                <n-button strong size="small" color="#5c96fa" @click="zoomIn($event)">
                    <template #icon>
                        <NIcon color="#fff">
                            <AddCircleOutline />
                        </NIcon>
                    </template>
                </n-button>
                <n-button strong size="small" color="#5c96fa" @click="zoomOut($event)">
                    <template #icon>
                        <NIcon color="#fff">
                            <RemoveCircleOutline />
                        </NIcon>
                    </template>
                </n-button>
            </n-flex>
        </div>
    </DialogModal>
</template>

<script setup>
import DialogModal from '@/components/DialogModal/index.vue'
import { ref, onMounted, watch, onBeforeUnmount } from 'vue'
import { NIcon } from 'naive-ui'
import { throttle } from 'lodash'
import { AddCircleOutline, RemoveCircleOutline } from '@vicons/ionicons5'
import { getRobotDeviceListFn, getRobotMapInfoFn } from '@/utils/getRobotInfo'
import { getMarkerListAllApi } from '@/api/home'

const modalTitle = ref('预置位配置') // 模态框标题
const mousePosition = ref(null) // 鼠标位置
const devicePoints = ref([]) // 设备点位
const isPointClickStatus = ref(true) // 是否点击点位
const mapInfo = ref({}) // 地图信息

// SVG 初始尺寸
const INITIAL_WIDTH = ref(0)
const INITIAL_HEIGHT = ref(0)

// SVG 动态宽高
const svgWidth = ref(INITIAL_WIDTH.value)
const svgHeight = ref(INITIAL_HEIGHT.value)

// 拖拽相关状态
const isDragging = ref(false) // 是否拖拽
const offsetX = ref(0) // 偏移量X
const offsetY = ref(0) // 偏移量Y
const startX = ref(0) // 起始X
const startY = ref(0) // 起始Y
const maxOffsetX1 = ref(0) // 最大偏移量X
const maxOffsetY1 = ref(0) // 最大偏移量Y

// 缩放比例
const scale = ref(1.0)

// 缩放配置
const MIN_SCALE = 0.5 // 最小缩放比例
const MAX_SCALE = 3 // 最大缩放比例
const SCALE_STEP = 0.1 // 每次滚轮的缩放步长

// 右键菜单相关状态
const showContextMenu = ref(false) // 是否显示右键菜单
const contextMenuStyle = ref({}) // 右键菜单样式
const selectedPointIndex = ref(-1) // 选中的点位索引

// 容器尺寸跟踪
const planeMapContainer = ref(null) // 容器引用
const svgMapRef = ref(null) // svg引用
const tooltipStyle = ref({}) // 提示框样式

const itemRefs = ref([]) // 标记点位引用
const emits = defineEmits(['onHandleCloseModal', 'onHandleAddMarker']) // 定义 emits

// 定义props
const props = defineProps({
    markerInfoNew: {
        type: Object,
        default: () => {},
    },
})

// 设置标记点位引用
const setItemRef = (el, index) => {
    if (el) {
        itemRefs.value[index] = el
    }
}

// 缩放时调整偏移量（以鼠标位置为中心）
const adjustOffsetOnZoom = (e, newScale) => {
    const container = planeMapContainer.value
    if (!container) return

    const containerRect = container.getBoundingClientRect()
    const mouseX = e ? e.clientX - containerRect.left : containerRect.width / 2
    const mouseY = e ? e.clientY - containerRect.top : containerRect.height / 2

    // 计算鼠标在内容中的相对位置（基于当前缩放和偏移）
    const contentX = (mouseX - offsetX.value) / scale.value
    const contentY = (mouseY - offsetY.value) / scale.value

    // 更新偏移量（保持鼠标指向的内容位置不变）
    offsetX.value = mouseX - contentX * newScale
    offsetY.value = mouseY - contentY * newScale

    enforceBoundaries() // 确保修正后不越界
}

// 缩放
const zoom = (direction, e = { clientX: 0, clientY: 0 }) => {
    const delta = direction === 'in' ? SCALE_STEP : -SCALE_STEP
    const newScale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, scale.value + delta))

    if (newScale !== scale.value) {
        const oldScale = scale.value
        scale.value = newScale
        updateSvgSize() // 内部已按比例修正偏移量
        adjustOffsetOnZoom(e, newScale) // 进一步以鼠标为中心修正
    }
}

// 放大
const zoomIn = (e) => zoom('in', e)

// 缩小
const zoomOut = (e) => zoom('out', e)

// 滚轮缩放
const handleWheel = (e) => {
    requestAnimationFrame(() => {
        e.preventDefault() // 延迟阻止默认行为
        zoom(e.deltaY > 0 ? 'out' : 'in', e)
    })
}

// 更新 SVG 尺寸
const updateSvgSize = () => {
    const oldScale = scale.value
    svgWidth.value = INITIAL_WIDTH.value * scale.value
    svgHeight.value = INITIAL_HEIGHT.value * scale.value

    // 按比例修正偏移量（保持视觉连续性）
    if (oldScale !== 0) {
        offsetX.value = (offsetX.value / oldScale) * scale.value
        offsetY.value = (offsetY.value / oldScale) * scale.value
    }

    // 确保修正后不越界
    enforceBoundaries()
}

// 确保修正后不越界
const enforceBoundaries = () => {
    const { maxOffsetX, maxOffsetY } = getMaxOffset()

    // 限制偏移量
    offsetX.value = Math.min(0, Math.max(-maxOffsetX, offsetX.value))
    offsetY.value = Math.min(0, Math.max(-maxOffsetY, offsetY.value))

    // 确保鼠标坐标不会越界（二次保护）
    if (mousePosition.value) {
        mousePosition.value = {
            x: Math.max(0, Math.min(svgWidth.value / scale.value, mousePosition.value.x)),
            y: Math.max(0, Math.min(svgHeight.value / scale.value, mousePosition.value.y)),
        }
    }
}

// 开始拖拽
const startDrag = (e) => {
    if (!canDrag()) return // 如果不需要拖拽，直接返回
    isDragging.value = true
    startX.value = e.clientX - offsetX.value
    startY.value = e.clientY - offsetY.value
    document.addEventListener('mousemove', handleDrag)
    document.addEventListener('mouseup', stopDrag)
}

// 处理拖拽
const handleDrag = (e) => {
    if (!isDragging.value) return

    const { maxOffsetX, maxOffsetY } = getMaxOffset()

    // 计算新偏移量，并限制范围
    let newOffsetX = e.clientX - startX.value
    let newOffsetY = e.clientY - startY.value

    maxOffsetX1.value = maxOffsetX
    maxOffsetY1.value = maxOffsetY

    // 限制 X 轴范围（左边界和右边界）
    newOffsetX = Math.min(0, newOffsetX) // 不能向右移动（左边界）
    newOffsetX = Math.max(-maxOffsetX, newOffsetX) // 不能向左超出（右边界）

    // 限制 Y 轴范围（上边界和下边界）
    newOffsetY = Math.min(0, newOffsetY) // 不能向下移动（上边界）
    newOffsetY = Math.max(-maxOffsetY, newOffsetY) // 不能向上超出（下边界）

    offsetX.value = newOffsetX
    offsetY.value = newOffsetY

    // 强制更新坐标显示
    if (showTooltip.value) {
        mousePosition.value = getLogicalPosition(e.clientX, e.clientY)
    }
}

// 停止拖拽
const stopDrag = () => {
    isDragging.value = false
    isPointClickStatus.value = true
    document.removeEventListener('mousemove', handleDrag)
    document.removeEventListener('mouseup', stopDrag)
}

// 是否可以拖拽
const canDrag = () => {
    const parentWidth = planeMapContainer.value?.clientWidth || 0
    const parentHeight = planeMapContainer.value?.clientHeight || 0
    return svgWidth.value > parentWidth || svgHeight.value > parentHeight
}

// 计算最大可移动偏移量（限制拖拽边界）
const getMaxOffset = () => {
    const parentWidth = planeMapContainer.value?.clientWidth || 0
    const parentHeight = planeMapContainer.value?.clientHeight || 0
    return {
        maxOffsetX: Math.max(0, svgWidth.value - parentWidth), // 右边界
        maxOffsetY: Math.max(0, svgHeight.value - parentHeight), // 下边界
    }
}

// 获取逻辑坐标
const getLogicalPosition = (clientX, clientY) => {
    const svgRect = svgMapRef.value.getBoundingClientRect()

    // 计算相对于SVG内容的逻辑坐标（考虑缩放和偏移）
    const logicalX = (clientX - svgRect.left - offsetX.value) / scale.value
    // Y坐标需要翻转，因为原点在左下角
    const logicalY =
        svgHeight.value / scale.value - (clientY - svgRect.top - offsetY.value) / scale.value

    const logicalY1 = (clientY - svgRect.top - offsetY.value) / scale.value

    return {
        x: Math.max(0, Math.min(INITIAL_WIDTH.value, logicalX)),
        y: Math.max(0, Math.min(INITIAL_HEIGHT.value, logicalY)),
        y1: Math.max(0, Math.min(INITIAL_HEIGHT.value, logicalY1)),
    }
}

// 鼠标移动事件
const showTooltip = ref(false)

// 鼠标移动事件
const handleMouseMove = throttle((e) => {
    if (!svgMapRef.value) return
    // 检查鼠标是否在SVG内
    const svgRect = svgMapRef.value.getBoundingClientRect()
    const isInside =
        e.clientX >= svgRect.left &&
        e.clientX <= svgRect.right &&
        e.clientY >= svgRect.top &&
        e.clientY <= svgRect.bottom

    showTooltip.value = isInside
    if (isInside) {
        mousePosition.value = getLogicalPosition(e.clientX, e.clientY)
        tooltipStyle.value = {
            left: `${e.clientX}px`,
            top: `${e.clientY}px`,
        }
    }
}, 30)

// 左键点击标点
const handleMapClick = (e) => {
    isPointClickStatus.value = false
    if (!svgMapRef.value || isDragging.value) return // 拖拽过程中不标点
    // 判断是否点击了标记的点位
    const isPointClick = devicePoints.value.some((point, index) => {
        const pointRect = itemRefs.value[index].getBoundingClientRect()
        return (
            e.clientX >= pointRect.left &&
            e.clientX <= pointRect.right &&
            e.clientY >= pointRect.top &&
            e.clientY <= pointRect.bottom
        )
    })

    if (isPointClick) {
        return
    }

    const svgRect = svgMapRef.value.getBoundingClientRect()
    const isInside =
        e.clientX >= svgRect.left &&
        e.clientX <= svgRect.right &&
        e.clientY >= svgRect.top &&
        e.clientY <= svgRect.bottom

    if (isInside) {
        const pos = getLogicalPosition(e.clientX, e.clientY)
        addDevicePoint(pos.x, pos.y, pos.y1)
    }
}

// 处理右键点击
const handlePointRightClick = (e, point, index) => {
    e.preventDefault()
    selectedPointIndex.value = index

    // 计算菜单位置
    const containerRect = planeMapContainer.value.getBoundingClientRect()
    const x = e.clientX - containerRect.left
    const y = e.clientY - containerRect.top

    // 确保菜单不会超出容器边界
    const menuWidth = 100
    const menuHeight = 80
    const adjustedX = x + menuWidth > containerRect.width ? x - menuWidth : x
    const adjustedY = y + menuHeight > containerRect.height ? y - menuHeight : y

    contextMenuStyle.value = {
        left: `${adjustedX + 50}px`,
        top: `${adjustedY + 20}px`,
    }

    showContextMenu.value = true
}

// 关闭菜单
const closeContextMenu = () => {
    showContextMenu.value = false
}

// 点击菜单外部关闭菜单
const handleClickOutsideMenu = (e) => {
    if (showContextMenu.value && !e.target.closest('.context-menu')) {
        closeContextMenu()
    }
}

// 修改点位
const handleModifyPoint = () => {
    if (selectedPointIndex.value >= 0) {
        const point = devicePoints.value[selectedPointIndex.value]
        // 这里可以添加修改逻辑，比如弹出对话框
        const markerInfo = {
            type: '修改',
            xCount: point.xCount,
            yCount: point.yCount,
            markerIndex: selectedPointIndex.value,
            markerX: point.markerX,
            markerY: point.markerY,
            markerY1: point.markerY1,
            markerName: point.markerName,
            markerAngle: point.markerAngle,
            markerPreset: point.markerPreset,
        }
        emits('onHandleAddMarker', markerInfo)
    }
    closeContextMenu()
}

// 删除点位
const handleDeletePoint = () => {
    if (selectedPointIndex.value >= 0) {
        devicePoints.value.splice(selectedPointIndex.value, 1)
    }
    closeContextMenu()
}

// 添加设备点位
const addDevicePoint = (x, y, y1) => {
    if (isPointClickStatus.value) return
    devicePoints.value.push({
        xCount: x * 2, // 像素坐标 真实数据
        yCount: y * 2, // 像素坐标 真实数据
        markerX: x, // 直接存储逻辑坐标
        markerY: y, // 直接存储逻辑坐标
        markerY1: y1, // 直接存储逻辑坐标
        id: Date.now(),
        markerName: '',
        markerAngle: '', // 角度
        markerPreset: '', // 摄像头预置位
    })
}

// 点击标记的点位
const handlePointClick = (point, index) => {
    const markerInfo = {
        type: '新增',
        xCount: point.xCount, // 像素坐标 真实数据
        yCount: point.yCount, // 像素坐标 真实数据
        markerIndex: index,
        markerX: point.markerX,
        markerY: point.markerY,
        markerY1: point.markerY1,
        markerName: point.markerName,
        markerAngle: point.markerAngle,
        markerPreset: point.markerPreset,
    }
    emits('onHandleAddMarker', markerInfo)
}

// 获取全部已经添加的点位
const getMarkerListAll = async () => {
    const { data: res } = await getMarkerListAllApi()

    console.log(res, 'res全部点位--')
    if (res.code == 200) {
    }
}

getMarkerListAll()

// 关闭模态框
const onHandleCloseModal = () => {
    emits('onHandleCloseModal')
}

// 监听点击事件以关闭菜单
onMounted(async () => {
    document.addEventListener('click', handleClickOutsideMenu)
    const svg = svgMapRef.value
    svg.addEventListener('wheel', handleWheel, { passive: false }) // 明确声明

    const deviceInfo = await getRobotDeviceListFn()
    // 获取地图信息
    mapInfo.value = await getRobotMapInfoFn(deviceInfo?.puId)
})

onBeforeUnmount(() => {
    document.removeEventListener('click', handleClickOutsideMenu)
})

watch(
    () => props.markerInfoNew,
    (newVal) => {
        // 判断是否为空对象
        if (Object.keys(newVal).length > 0) {
            const svgRect = svgMapRef.value.getBoundingClientRect()
            const clientY =
                svgHeight.value - scale.value * (newVal.yCount / 2) + svgRect.top + offsetY.value
            const logicalY1 = (clientY - svgRect.top - offsetY.value) / scale.value
            devicePoints.value[newVal.markerIndex].markerX = newVal.xCount / 2
            devicePoints.value[newVal.markerIndex].markerY = newVal.markerY
            devicePoints.value[newVal.markerIndex].markerY1 = logicalY1
            devicePoints.value[newVal.markerIndex].markerName = newVal.markerName
            devicePoints.value[newVal.markerIndex].markerAngle = newVal.markerAngle
            devicePoints.value[newVal.markerIndex].markerPreset = newVal.markerPreset
            devicePoints.value[newVal.markerIndex].xCount = newVal.xCount
            devicePoints.value[newVal.markerIndex].yCount = newVal.yCount
        }
    },

    {
        immediate: true,
    },
)

watch(
    // 监听地图信息
    () => mapInfo.value,
    (newVal) => {
        if (newVal.mapWidth && newVal.mapHeight) {
            INITIAL_WIDTH.value = Math.ceil(newVal.mapWidth / 2)
            INITIAL_HEIGHT.value = Math.ceil(newVal.mapHeight / 2)
            svgWidth.value = INITIAL_WIDTH.value
            svgHeight.value = INITIAL_HEIGHT.value
        }
    },
)
</script>

<style lang="scss" scoped>
.plane-map-container {
    width: 100%;
    // height: 80vh;
    max-height: 85vh;
    overflow: auto;
    // 优化横向和竖向滚动条样式
    &::-webkit-scrollbar {
        width: 6px;
        height: 8px;
    }
    &::-webkit-scrollbar-thumb {
        background: #888;
        border-radius: 4px;
    }
    &::-webkit-scrollbar-track {
        background: #f1f1f1;
        border-radius: 4px;
    }

    &.can-drag {
        cursor: grab; /* 可拖拽时显示手型 */
        &:active {
            cursor: grabbing;
        }
    }

    .svg-map-container {
        position: relative;
        cursor: default; /* 默认箭头 */
    }

    circle {
        transition: fill 0.2s;
        cursor: pointer;

        &:hover {
            fill: #ff5252;
            stroke: white;
            stroke-width: 2px;
        }
    }

    // 操作按钮
    .operation-container {
        position: absolute;
        top: 80px;
        right: 60px;
        z-index: 1000;
        gap: 10px;
    }
}

.coord-tooltip {
    position: fixed; /* 改为fixed定位 */
    background: rgba(0, 0, 0, 0.8);
    color: white;
    padding: 4px 8px;
    border-radius: 4px;
    pointer-events: none;
    z-index: 1001;
    transform: translate(10px, 10px);
}

.context-menu {
    position: absolute;
    background: white;
    border: 1px solid #ddd;
    border-radius: 4px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
    z-index: 1002;
    min-width: 100px;

    .menu-item {
        padding: 8px 12px;
        cursor: pointer;
        color: #333;

        &:hover {
            background-color: #f5f5f5;
        }
    }
}
</style>
