<template>
  <div class="map-page with-bottom-nav">
    <div ref="mapContainer" class="map-container" />

    <!-- 定位按钮 -->
    <div class="map-controls">
      <van-button
        icon="aim"
        round
        type="primary"
        size="small"
        :loading="locating"
        @click="locateUser"
      >
        定位
      </van-button>
    </div>

    <!-- 许愿树信息弹出层 -->
    <van-popup
      v-model:show="showPopup"
      position="bottom"
      round
      :style="{ maxHeight: '45%' }"
      safe-area-inset-bottom
    >
      <div class="tree-popup" v-if="selectedTree">
        <div class="popup-cover" :style="{ background: popupGradient }">
          <span class="popup-emoji">{{ popupEmoji }}</span>
        </div>
        <h3 class="popup-name">{{ selectedTree.name }}</h3>
        <p class="popup-addr">{{ selectedTree.address }}</p>
        <div class="popup-meta">
          <van-tag
            :type="selectedTree.isInRange ? 'success' : 'warning'"
            round
            size="medium"
          >
            {{
              selectedTree.isInRange
                ? "可许愿"
                : "距离 " + fmtDist(selectedTree.distance)
            }}
          </van-tag>
          <span class="popup-count"
            >💬 {{ selectedTree.totalWishes }} 个愿望</span
          >
        </div>
        <div class="popup-actions">
          <van-button
            type="primary"
            block
            round
            size="small"
            @click="goTreeDetail"
          >
            查看详情
          </van-button>
          <van-button
            type="success"
            block
            round
            size="small"
            :disabled="!selectedTree.isInRange"
            @click="goMakeWish"
          >
            {{ selectedTree.isInRange ? "🙏 去许愿" : "需要靠近许愿树" }}
          </van-button>
        </div>
      </div>
    </van-popup>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from "vue";
import { useRouter } from "vue-router";
import { showToast } from "vant";
import { useLocationStore } from "@/stores/location";
import { getUserLocation } from "@/utils/geo";
import { getTreeGradient, getTreeEmoji } from "@/utils/theme";
import { fetchNearbyTrees } from "@/api/tree";
import markerImg from "@/assets/location-marker.png";
import { wgs84ToGcj02 } from "@/utils/mapTool";
import L from "leaflet";
import "leaflet/dist/leaflet.css";

const router = useRouter();
const locationStore = useLocationStore();

const mapContainer = ref<HTMLDivElement>();
const showPopup = ref(false);
const selectedTree = ref<any>(null);
const locating = ref(false);

const popupGradient = computed(() =>
  getTreeGradient(selectedTree.value?.id || 1),
);
const popupEmoji = computed(() => getTreeEmoji(selectedTree.value?.id || 1));

let map: any = null;
let userMarker: any = null;
let treeMarkers: L.Marker[] = [];

function fmtDist(m: number) {
  return m >= 1000 ? (m / 1000).toFixed(1) + "km" : m + "m";
}

function goTreeDetail() {
  showPopup.value = false;
  router.push(`/tree/${selectedTree.value.id}`);
}

function goMakeWish() {
  showPopup.value = false;
  router.push({ path: "/make-wish", query: { treeId: selectedTree.value.id } });
}

// 高德瓦片（GCJ-02 坐标系）
const GAODE_TILE = "https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}";

function initMap() {
  try {
    map = L.map(mapContainer.value!, {
      center: [39.9042, 116.4074],
      zoom: 14,
      attributionControl: false,
      zoomControl: false,
    });

    L.tileLayer(GAODE_TILE, {
      subdomains: ["1", "2", "3", "4"],
      maxZoom: 18,
    }).addTo(map);

    L.control.scale({ metric: true, imperial: false }).addTo(map);
    L.control.zoom({ position: "topright" }).addTo(map);

    locateUser();
  } catch (err) {
    showToast("地图加载失败");
    console.error(err);
  }
}

