<!--可以标点和回显-->
<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watchEffect } from 'vue';
import { useScriptTag } from '@vueuse/core';
import { AMAP_SDK_URL } from '@/constants/map-sdk';

// eslint-disable-next-line no-underscore-dangle
window._AMapSecurityConfig = {
  securityJsCode: '3625f15d14e8a930436da886419363ff'
};

defineOptions({
  name: 'MapGaodeSelect'
});

// 可得到地址
const address = defineModel<string>('address', { default: '' });
const logLat = defineModel<[number, number] | [string, string] | string | null>('value', { default: null });
let originLogLat = logLat.value; // 初始化地址的经纬度

const { load } = useScriptTag(AMAP_SDK_URL);
const domRef = ref<HTMLDivElement | null>(null);
const openDomRef = ref<HTMLDivElement | null>(null);
const searchValue = ref<string>('');
const searchOptions = ref<any[]>([]);
const showModal = ref(false);

// eslint-disable-next-line vue/return-in-computed-property
const loglat = computed<[number, number]>(() => {
  // 转换成[number, number]格式
  if (Array.isArray(logLat.value)) {
    if (Object.prototype.toString.call(logLat.value[0]) === '[object String]')
      return logLat.value.map(item => Number(item));
    return logLat.value;
  } else if (Object.prototype.toString.call(logLat.value) === '[object String]') {
    return logLat.value!.split(',').map(item => Number(item));
  }
});

const map = ref<AMap.Map | null>(null);
const marker = ref<AMap.Marker | null>(null);
const circle = ref<AMap.Circle | null>(null);
const geocoder = ref<any>(null);
const autoComplete = ref<any>(null);
const placeSearch = ref<any>(null);

// 初始化渲染的
async function renderMap(mapClick: boolean = false) {
  await load(true);
  const dom = mapClick ? openDomRef.value : domRef.value;
  if (dom) {
    map.value = new AMap.Map(dom, {
      zoom: 19,
      center: loglat.value || [113.3926, 22.51595],
      viewMode: '3D'
    });
    console.log('初始化地图成功', map.value);
    // 如果初始化点存在就绘制点
    if (logLat.value) {
      marker.value = new AMap.Marker({
        position: new AMap.LngLat(...(loglat.value as [number, number])),
        map: map.value
      });
    }

    loadPlugin();

    if (mapClick) {
      // 地图点击事件
      map.value.on('click', clickMapHandler);
    }

    map.value.getCenter();
  }
}

// 需要加载的插件有经纬度和电子转换，POI 搜索插件，输入提示插件
function loadPlugin() {
  AMap.plugin(['AMap.Geocoder', 'AMap.PlaceSearch', 'AMap.AutoComplete'], () => {
    // 开发依赖有一个map的ts检测包，但是不包括插件相关的
    geocoder.value = new AMap.Geocoder();

    if (showModal.value) {
      // 输入提示
      autoComplete.value = new AMap.AutoComplete();
      placeSearch.value = new AMap.PlaceSearch({
        map: map.value
      });
      // 构造地点查询类
      autoComplete.value.on('select', select);

      // poi覆盖物点击事件
      placeSearch.value.on('markerClick', clickMarkerHandler);
    }
  });
}

function select(e: any) {
  console.log(e);
  placeSearch.value.setCity(e.poi.adcode);
  // 关键字查询查询
  placeSearch.value.search(e.poi.name);
}

function openMap() {
  showModal.value = true;
  handleDestroy();
  renderMap(true);
}

function closeMap() {
  showModal.value = false;
  logLat.value = originLogLat;
  handleDestroy();
  renderMap();
}

// 地图点击事件
function clickMapHandler(e: any) {
  logLat.value = [e.lnglat.getLng(), e.lnglat.getLat()];

  if (marker.value) {
    marker.value.setMap(null);
  }
  marker.value = new AMap.Marker({
    position: new AMap.LngLat(e.lnglat.getLng(), e.lnglat.getLat()),
    map: map.value!
  });
}

// poi点击事件
function clickMarkerHandler(e: any) {
  logLat.value = [e.event.lnglat.getLng(), e.event.lnglat.getLat()];
}

function handleSelect() {
  showModal.value = false;
  originLogLat = loglat.value;
  handleDestroy();
  renderMap();
}

function handleDestroy() {
  map.value?.destroy();
  map.value = null;
}

function handleSearch(val: string) {
  if (val.trim() === '') return;
  autoComplete.value.search(val, (status: string, result: any) => {
    if (status === 'complete' && result.tips) {
      searchOptions.value = result.tips;
    } else {
      searchOptions.value = [];
    }
    console.log('搜索结果：', status, result);
  });
}

function handleSelectValue(value: string, option: any) {
  console.log(value, option);
  placeSearch.value.setCity(option.adcode);
  // 关键字查询查询
  placeSearch.value.search(option.name);

  logLat.value = [option.location.getLng(), option.location.getLat()];
}

watchEffect(() => {
  if (logLat.value && geocoder.value) {
    geocoder.value.getAddress(loglat.value, (status: string, result: any) => {
      if (status === 'complete' && result.regeocode) {
        address.value = result.regeocode.formattedAddress;
        console.log('地址解析成功:', result.regeocode.formattedAddress);
      } else {
        address.value = '';
        console.error('地址解析失败:', status, result); // 增加详细错误日志
      }
    });
  }
});

onMounted(() => {
  // 加载初始化的地图组件
  renderMap();
});

onBeforeUnmount(() => {
  handleDestroy();
  marker.value = null;
  circle.value = null;
  geocoder.value = null;
  autoComplete.value = null;
  placeSearch.value = null;
});
</script>

<template>
  <div class="flex-1">
    <NButton type="primary" @click="openMap">打开地图</NButton>

    <!--默认展示的地图-->
    <div ref="domRef" class="mt-10px h-300px w-full"></div>

    <NModal
      v-model:show="showModal"
      :mask-closable="false"
      title="选择位置"
      preset="card"
      class="w-700px"
      @after-leave="closeMap"
    >
      <NFormItem label="关键词搜索">
        <!--<NInput v-model:value="searchValue"></NInput>-->
        <NSelect
          v-model:value="searchValue"
          :options="searchOptions"
          filterable
          remote
          label-field="name"
          value-field="id"
          @search="handleSearch"
          @update:value="handleSelectValue"
        ></NSelect>
      </NFormItem>
      <div ref="openDomRef" class="h-400px w-full"></div>

      <template #footer>
        <div class="flex-y-center justify-end gap-x-10px">
          <NButton type="default" @click="closeMap">取消</NButton>
          <NButton type="primary" @click="handleSelect">确定</NButton>
        </div>
      </template>
    </NModal>
  </div>
</template>

<style scoped></style>
