<template>
  <view ref="mapComponentRef" class="map-component">
    <map
      id="museum-map"
      class="map"
      :latitude="mapCenter.latitude"
      :longitude="mapCenter.longitude"
      :scale="mapScale"
      :markers="markers"
      :polygons="polygons"
      :polylines="displayPolylines"
      :show-location="!isH5"
      :enable-3D="false"
      :enable-overlooking="false"
      :enable-zoom="true"
      :enable-scroll="true"
      :enable-rotate="false"
      @markertap="handleMarkerTap"
      @regionchange="handleRegionChange"
      @tap="handleMapTap"
    >
      <!-- 自定义控件 -->
      <cover-view class="map-controls">
        <!-- 楼层选择器 -->
        <cover-view class="floor-selector-wrapper">
          <cover-view class="floor-selector">
            <cover-view
              v-for="floor in floors"
              :key="floor.id"
              class="floor-item"
              :class="{ active: currentFloor === floor.id }"
              @tap="handleFloorClick(floor.id)"
            >
              <cover-view class="floor-label">{{ floor.label }}</cover-view>
            </cover-view>
          </cover-view>
        </cover-view>

        <!-- 功能按钮 -->
        <cover-view class="action-buttons">
          <!-- 进入 3D 馆内模式按钮 -->
          <cover-view class="action-btn indoor-mode-btn" @tap="handleEnter3D">
            <cover-view class="btn-text">🏛</cover-view>
            <cover-view class="btn-sub-text">馆内</cover-view>
          </cover-view>
          <cover-view class="action-btn" @tap="handleLocation">
            <cover-view class="btn-text">📍</cover-view>
          </cover-view>
          <cover-view class="action-btn" @tap="handleZoomIn">
            <cover-view class="btn-text">+</cover-view>
          </cover-view>
          <cover-view class="action-btn" @tap="handleZoomOut">
            <cover-view class="btn-text">-</cover-view>
          </cover-view>
        </cover-view>
      </cover-view>
    </map>
  </view>
</template>

<script setup lang="ts">
import { computed, ref, onBeforeUnmount, onMounted, nextTick, watch } from 'vue'
import { getMuseumEntranceLocation } from '@/services/tencent/TencentMapService'

const isH5 = typeof window !== 'undefined'

interface MapCenter {
  latitude: number
  longitude: number
}

interface Marker {
  id: number
  latitude: number
  longitude: number
  iconPath: string
  width: number
  height: number
  title?: string
  callout?: {
    content: string
    display: 'ALWAYS' | 'BYCLICK'
    padding: number
    borderRadius: number
    bgColor: string
    color: string
    fontSize: number
  }
}

interface Polygon {
  points: Array<{ latitude: number; longitude: number }>
  strokeWidth: number
  strokeColor: string
  fillColor: string
  zIndex: number
}

interface Polyline {
  points: Array<{ latitude: number; longitude: number }>
  color: string
  width: number
  dottedLine?: boolean
}

export interface OutdoorMapMarker {
  id: string
  title: string
  subtitle?: string
  latitude: number
  longitude: number
}

interface MapFloor {
  id: string
  label: string
}

const props = withDefaults(defineProps<{
  activeFloor?: string
  floors?: MapFloor[]
  polylines?: Polyline[]
  outdoorMarkers?: OutdoorMapMarker[]
  activeOutdoorMarkerId?: string
  outdoorFocusOffsetY?: number
}>(), {
  activeFloor: '1F',
  floors: () => [] as MapFloor[],
  polylines: () => [] as Polyline[],
  outdoorMarkers: () => [] as OutdoorMapMarker[],
  activeOutdoorMarkerId: '',
  outdoorFocusOffsetY: 0
})

const emit = defineEmits<{
  markerClick: [markerId: number]
  outdoorMarkerClick: [markerId: string]
  floorChange: [floor: string]
  enter3DMode: []
  mapTap: [location: { latitude: number; longitude: number }]
}>()

// 深圳自然博物馆实际坐标
// POI ID: 7043042949572197975
const mapCenter = ref<MapCenter>({
  latitude: 22.692763,  // 深圳自然博物馆纬度
  longitude: 114.363572  // 深圳自然博物馆经度（调整到馆外 2D 视觉中心）
})

// 地图缩放级别（调整为适中比例，既能看到建筑全貌又能看清细节）
const mapScale = ref(17)

// 当前楼层
const currentFloor = ref(props.activeFloor)
const mapComponentRef = ref<unknown>(null)
const userLocationMarker = ref<Marker | null>(null)
let mapAuthErrorObserver: MutationObserver | null = null
let mapAuthErrorLogged = false
const mapAuthErrorText = '鉴权失败，请传入正确的key'
const OUTDOOR_MARKER_ID_BASE = 20000

