<template>
    <!-- POI点信息弹窗 -->
    <div v-if="selectedPoint" class="custom-popup" :style="{
        left: `${popupPosition.x}px`,
        top: `${popupPosition.y}px`
    }">
        <div class="popup-content" :class="{ 'bottom': popupPosition.bottom }">
            <h3>{{ selectedPoint.STNM || '未知点' }}</h3>
            <p><strong>经度:</strong> {{ selectedPoint.LGTD }}</p>
            <p><strong>纬度:</strong> {{ selectedPoint.LTTD }}</p>
            <div class="popup-arrow"></div>
        </div>
    </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue'
import * as Cesium from 'cesium';

// 接收父组件传递的参数
const props = defineProps({
    viewer: {
        type: Object,
        required: true
    },
    visible: {
        type: Boolean,
        default: true
    },
    data: {
        type: Array,
        default: () => []
    },
    pointImage: {
        type: String,
        default: '/src/assets/icon/blue.png'
    },
    flyToOptions: {
        type: Object,
        default: () => ({
            duration: 1.5,
            offset: new Cesium.HeadingPitchRange(0, -0.5, 1500),
            maximumHeight: 5000000
        })
    }
});

// 暴露事件
const emits = defineEmits(['onPointSelected', 'onPointClicked', 'onFlyFailed']);

// POI相关状态
const selectedPoint = ref(null);
const popupPosition = ref({ x: 0, y: 0, bottom: false });
const poiEntities = ref([]);
const entityDataMap = ref(new Map());
const popupUpdateCallback = ref(null);
let handler = null;
const flying = ref(false); // 飞行状态标记

// 获取Cesium容器元素
const getCesiumContainer = () => {
    return document.getElementById('cesiumContainer');
};

// 计算页面缩放比例（与autofit配置一致）
const getScaleRatio = () => {
    const designWidth = 1920;
    const designHeight = 1080;
    return Math.min(window.innerWidth / designWidth, window.innerHeight / designHeight);
};

// 更新POI弹窗位置
const updatePOIPopupPosition = (entity) => {
    if (popupUpdateCallback.value) {
        props.viewer.scene.postRender.removeEventListener(popupUpdateCallback.value);
        popupUpdateCallback.value = null;
    }

    if (!entity || !entity.position || !selectedPoint.value) return;

    popupUpdateCallback.value = () => {
        const container = getCesiumContainer();
        const containerRect = container.getBoundingClientRect();
        const entityPosition = props.viewer.scene.cartesianToCanvasCoordinates(
            entity.position.getValue(props.viewer.clock.currentTime)
        );

        if (entityPosition) {
            nextTick(() => {
                const popupEl = document.querySelector('.custom-popup .popup-content');
                if (!popupEl) return;

                const popupRect = popupEl.getBoundingClientRect();
                const popupWidth = popupRect.width;
                const popupHeight = popupRect.height;
                const arrowHeight = 10;

                // 计算POI点大小
                const billboardScale = entity.billboard?.scale || 0.4;
                const pointRadius = (20 * billboardScale) / 2;

                // 计算弹窗位置
                let x = (entityPosition.x - containerRect.left) - (popupWidth / 2);
                let y, bottom = false;

                // 默认显示在点的上方
                y = (entityPosition.y - containerRect.top) - popupHeight - arrowHeight - pointRadius;

                // 如果上方空间不足，显示在点的下方
                if (y < 0) {
                    y = (entityPosition.y - containerRect.top) + pointRadius + arrowHeight;
                    bottom = true;
                }

                // 边界检查
                if (x < 0) x = 0;
                if (x + popupWidth > containerRect.width) {
                    x = containerRect.width - popupWidth;
                }

                popupPosition.value = { x, y, bottom };
            });
        }
    };

    props.viewer.scene.postRender.addEventListener(popupUpdateCallback.value);
    popupUpdateCallback.value();
};

// 隐藏POI弹窗
const hidePOIPopup = () => {
    selectedPoint.value = null;
    if (popupUpdateCallback.value) {
        props.viewer.scene.postRender.removeEventListener(popupUpdateCallback.value);
        popupUpdateCallback.value = null;
    }
};

