<template>
  <div class="rounded-lg overflow-hidden border border-base-300">
    <ClientOnly>
      <MapboxMap
        :key="mapId"
        :map-id="mapId"
        :style="`height: ${height}px; width: 100%;`"
        :options="mapOptions"
        @load="onMapCreated"
      />

      <template #fallback>
        <div :style="`height: ${height}px`" class="w-full bg-base-200 flex items-center justify-center">
          <span class="loading loading-spinner loading-xs"></span>
        </div>
      </template>
    </ClientOnly>
  </div>
</template>

<script setup lang="ts">
import type { Map as MapboxMapType } from 'mapbox-gl'
import { getCurrentInstance } from 'vue'

const props = withDefaults(defineProps<{
  latitude: number
  longitude: number
  height?: number
}>(), {
  height: 120
})

const mapRef = ref<MapboxMapType | null>(null)

const instanceId = getCurrentInstance()?.uid || Math.floor(Math.random() * 100000)
const mapId = computed(() => `location-mini-map-${instanceId}`)

const mapOptions = computed(() => ({
  style: 'mapbox://styles/mapbox/streets-v12',
  center: [props.longitude, props.latitude] as [number, number],
  zoom: 5,
  interactive: false,
  attributionControl: false
}))

const onMapCreated = (map: MapboxMapType) => {
  mapRef.value = map

  const initMap = () => {
    map.addSource('location-point', {
      type: 'geojson',
      data: {
        type: 'Feature',
        properties: {},
        geometry: {
          type: 'Point',
          coordinates: [props.longitude, props.latitude]
        }
      }
    })

    map.addLayer({
      id: 'location-point-layer',
      type: 'circle',
      source: 'location-point',
      paint: {
        'circle-radius': 8,
        'circle-color': '#10b981',
        'circle-stroke-width': 2,
        'circle-stroke-color': '#ffffff'
      }
    })
  }

  if (map.loaded()) {
    initMap()
  } else {
    map.on('load', initMap)
  }
}

watch(
  () => [props.latitude, props.longitude],
  () => {
    const map = mapRef.value
    if (!map) return

    map.setCenter([props.longitude, props.latitude])

    const source = map.getSource('location-point') as mapboxgl.GeoJSONSource | undefined
    if (source) {
      source.setData({
        type: 'Feature',
        properties: {},
        geometry: {
          type: 'Point',
          coordinates: [props.longitude, props.latitude]
        }
      })
    }
  }
)
</script>
