<script setup lang="ts">
import { ref } from 'vue'
import { loadModules } from 'esri-loader'
import axios from 'axios'
import { useCounterMixin } from '@/stores/mixin'
import { useQuasar } from 'quasar'
import { usePrivacyStore } from '@/stores/privacy'
import { useLocationValidation } from '@/composables/useLocationValidation'

const mixin = useCounterMixin()
const { messageError } = mixin
const privacyStore = usePrivacyStore()

// import type { LocationObject } from '@/interface/index/Main'
const mapElement = ref<HTMLElement | null>(null)
const emit = defineEmits(['update:location', 'locationStatus', 'mockDetected'])
const $q = useQuasar()

const { validateLocation, showMockWarning } = useLocationValidation()

function updateLocation(latitude: number, longitude: number, namePOI: string) {
  // ส่ง event ไปยัง parent component เพื่ออัพเดทค่า props
  emit('update:location', latitude, longitude, namePOI)
}

const poiPlaceName = ref<string>('') // ชื่อพื้นที่ใกล้เคียง

// Replace ArcGIS api key
const apiKey = ref<string>(
  'YLATgWuywoeRLHn6KImj5rg7UaP8bJoR9jiTldoCVBHlqFIebwMSA5wIXEmcYhwXwMHkmNISEYtUz3x0oiGIIx0bIXXnUwi0OzupoOEtDrQIsRPVtor7gaPpXEmH8TrNaMT3snf6zO_yujHLGzborg-L9aeAjTJn4ndL6f8qFmRzYcX93E2vyA-7XCufLYTRsdTE5Aq-9hnx1q9PmYVMqhAZpL7dWqn3JgO33fRXetk.'
  // 'AAPK4f700a4324d04e9f8a1a134e0771ac45FXWawdCl-OotFfr52gz9XKxTDJTpDzw_YYcwbmKDDyAJswf14FoPyw0qBkN64DvP'
)
const zoomMap = ref<number>(18)