// 楼层列表
const floors = computed(() => props.floors)

// 博物馆建筑围栏（多边形）
// 深圳自然博物馆实际建筑轮廓坐标
const polygons = ref<Polygon[]>([
  {
    points: [
      { latitude: 22.693738, longitude: 114.362331 },
      { latitude: 22.69358, longitude: 114.362239 },
      { latitude: 22.693513, longitude: 114.362239 },
      { latitude: 22.691953, longitude: 114.362252 },
      { latitude: 22.692106, longitude: 114.365058 },
      { latitude: 22.692167, longitude: 114.365051 },
      { latitude: 22.693129, longitude: 114.365018 },
      { latitude: 22.693135, longitude: 114.364655 },
      { latitude: 22.693196, longitude: 114.363982 },
      { latitude: 22.693232, longitude: 114.363764 },
      { latitude: 22.693348, longitude: 114.363473 },
      { latitude: 22.693476, longitude: 114.36319 },
      { latitude: 22.693653, longitude: 114.362714 },
      { latitude: 22.693701, longitude: 114.362523 },
      { latitude: 22.693738, longitude: 114.362351 },
    ],
    strokeWidth: 3,
    strokeColor: '#E0E100',  // 黄色边框
    fillColor: '#E0E10020',  // 半透明黄色填充
    zIndex: 1
  }
])

// 博物馆标记点（初始占位，API 获取后更新）
const museumMarker = ref<Marker>({
  id: 0,
  latitude: 22.692763,
  longitude: 114.363487,
  iconPath: '/static/icons/marker-museum.svg',
  width: 40,
  height: 40,
  title: '深圳自然博物馆',
  callout: {
    content: '深圳自然博物馆',
    display: 'ALWAYS',
    padding: 12,
    borderRadius: 6,
    bgColor: '#E0E100',
    color: '#000000',
    fontSize: 14
  }
})

// 主入口标记点
const entranceMarker = ref<Marker>({
  id: 1,
  latitude: 22.692363,
  longitude: 114.363487,
  iconPath: '/static/icons/marker-entrance.svg',
  width: 30,
  height: 30,
  title: '主入口',
  callout: {
    content: '主入口',
    display: 'BYCLICK',
    padding: 10,
    borderRadius: 5,
    bgColor: '#000000',
    color: '#FFFFFF',
    fontSize: 12
  }
})

const outdoorMarkerIdMap = computed(() => {
  const markerMap = new Map<number, string>()
  props.outdoorMarkers.forEach((marker, index) => {
    markerMap.set(OUTDOOR_MARKER_ID_BASE + index, marker.id)
  })
  return markerMap
})

const outdoorDisplayMarkers = computed<Marker[]>(() => (
  props.outdoorMarkers.map((marker, index) => {
    const isActive = marker.id === props.activeOutdoorMarkerId

    return {
      id: OUTDOOR_MARKER_ID_BASE + index,
      latitude: marker.latitude,
      longitude: marker.longitude,
      iconPath: '/static/icons/marker-location.svg',
      width: isActive ? 42 : 32,
      height: isActive ? 42 : 32,
      title: marker.title,
      callout: {
        content: marker.subtitle ? `${marker.title}\n${marker.subtitle}` : marker.title,
        display: isActive ? 'ALWAYS' : 'BYCLICK',
        padding: 10,
        borderRadius: 6,
        bgColor: isActive ? '#262421' : '#FFFFFF',
        color: isActive ? '#E0E100' : '#262421',
        fontSize: 12
      }
    }
  })
))

// 地图标记点列表
const markers = computed(() => [
  museumMarker.value,
  entranceMarker.value,
  ...outdoorDisplayMarkers.value,
  ...(userLocationMarker.value ? [userLocationMarker.value] : [])
])

// 显示的路线列表（转换格式以适配 uni-app map 组件）
const displayPolylines = computed(() => {
  return props.polylines.map((polyline, index) => ({
    ...polyline,
    id: index,
    // 确保点格式正确
    points: polyline.points.map((p) => ({
      latitude: p.latitude,
      longitude: p.longitude
    }))
  }))
})

/**
 * 更新用户位置标记
 */