// 创建POI点实体
const createPOIEntities = () => {
    // 清除现有实体
    clearPOIEntities();

    // 定义距离显示条件和缩放属性
    const distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, 10000000);
    const pointNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 1000000, 0.3);
    const labelNearFarScalar = new Cesium.NearFarScalar(10000, 1.0, 400000, 0);

    // 创建新实体
    props.data.forEach((item) => {
        // 验证经纬度数据是否有效
        if (!item.LGTD || !item.LTTD) {
            console.warn('POI点数据缺少经纬度信息:', item);
            return;
        }

        try {
            const longitude = parseFloat(item.LGTD);
            const latitude = parseFloat(item.LTTD);

            // 验证经纬度是否在有效范围内
            if (isNaN(longitude) || isNaN(latitude) || longitude < -180 || longitude > 180 || latitude < -90 || latitude > 90) {
                console.warn('无效的经纬度数据:', item);
                return;
            }

            const position = Cesium.Cartesian3.fromDegrees(longitude, latitude);
            const entity = props.viewer.entities.add({
                position: position,
                billboard: {
                    image: props.pointImage,
                    scale: 0.4,
                    color: Cesium.Color.YELLOW,
                    horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                    distanceDisplayCondition: distanceDisplayCondition,
                    scaleByDistance: pointNearFarScalar,
                    show: props.visible
                },
                label: {
                    text: item.STNM || '未知点',
                    font: '25px 微软雅黑',
                    fillColor: Cesium.Color.WHITE,
                    backgroundColor: new Cesium.Color(0.1, 0.1, 0.1, 0.7),
                    backgroundPadding: new Cesium.Cartesian2(8, 4),
                    showBackground: true,
                    cornerRadius: 4,
                    outlineColor: Cesium.Color.BLACK,
                    outlineWidth: 1,
                    horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                    pixelOffset: new Cesium.Cartesian2(0, -32),
                    scale: 1.0,
                    disableDepthTestDistance: Number.POSITIVE_INFINITY,
                    distanceDisplayCondition: distanceDisplayCondition,
                    scaleByDistance: labelNearFarScalar,
                    show: props.visible
                },
                id: `point-${item.STCD || item.LGTD + '-' + item.LTTD}`,
                properties: {
                    data: item
                }
            });
            entityDataMap.value.set(entity.id, item);
            poiEntities.value.push(entity);
        } catch (error) {
            console.error('创建POI实体失败:', error, '数据:', item);
        }
    });
};

// 清除POI实体
const clearPOIEntities = () => {
    poiEntities.value.forEach(entity => {
        props.viewer.entities.remove(entity);
    });
    poiEntities.value = [];
    entityDataMap.value.clear();
};

// 优化：直接使用坐标飞行到POI点（移除实体飞行方式）
const flyToPOIPoint = async (entity, data) => {
    // 防止重复触发飞行
    if (flying.value) return false;

    if (!props.viewer || !data || !data.LGTD || !data.LTTD) {
        console.error('飞行参数不完整');
        emits('onFlyFailed', data, '参数不完整');
        return false;
    }

    flying.value = true;
    let success = false;

    try {
        // 直接使用经纬度坐标飞行（移除实体飞行方式）
        const longitude = parseFloat(data.LGTD);
        const latitude = parseFloat(data.LTTD);

        if (isNaN(longitude) || isNaN(latitude)) {
            throw new Error('经纬度解析失败');
        }

        // 计算目标高度 - 确保合理
        const height = Math.min(
            props.flyToOptions.offset.range,
            props.flyToOptions.maximumHeight
        );

        // 坐标微调参数（根据实际偏差调整）
        const lonOffset = -0.001;  // 经度偏移量
        const latOffset = -0.025;  // 纬度偏移量
        
        // 计算最终目标位置（应用微调）
        const destination = Cesium.Cartesian3.fromDegrees(
            longitude + lonOffset,
            latitude + latOffset,
            height
        );

        // 验证目标位置是否有效
        if (Cesium.Cartesian3.equals(destination, Cesium.Cartesian3.ZERO)) {
            throw new Error('计算的目标位置无效');
        }

        // 使用相机直接飞行
        await new Promise((resolve, reject) => {
            props.viewer.camera.flyTo({
                destination: destination,
                orientation: {
                    heading: props.flyToOptions.offset.heading || Cesium.Math.toRadians(0),
                    pitch: props.flyToOptions.offset.pitch || Cesium.Math.toRadians(-60),  // 更平缓的角度
                    roll: 0
                },
                duration: props.flyToOptions.duration || 1.5,
                complete: resolve,
                cancel: () => reject(new Error('用户取消飞行'))
            });
        });

        success = true;
        console.log('使用坐标飞行成功:', data.STNM);
    } catch (coordError) {
        console.error('坐标飞行失败:', coordError.message);
        emits('onFlyFailed', data, coordError.message);

        // 最终备选方案：直接设置相机位置
        try {
            const longitude = parseFloat(data.LGTD);
            const latitude = parseFloat(data.LTTD);

            if (!isNaN(longitude) && !isNaN(latitude)) {
                props.viewer.camera.setView({
                    destination: Cesium.Cartesian3.fromDegrees(
                        longitude,
                        latitude,
                        props.flyToOptions.offset.range
                    ),
                    orientation: {
                        heading: props.flyToOptions.offset.heading || 0,
                        pitch: props.flyToOptions.offset.pitch || -Cesium.Math.PI_OVER_TWO,
                        roll: 0
                    }
                });
                success = true;
                console.log('使用setView直接定位成功');
            }
        } catch (finalError) {
            console.error('所有飞行方法均失败:', finalError.message);
        }
    } finally {
        flying.value = false;
    }

    return success;
};