async function initializeMap() {
  try {
    // Load modules of ArcGIS
    loadModules([
      'esri/config',
      'esri/Map',
      'esri/views/MapView',
      'esri/geometry/Point',
      'esri/Graphic',
      'esri/layers/TileLayer',
    ]).then(async ([esriConfig, Map, MapView, Point, Graphic, TileLayer]) => {
      // Set apiKey
      // esriConfig.apiKey =
      //   'AAPK4f700a4324d04e9f8a1a134e0771ac45FXWawdCl-OotFfr52gz9XKxTDJTpDzw_YYcwbmKDDyAJswf14FoPyw0qBkN64DvP'

      // Create a FeatureLayer using a custom server URL
      // const hillshadeLayer = new TileLayer({
      //   url: `https://bmagis.bangkok.go.th/arcgis/rest/services/cache/BMA_3D_2D_Cache/MapServer`,
      // })

      const map = new Map({
        basemap: 'streets',
        // basemap: 'arcgis-topographic',
        // layers: [hillshadeLayer],
      })

      navigator.geolocation.getCurrentPosition(async (position) => {
        const { latitude, longitude } = position.coords

        const mapView = new MapView({
          container: 'mapViewDisplay',
          map: map,
          center: {
            latitude: latitude,
            longitude: longitude,
          }, // Set the initial map center current position

          zoom: zoomMap.value,
          constraints: {
            snapToZoom: false, // Disables snapping to the zoom level
            minZoom: zoomMap.value, // Set minimum zoom level
            maxZoom: zoomMap.value, // Set maximum zoom level (same as minZoom for fixed zoom)
          },

          ui: {
            components: [], // Empty array to remove all default UI components
          },
        })

        // ตำแหน่งของผู้ใช้
        const userPoint = new Point({ longitude, latitude })
        const userSymbol = {
          type: 'picture-marker',
          url: 'http://maps.google.com/mapfiles/ms/icons/red.png',
          width: '32px',
          height: '32px',
        }
        const userGraphic = new Graphic({
          geometry: userPoint,
          symbol: userSymbol,
        })
        mapView.graphics.add(userGraphic)
        // Get POI place ยิงไปขอที่ server ของกทม.ก่อน
        await axios
          .get(
            'https://bmagis.bangkok.go.th/portal/sharing/servers/e4732c3a9fe549ab8bc697573b468f68/rest/services/World/GeocodeServer/reverseGeocode/',
            {
              params: {
                f: 'json', // Format JSON response
                distance: 2000,
                category: 'POI',
                location: {
                  spatialReference: { wkid: 4326 },
                  x: longitude,
                  y: latitude,
                },
                token: apiKey.value,
              },
            }
          )
          .then((response) => {
            // console.log('poi', response.data.location)
            poiPlaceName.value = response.data.address
              ? response.data.address.PlaceName === ''
                ? response.data.address.ShortLabel
                : response.data.address.PlaceName
              : 'ไม่พบข้อมูล'
            const poiPoint = new Point({
              longitude: response.data.location.x,
              latitude: response.data.location.y,
            })
            const poiSymbol = {
              type: 'picture-marker',
              url: 'http://maps.google.com/mapfiles/ms/icons/blue.png',
              width: '32px',
              height: '32px',
            }
            const poiGraphic = new Graphic({
              geometry: poiPoint,
              symbol: poiSymbol,
            })
            mapView.graphics.add(poiGraphic)
            // อัปเดตการแสดงผลให้แสดงทั้งตำแหน่งของผู้ใช้และ POI
            mapView.goTo({
              target: [userPoint, poiPoint],
              zoom: zoomMap.value,
            })

            updateLocation(latitude, longitude, poiPlaceName.value)
          })
          .catch(async (error) => {
            // console.error('Error fetching points of interest:', error)
            // Get POI place ยิงไปขอที่ server arcgis ไม่ต้องใช้ token
            await axios
              .get(
                'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode/',
                {
                  params: {
                    f: 'json', // Format JSON response
                    distance: 2000,
                    category: 'POI',
                    location: {
                      spatialReference: { wkid: 4326 },
                      x: longitude,
                      y: latitude,
                    },
                  },
                }
              )
              .then((response) => {
                // console.log('poi', response.data.location)
                poiPlaceName.value = response.data.address
                  ? response.data.address.PlaceName === ''
                    ? response.data.address.ShortLabel
                    : response.data.address.PlaceName
                  : 'ไม่พบข้อมูล'
                const poiPoint = new Point({
                  longitude: response.data.location.x,
                  latitude: response.data.location.y,
                })
                const poiSymbol = {
                  type: 'picture-marker',
                  url: 'http://maps.google.com/mapfiles/ms/icons/blue.png',
                  width: '32px',
                  height: '32px',
                }
                const poiGraphic = new Graphic({
                  geometry: poiPoint,
                  symbol: poiSymbol,
                })
                mapView.graphics.add(poiGraphic)
                // อัปเดตการแสดงผลให้แสดงทั้งตำแหน่งของผู้ใช้และ POI
                mapView.goTo({
                  target: [userPoint, poiPoint],
                  zoom: zoomMap.value,
                })

                updateLocation(latitude, longitude, poiPlaceName.value)
              })
              .catch((error) => {
                // console.error('Error fetching points of interest:', error)
              })
          })
      })
    })
  } catch (error) {
    console.error('Error loading the map', error)
  }
}