const updateUserLocation = (location: { latitude: number; longitude: number }) => {
  userLocationMarker.value = {
    id: 999,
    latitude: location.latitude,
    longitude: location.longitude,
    iconPath: '/static/icons/marker-user-location.svg',
    width: 40,
    height: 40,
    title: '我的位置',
    callout: {
      content: '您在这里',
      display: 'BYCLICK',
      padding: 10,
      borderRadius: 5,
      bgColor: '#000000',
      color: '#FFFFFF',
      fontSize: 12
    }
  }
}

/**
 * 清除用户位置标记
 */
const clearUserLocation = () => {
  userLocationMarker.value = null
}

/**
 * 移动地图中心到指定位置
 */
const moveTo = (location: { latitude: number; longitude: number }) => {
  mapCenter.value = {
    latitude: location.latitude,
    longitude: location.longitude
  }
}

const clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value))

const getLatitudeDegreesPerPixel = (latitude: number, scale: number) => {
  const latitudeRadians = latitude * Math.PI / 180
  const worldPixelSize = 256 * (2 ** scale)
  return 360 * Math.cos(latitudeRadians) / worldPixelSize
}

const moveToWithVerticalOffset = (
  location: { latitude: number; longitude: number },
  offsetY: number
) => {
  const effectiveOffsetY = clamp(offsetY, 0, 360)
  if (effectiveOffsetY <= 0) {
    moveTo(location)
    return
  }

  const latitudeOffset = getLatitudeDegreesPerPixel(location.latitude, mapScale.value) * effectiveOffsetY
  mapCenter.value = {
    latitude: location.latitude - latitudeOffset,
    longitude: location.longitude
  }
}

// 暴露方法给父组件
defineExpose({
  updateUserLocation,
  clearUserLocation,
  moveTo
})

// 处理标记点点击
const handleMarkerTap = (e: any) => {
  const markerId = Number(e.detail?.markerId ?? e.markerId)
  console.log('点击标记点:', markerId)
  const outdoorMarkerId = outdoorMarkerIdMap.value.get(markerId)
  if (outdoorMarkerId) {
    emit('outdoorMarkerClick', outdoorMarkerId)
  }
  emit('markerClick', markerId)
}

// 处理地图区域变化
const handleRegionChange = (e: any) => {
  if (e.type === 'end') {
    console.log('地图区域变化:', e.detail)
  }
}

// 处理地图点击
const handleMapTap = (e: any) => {
  console.log('点击地图:', e.detail)
  const { latitude, longitude } = e.detail || {}
  if (latitude !== undefined && longitude !== undefined) {
    emit('mapTap', { latitude, longitude })
  }
}

// 处理楼层点击
const handleFloorClick = (floorId: string) => {
  currentFloor.value = floorId
  emit('floorChange', floorId)
  console.log('切换楼层:', floorId)
}

// 定位到当前位置
const handleLocation = () => {
  uni.getLocation({
    type: 'gcj02',
    success: (res) => {
      mapCenter.value = {
        latitude: res.latitude,
        longitude: res.longitude
      }

      // 添加或更新用户位置标记
      userLocationMarker.value = {
        id: 999,
        latitude: res.latitude,
        longitude: res.longitude,
        iconPath: '/static/icons/marker-user-location.svg',
        width: 40,
        height: 40,
        title: '我的位置',
        callout: {
          content: '您在这里',
          display: 'BYCLICK',
          padding: 10,
          borderRadius: 5,
          bgColor: '#000000',
          color: '#FFFFFF',
          fontSize: 12
        }
      }

      console.log('定位成功:', res)
    },
    fail: (err) => {
      console.error('定位失败:', err)
      uni.showToast({
        title: '定位失败',
        icon: 'none'
      })
    }
  })
}

// 放大地图
const handleZoomIn = () => {
  if (mapScale.value < 20) {
    mapScale.value += 1
    console.log('放大地图，当前缩放级别:', mapScale.value)
  }
}

// 缩小地图
const handleZoomOut = () => {
  if (mapScale.value > 3) {
    mapScale.value -= 1
    console.log('缩小地图，当前缩放级别:', mapScale.value)
  }
}

// 进入 3D 馆内模式
const handleEnter3D = () => {
  console.log('进入 3D 馆内模式')
  emit('enter3DMode')
}

watch(
  () => [props.activeOutdoorMarkerId, props.outdoorMarkers, props.outdoorFocusOffsetY] as const,
  ([activeOutdoorMarkerId, outdoorMarkers, outdoorFocusOffsetY]) => {
    if (!activeOutdoorMarkerId) return
    const activeMarker = outdoorMarkers.find((marker) => marker.id === activeOutdoorMarkerId)
    if (!activeMarker) return
    moveToWithVerticalOffset(
      {
        latitude: activeMarker.latitude,
        longitude: activeMarker.longitude
      },
      outdoorFocusOffsetY
    )
  },
  { immediate: true }
)

