/**
 * useMap - 响应式地图实例管理组合式函数
 *
 * 基于 MapManager 单例提供响应式地图实例、加载状态、中心点、缩放级别等。
 * 自动订阅地图生命周期事件，组件卸载时自动清理。
 *
 * @module map/composables/useMap
 */

import { ref, readonly, onUnmounted, type Ref, type DeepReadonly } from 'vue'
import maplibregl from 'maplibre-gl'
import { MapManager } from '../MapManager'

// Local type alias: use maplibregl.Map to avoid potential conflicts
// with types re-exported via `export type *` in maplibre-gl's d.ts
type MapInstance = maplibregl.Map

// ============================================================
// 类型定义
// ============================================================

/**
 * useMap 返回类型
 */
export interface UseMapReturn {
  /**
   * 当前 maplibregl.Map 实例（只读）
   *
   * 地图未创建时为 null，加载完成后为 Map 实例
   */
  map: Ref<MapInstance | null>

  /**
   * 地图是否正在加载
   *
   * 初始为 true，收到 'map:loaded' 事件后变为 false；
   * 地图销毁后重置为 true
   */
  loading: DeepReadonly<Ref<boolean>>

  /**
   * 地图加载/运行时的错误信息
   *
   * 当 map 触发 'error' 事件时更新
   */
  error: DeepReadonly<Ref<string | null>>

  /**
   * 地图当前中心点坐标 [lng, lat]（只读）
   *
   * 每次 'moveend' 事件后自动更新
   */
  center: DeepReadonly<Ref<[number, number] | null>>

  /**
   * 地图当前缩放级别（只读）
   *
   * 每次 'zoomend' 事件后自动更新
   */
  zoom: DeepReadonly<Ref<number | null>>

  /**
   * 地图是否已加载完成
   *
   * 等同于 !loading && map !== null
   */
  isReady: DeepReadonly<Ref<boolean>>
}

// ============================================================
// useMap
// ============================================================

/**
 * 响应式地图实例管理组合式函数
 *
 * 订阅 MapManager 单例的生命周期事件，提供 Vue 响应式的地图状态。
 * 组件卸载时自动取消所有订阅。
 *
 * @returns 地图响应式状态与方法
 *
 * @example
 * ```vue
 * <script setup lang="ts">
 * import { useMap } from '@/map/composables/useMap'
 *
 * const { map, loading, center, zoom, isReady, error } = useMap()
 *
 * watch(isReady, (ready) => {
 *   if (ready) console.log('地图就绪，中心点：', center.value)
 * })
 * </script>
 * ```
 */
export function useMap(): UseMapReturn {
  // ----------------------------------------------------------
  // 获取单例
  // ----------------------------------------------------------
  const manager = MapManager.getInstance()

  // ----------------------------------------------------------
  // 响应式状态
  // ----------------------------------------------------------

  /** 地图实例 */
  const map = ref<MapInstance | null>(manager.getMap())

  /** 加载状态：初始根据当前是否有已加载的地图判断 */
  const loading = ref<boolean>(!manager.hasMap())

  /** 错误信息 */
  const error = ref<string | null>(null)

  /** 中心点坐标 */
  const center = ref<[number, number] | null>(null)

  /** 缩放级别 */
  const zoom = ref<number | null>(null)

  /** 是否就绪 */
  const isReady = ref<boolean>(manager.hasMap())

  // ----------------------------------------------------------
  // 内部辅助函数
  // ----------------------------------------------------------

  /**
   * 同步中心点和缩放级别
   */
  function syncViewState(m: MapInstance): void {
    const c = m.getCenter()
    center.value = [c.lng, c.lat]
    zoom.value = m.getZoom()
  }

  /**
   * 绑定 map 实例上的原生事件
   */
  function bindMapEvents(m: MapInstance): void {
    m.on('moveend', () => syncViewState(m))
    m.on('zoomend', () => {
      zoom.value = m.getZoom()
    })
    m.on('error', (e: { error?: Error }) => {
      error.value = e.error?.message ?? '地图发生未知错误'
    })
  }

  /**
   * 解绑 map 实例上的原生事件
   */
  function unbindMapEvents(m: MapInstance): void {
    m.off('moveend', () => syncViewState(m))
    m.off('zoomend', () => {
      zoom.value = m.getZoom()
    })
    m.off('error', () => {})
  }

  // ----------------------------------------------------------
  // 订阅 MapManager 生命周期事件
  // ----------------------------------------------------------

  /** 地图加载完成 */
  function onMapLoaded(m: MapInstance): void {
    map.value = m
    loading.value = false
    error.value = null
    isReady.value = true

    // 同步初始视图状态
    syncViewState(m)

    // 绑定后续的原生地图事件
    bindMapEvents(m)
  }

  /** 地图即将创建 */
  function onMapCreating(): void {
    loading.value = true
    isReady.value = false
    error.value = null
  }

  /** 地图已销毁 */
  function onMapDestroyed(): void {
    // 解绑旧实例的事件
    const m = map.value as MapInstance | null
    if (m) {
      unbindMapEvents(m)
    }

    map.value = null
    loading.value = true
    isReady.value = false
    center.value = null
    zoom.value = null
  }

  // 注册事件监听
  manager.on('map:loaded', onMapLoaded)
  manager.on('map:creating', onMapCreating)
  manager.on('map:destroyed', onMapDestroyed)

  // 如果当前已有已加载的地图实例，立即同步状态
  const currentMap = manager.getMap()
  if (currentMap && currentMap.loaded()) {
    onMapLoaded(currentMap)
  } else if (currentMap) {
    // 地图存在但尚未加载完成
    map.value = currentMap
    loading.value = true
    isReady.value = false

    // 监听该实例的 load 事件
    currentMap.once('load', () => {
      onMapLoaded(currentMap)
    })
  }

  // ----------------------------------------------------------
  // 组件卸载时清理
  // ----------------------------------------------------------
  onUnmounted(() => {
    manager.off('map:loaded', onMapLoaded)
    manager.off('map:creating', onMapCreating)
    manager.off('map:destroyed', onMapDestroyed)

    // 清理原生地图事件
    const m2 = map.value as MapInstance | null
    if (m2) {
      unbindMapEvents(m2)
    }
  })

  // ----------------------------------------------------------
  // 返回只读响应式状态
  // ----------------------------------------------------------
  return {
    map: map as Ref<MapInstance | null>,
    loading: readonly(loading),
    error: readonly(error),
    center: readonly(center),
    zoom: readonly(zoom),
    isReady: readonly(isReady),
  } as UseMapReturn
}