// 初始化事件监听
const initEventListeners = () => {
    // 清除现有处理器
    if (handler) {
        handler.destroy();
    }

    handler = new Cesium.ScreenSpaceEventHandler(props.viewer.scene.canvas);

    // 点击事件处理
    handler.setInputAction(async (click) => {
        const scaleRatio = getScaleRatio();
        const correctedX = click.position.x / scaleRatio;
        const correctedY = click.position.y / scaleRatio;

        if (!props.visible || flying.value) return; // 飞行中不响应新点击

        // 标准拾取
        const pickedObject = props.viewer.scene.pick(new Cesium.Cartesian2(correctedX, correctedY));

        // 隐藏弹窗
        hidePOIPopup();

        if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
            const entityId = pickedObject.id.id;
            const data = entityDataMap.value.get(entityId) ||
                pickedObject.id.properties?.data?.getValue();

            if (data && !entityId.startsWith('typhoon-point-')) {
                selectedPoint.value = data;

                // 计算图标屏幕坐标，固定显示在图标上方
                const entityPosition = props.viewer.scene.cartesianToCanvasCoordinates(pickedObject.id.position._value);
                if (entityPosition) {
                    popupPosition.value = {
                        x: (entityPosition.x / scaleRatio) - 100,
                        y: (entityPosition.y / scaleRatio) - 130,  // 130 = 弹框高度 + 间距
                        bottom: false
                    };
                }

                // 通知父组件
                emits('onPointSelected', data);
                emits('onPointClicked', data);

                // 跳转到POI点
                const flySuccess = await flyToPOIPoint(pickedObject.id, data);
                if (!flySuccess) {
                    console.warn('飞行到POI点最终失败');
                }
            }
        } else {
            selectedPoint.value = null;
            emits('onPointSelected', null);
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
};

// 监听visible属性变化
watch(() => props.visible, (newVal) => {
    poiEntities.value.forEach(entity => {
        if (entity && entity.billboard) {
            entity.billboard.show = newVal;
            entity.label.show = newVal;
        }
    });
});

// 监听数据变化
watch(() => props.data, (newVal) => {
    if (newVal && newVal.length > 0) {
        createPOIEntities();
    }
}, { deep: true });

// 监听viewer变化
watch(() => props.viewer, (newVal) => {
    if (newVal) {
        initEventListeners();
        if (props.data && props.data.length > 0) {
            createPOIEntities();
        }
    }
});

// 组件挂载时初始化
onMounted(() => {
    if (props.viewer) {
        initEventListeners();

        // 初始创建POI点
        if (props.data && props.data.length > 0) {
            createPOIEntities();
        }
    } else {
        console.warn('POI组件挂载时viewer尚未初始化');
    }
});

// 组件卸载时清理
onUnmounted(() => {
    // 移除弹窗更新回调
    if (popupUpdateCallback.value) {
        props.viewer?.scene.postRender.removeEventListener(popupUpdateCallback.value);
    }

    // 清除事件处理器
    if (handler) {
        handler.destroy();
    }

    // 清除所有POI实体
    clearPOIEntities();
});

// 暴露方法
defineExpose({
    hidePOIPopup,
    flyToPOIPoint
});
</script>

<style scoped>
.custom-popup {
    position: absolute;
    z-index: 1000;
    pointer-events: none;
    top: 0;
    left: 0;
}

.popup-content {
    background-color: white;
    border-radius: 5px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
    padding: 10px 15px;
    width: 240px;
    pointer-events: all;
    min-width: 200px;
    box-sizing: border-box;
    position: relative;
}

.popup-arrow {
    position: absolute;
    width: 0;
    height: 0;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    left: 50%;
    transform: translateX(-50%);
}

.popup-content:not(.bottom) .popup-arrow {
    bottom: -10px;
    border-top: 10px solid white;
}

.popup-content.bottom .popup-arrow {
    top: -10px;
    border-bottom: 10px solid white;
}

.popup-content h3 {
    margin-top: 0;
    margin-bottom: 8px;
    color: #333;
    font-size: 16px;
}

.popup-content p {
    margin: 5px 0;
    color: #666;
    font-size: 14px;
}

@media (max-width: 768px) {
    .popup-content {
        width: 200px;
        padding: 8px 12px;
    }
}
</style>