// GPS 定位 → GCJ-02 转换（供 store 定时刷新使用）
async function getGcjLocation(): Promise<{ lng: number; lat: number }> {
  const gps = await getUserLocation()
  const gcj = wgs84ToGcj02(gps)
  console.log(`GPS → GCJ-02：${gps.lng},${gps.lat} → ${gcj.lng},${gcj.lat}`)
  return gcj
}

async function locateUser() {
  locating.value = true;
  try {
    const { lng, lat } = await getGcjLocation();
    locationStore.setLocation(lng, lat);

    if (map) {
      map.setView([lat, lng], 16);

      if (userMarker) map.removeLayer(userMarker);
      const icon = L.icon({
        iconUrl: markerImg,
        iconSize: [25, 45],
        iconAnchor: [12, 45],
      });
      userMarker = L.marker([lat, lng], { icon, zIndexOffset: 200 }).addTo(map);
    }

    await loadTrees();
  } catch {
    await loadTrees();
  } finally {
    locating.value = false;
  }
}

async function loadTrees() {
  if (!locationStore.lng) return;

  const trees = await fetchNearbyTrees(
    locationStore.lng,
    locationStore.lat!,
    50000,
    100,
  );

  treeMarkers.forEach((m) => map.removeLayer(m));
  treeMarkers = [];

  trees.forEach((tree: any) => {
    const isIn = tree.isInRange;
    const color = isIn ? "#07c160" : "#ff976a";
    const label = `${tree.name} ${fmtDist(tree.distance)}`;

    const icon = L.divIcon({
      className: "",
      html: `
        <div style="
          position:relative;
          text-align:center;
          background:${color};
          color:#fff;
          padding:4px 10px;
          border-radius:16px;
          font-size:11px;
          white-space:nowrap;
          box-shadow:0 2px 8px rgba(0,0,0,0.3);
          max-width:160px;
          overflow:hidden;
          text-overflow:ellipsis;
        ">
          ${label}
          <div style="
            position:absolute;
            bottom:-6px;
            left:50%;
            transform:translateX(-50%);
            width:0;
            height:0;
            border-left:6px solid transparent;
            border-right:6px solid transparent;
            border-top:6px solid ${color};
          "></div>
        </div>`,
      iconSize: [0, 0] as any,
      iconAnchor: [0, 0],
    });

    const marker = L.marker([tree.latitude, tree.longitude], { icon }).addTo(map);

    marker.on("click", () => {
      selectedTree.value = tree;
      showPopup.value = true;
    });

    treeMarkers.push(marker);
  });

  if (trees.length > 0 && locationStore.lng) {
    const bounds = L.latLngBounds(
      trees.map((t: any) => [t.latitude, t.longitude] as L.LatLngTuple)
    );
    bounds.extend([locationStore.lat!, locationStore.lng]);
    map.fitBounds(bounds, { padding: [50, 50] });
  }
}

watch(
  () => [locationStore.lng, locationStore.lat] as const,
  ([lng, lat]) => {
    if (lng != null && lat != null && userMarker) {
      userMarker.setLatLng([lat, lng]);
    }
  },
);

onMounted(async () => {
  await nextTick();
  locationStore.setLocationFn(getGcjLocation);
  initMap();
  locationStore.startWatch(5000);
});

onUnmounted(() => {
  locationStore.stopWatch();
  if (map) map.remove();
});
</script>

<style scoped>
.map-page {
  position: relative;
  width: 100%;
  height: calc(100vh - 50px);
}
.map-container {
  width: 100%;
  height: 100%;
}
.map-controls {
  position: absolute;
  bottom: 20px;
  right: 16px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.tree-popup {
  padding: 16px;
}
.popup-cover {
  width: 100%;
  height: 120px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
}
.popup-emoji {
  font-size: 44px;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
}
.popup-name {
  font-size: 17px;
  margin: 10px 0 4px;
}
.popup-addr {
  font-size: 12px;
  color: #999;
  margin-bottom: 10px;
}
.popup-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
}
.popup-count {
  font-size: 12px;
  color: #666;
}
.popup-actions {
  display: flex;
  gap: 8px;
}
</style>