const getMapComponentElement = () => {
  const rawRef = mapComponentRef.value
  if (rawRef instanceof HTMLElement) return rawRef

  const maybeComponent = rawRef as { $el?: Element } | null
  if (maybeComponent?.$el instanceof HTMLElement) return maybeComponent.$el

  if (typeof document === 'undefined') return null
  return document.querySelector<HTMLElement>('.map-component')
}

const hideAuthErrorElement = (element: Element) => {
  const target = element instanceof HTMLElement ? element : element.parentElement
  if (!target) return

  target.style.setProperty('display', 'none', 'important')
  target.style.setProperty('visibility', 'hidden', 'important')
  target.style.setProperty('opacity', '0', 'important')
  target.style.setProperty('pointer-events', 'none', 'important')
  target.setAttribute('aria-hidden', 'true')
}

const hasDirectAuthErrorText = (element: Element) => {
  return Array.from(element.childNodes).some((node) => (
    node.nodeType === Node.TEXT_NODE
    && (node.textContent || '').trim() === mapAuthErrorText
  ))
}

const detectAndHideMapAuthError = () => {
  const root = getMapComponentElement()
  if (!root) return

  const text = root.textContent || ''
  if (!text.includes('鉴权失败')) return

  root.querySelectorAll('*').forEach((element) => {
    const elementText = (element.textContent || '').trim()
    if (elementText === mapAuthErrorText && hasDirectAuthErrorText(element)) {
      hideAuthErrorElement(element)
    }
  })

  if (!mapAuthErrorLogged) {
    mapAuthErrorLogged = true
    console.error('腾讯地图鉴权失败，已隐藏页面内置错误提示:', text.trim())
  }
}

const startMapAuthErrorMonitor = () => {
  if (typeof window === 'undefined') return

  void nextTick(() => {
    detectAndHideMapAuthError()

    const root = getMapComponentElement()
    if (!root || typeof MutationObserver === 'undefined') return

    mapAuthErrorObserver = new MutationObserver(() => {
      detectAndHideMapAuthError()
    })
    mapAuthErrorObserver.observe(root, {
      childList: true,
      subtree: true,
      characterData: true
    })

    window.setTimeout(detectAndHideMapAuthError, 600)
    window.setTimeout(detectAndHideMapAuthError, 1600)
    window.setTimeout(detectAndHideMapAuthError, 3000)
  })
}

onMounted(async () => {
  startMapAuthErrorMonitor()
  console.log('地图组件已挂载，开始获取入口位置...')

  // 从腾讯地图 API 获取入口位置
  const entranceLocation = await getMuseumEntranceLocation()

  if (entranceLocation) {
    entranceMarker.value = {
      ...entranceMarker.value,
      latitude: entranceLocation.lat,
      longitude: entranceLocation.lng
    }
    console.log('已更新入口位置:', entranceLocation)
  }
})

onBeforeUnmount(() => {
  mapAuthErrorObserver?.disconnect()
  mapAuthErrorObserver = null
})
</script>

<style scoped lang="scss">
.map-component {
  width: 100%;
  height: 100%;
  position: relative;
  background: var(--museum-bg-map);
}

.map {
  width: 100%;
  height: 100%;
  background: var(--museum-bg-map);
}

.map-controls {
  display: none;
}

.floor-selector-wrapper {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  pointer-events: auto;
}

.floor-selector {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background-color: rgba(255, 255, 255, 0.8);
  border-radius: 8px;
  padding: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.floor-item {
  width: 46px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: transparent;
  border-radius: 8px;
  transition: all 0.3s;
}

.floor-item.active {
  background-color: #000000;
}

.floor-label {
  font-size: 14px;
  font-weight: 500;
  color: #424754;
}

.floor-item.active .floor-label {
  color: #E0E100;
}

.action-buttons {
  position: absolute;
  right: 12px;
  bottom: 20px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 12px;
  pointer-events: auto;
}

.action-btn {
  width: 46px;
  height: 46px;
  background-color: rgba(255, 255, 255, 0.9);
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.btn-text {
  font-size: 24px;
  font-weight: 500;
  color: #333333;
}

// 馆内模式按钮
.indoor-mode-btn {
  width: 46px;
  height: 64px !important;
  background-color: #E0E100;
  flex-direction: column;
  gap: 2px;
  
  .btn-text {
    font-size: 20px;
  }
  
  .btn-sub-text {
    font-size: 10px;
    font-weight: 600;
    color: #000000;
  }
}
</style>