const locationGranted = ref<boolean>(false)
// Function to request location permission
const requestLocationPermission = () => {
  // เช็คสิทธิ์ privacy ก่อนเข้าถึงแผนที่
  if (!privacyStore.isAccepted) {
    $q.notify({
      type: 'warning',
      message: 'กรุณายอมรับนโยบายคุ้มครองข้อมูลส่วนบุคคลก่อนใช้งานแผนที่',
      position: 'top',
    })
    return
  }

  if (!navigator.geolocation) {
    messageError(
      $q,
      '',
      'ไม่สามารถระบุตำแหน่งปัจจุบันได้ เบราว์เซอร์ของคุณไม่รองรับ Geolocation'
    )
    return
  }

  navigator.geolocation.getCurrentPosition(
    async (position) => {
      // Validate location first
      const validationResult = validateLocation(position)

      // Always emit mockDetected event (regardless of result)
      if (validationResult.isMockDetected) {
        showMockWarning(validationResult)
        emit('mockDetected', validationResult)
      }

      // Check for critical errors (invalid coordinates) that prevent showing location
      const hasCriticalErrors = validationResult.errors.some(error =>
        error.includes('พิกัดตำแหน่งไม่ถูกต้อง')
      )

      if (hasCriticalErrors) {
        locationGranted.value = false
        emit('locationStatus', false)
        messageError($q, '', validationResult.errors[0])
        return
      }

      // Permission granted based on mock detection
      locationGranted.value = !validationResult.isMockDetected
      emit('locationStatus', !validationResult.isMockDetected)

      const { latitude, longitude } = position.coords
      // console.log('Current position:', latitude, longitude)

      if (!latitude || !longitude) {
        messageError($q, '', 'ไม่สามารถระบุตำแหน่งปัจจุบันได้')
        return
      }

      // Center map on user's location if map is initialized
      if (privacyStore.isAccepted) {
        await initializeMap()
      }
    },
    (error) => {
      // Permission denied
      locationGranted.value = false
      emit('locationStatus', false)

      switch (error.code) {
        case error.PERMISSION_DENIED:
          messageError(
            $q,
            '',
            'ไม่สามารถระบุตำแหน่งปัจจุบันได้ เนื่องจากคุณปฏิเสธการเข้าถึงตำแหน่ง กรุณาเปิดการเข้าถึงตำแหน่ง'
          )
          break
        case error.POSITION_UNAVAILABLE:
          messageError($q, '', 'ไม่สามารถระบุตำแหน่งปัจจุบันได้')
          break
        case error.TIMEOUT:
          messageError($q, '', 'การร้องขอตำแหน่งหมดเวลา กรุณาลองอีกครั้ง')
          break
        default:
          messageError(
            $q,
            '',
            'ไม่สามารถระบุตำแหน่งปัจจุบันได้ เกิดข้อผิดพลาดไม่ทราบสาเหตุในการเข้าถึงตำแหน่ง'
          )
          break
      }
    },
    { enableHighAccuracy: true }
  )
}

defineExpose({
  requestLocationPermission,
  locationGranted,
})
</script>

<template>
  <!-- Loading skeleton -->
  <div v-if="!poiPlaceName" class="col-12">
    <q-skeleton
      :height="$q.screen.gt.xs ? '35vh' : '45px'"
      width="100%"
      :style="$q.screen.gt.xs ? ';' : 'border-radius: 20px'"
      class="bg-grey-4"
    />
  </div>

  <q-card
    v-show="poiPlaceName"
    bordered
    flat
    class="col-12 bg-grey-2 shadow-0"
    :style="$q.screen.gt.xs ? ';' : 'border-radius: 20px'"
  >
    <div v-if="$q.screen.gt.xs">
      <div
        id="mapViewDisplay"
        ref="mapElement"
        style="height: 35vh; pointer-events: none"
      ></div>

      <div
        :class="
          $q.screen.gt.xs
            ? 'q-pa-xs text-weight-medium text-grey-8'
            : 'q-pa-xs text-weight-medium text-grey-8'
        "
      >
        พื้นที่ใกล้เคียง
        <span class="q-px-sm">:</span>
        {{ poiPlaceName }}
      </div>
    </div>

    <q-card v-else style="border-radius: 20px">
      <q-expansion-item
        class="shadow-1 overflow-hidden bg-grey-4 text-left"
        style="border-radius: 20px"
        dense
        default-opened
      >
        <template v-slot:header>
          <q-item-section avatar class="q-pr-none expanAS">
            <q-avatar icon="mdi-map-marker" />
          </q-item-section>

          <q-item-section>
            {{ poiPlaceName }}
          </q-item-section>
        </template>

        <div id="mapViewDisplay" style="height: 20vh"></div>
      </q-expansion-item>
    </q-card>
  </q-card>
</template>

<style>
.expanAS.q-item__section--avatar {
  min-width: 40px !important;
}
</style>
