import townshipGeoJson from '@/assets/mapJson/map.json'

export const TOWNSHIP_SOURCE_ID = 'baqing-township'
export const TOWNSHIP_FILL_LAYER_ID = 'baqing-township-fill'
export const TOWNSHIP_LINE_GLOW_LAYER_ID = 'baqing-township-line-glow'
export const TOWNSHIP_LINE_LAYER_ID = 'baqing-township-line'

/** 乡镇名称标注手动微调（经度, 纬度） */
const TOWNSHIP_LABEL_OVERRIDES = {
  拉西镇: [94.003062, 32.041406],
  玛如乡: [93.862433, 32.341736]
}

/** 乡镇点击下钻中心手动微调（经度, 纬度） */
const TOWNSHIP_DRILL_CENTER_OVERRIDES = {
  拉西镇: [94.054094, 31.920244]
}

function getTownshipDrillCenter(feature) {
  if (!feature) {
    return null
  }
  const name = String(feature.properties?.name || '')
  const override = TOWNSHIP_DRILL_CENTER_OVERRIDES[name]
  if (Array.isArray(override) && override.length >= 2) {
    const lng = Number(override[0])
    const lat = Number(override[1])
    if (Number.isFinite(lng) && Number.isFinite(lat)) {
      return [lng, lat]
    }
  }

  const labelPoint = getTownshipLabelPoints().find((item) => item.name === name)?.lngLat
  if (Array.isArray(labelPoint) && labelPoint.length >= 2) {
    return [...labelPoint]
  }

  const center = feature.properties?.center
  if (Array.isArray(center) && center.length >= 2) {
    return [Number(center[0]), Number(center[1])]
  }

  return null
}

/** POI 周边搜索中心：拉西镇用手动坐标，其余乡镇用 json 的 center/centroid */
export function getTownshipPoiSearchCenter(feature) {
  if (!feature) {
    return null
  }
  const name = String(feature.properties?.name || '')
  const override = TOWNSHIP_DRILL_CENTER_OVERRIDES[name]
  if (Array.isArray(override) && override.length >= 2) {
    const lng = Number(override[0])
    const lat = Number(override[1])
    if (Number.isFinite(lng) && Number.isFinite(lat)) {
      return [lng, lat]
    }
  }

  const center = feature.properties?.centroid || feature.properties?.center
  if (Array.isArray(center) && center.length >= 2) {
    const lng = Number(center[0])
    const lat = Number(center[1])
    if (Number.isFinite(lng) && Number.isFinite(lat)) {
      return [lng, lat]
    }
  }

  return null
}

/** POI 多边形搜索范围：取乡镇边界外环 [经度, 纬度][] */
export function getTownshipPoiSearchPolygon(feature) {
  const ring = getPolygonOuterRing(feature)
  if (!Array.isArray(ring) || ring.length < 3) {
    return null
  }
  return ring.map(([lng, lat]) => [Number(lng), Number(lat)])
}

export function getTownshipGeoJson() {
  return townshipGeoJson
}

export function getTownshipFeatures(geojson = townshipGeoJson) {
  return (geojson?.features || []).filter((feature) => feature?.geometry?.type === 'Polygon')
}

function getPolygonOuterRing(feature) {
  return feature?.geometry?.coordinates?.[0] || null
}

function pointInPolygon(point, ring) {
  const x = point[0]
  const y = point[1]
  let inside = false
  for (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {
    const xi = ring[i][0]
    const yi = ring[i][1]
    const xj = ring[j][0]
    const yj = ring[j][1]
    const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi
    if (intersect) {
      inside = !inside
    }
  }
  return inside
}

/** 在多边形内部求视觉中心（拉西镇等 concave 面 properties.centroid 可能在面外） */
function computePolygonLabelPoint(ring, precision = 0.001) {
  if (!Array.isArray(ring) || ring.length < 4) {
    return null
  }

  let minLng = Infinity
  let maxLng = -Infinity
  let minLat = Infinity
  let maxLat = -Infinity
  ring.forEach(([lng, lat]) => {
    minLng = Math.min(minLng, lng)
    maxLng = Math.max(maxLng, lng)
    minLat = Math.min(minLat, lat)
    maxLat = Math.max(maxLat, lat)
  })

  const width = maxLng - minLng
  const height = maxLat - minLat
  if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
    return null
  }

  const cellSize = Math.min(width, height)
  const half = cellSize / 2
  const cells = []

  const cellMaxDistance = (lng, lat, inside) => {
    if (!inside) {
      return -1
    }
    return Math.min(lng - minLng, maxLng - lng, lat - minLat, maxLat - lat)
  }

  for (let lng = minLng; lng < maxLng; lng += cellSize) {
    for (let lat = minLat; lat < maxLat; lat += cellSize) {
      const cx = lng + half
      const cy = lat + half
      const inside = pointInPolygon([cx, cy], ring)
      cells.push({
        x: cx,
        y: cy,
        h: half,
        max: cellMaxDistance(cx, cy, inside) + half * Math.SQRT2
      })
    }
  }

  cells.sort((a, b) => b.max - a.max)
  let best = cells[0]
  if (!best) {
    return null
  }

  while (best.h > precision) {
    const nextHalf = best.h / 2
    let nextBest = null
    ;[
      [-nextHalf, -nextHalf],
      [nextHalf, -nextHalf],
      [-nextHalf, nextHalf],
      [nextHalf, nextHalf]
    ].forEach(([dx, dy]) => {
      const cx = best.x + dx
      const cy = best.y + dy
      const inside = pointInPolygon([cx, cy], ring)
      const cell = {
        x: cx,
        y: cy,
        h: nextHalf,
        max: cellMaxDistance(cx, cy, inside) + nextHalf * Math.SQRT2
      }
      if (!nextBest || cell.max > nextBest.max) {
        nextBest = cell
      }
    })
    best = nextBest || best
  }

  return [best.x, best.y]
}

/** 从多边形几何计算乡镇标注点（手动微调 > 面内视觉中心 > properties.centroid） */
export function getTownshipLabelPoints(geojson = townshipGeoJson) {
  return getTownshipFeatures(geojson)
    .map((feature) => {
      const props = feature.properties || {}
      const name = String(props.name || '')
      const override = TOWNSHIP_LABEL_OVERRIDES[name]
      let lngLat = null

      if (Array.isArray(override) && override.length >= 2) {
        const lng = Number(override[0])
        const lat = Number(override[1])
        if (Number.isFinite(lng) && Number.isFinite(lat)) {
          lngLat = [lng, lat]
        }
      }

      if (!lngLat) {
        const ring = getPolygonOuterRing(feature)
        lngLat = computePolygonLabelPoint(ring)
      }

      if (!lngLat) {
        const center = props.centroid || props.center
        if (!Array.isArray(center) || center.length < 2) {
          return null
        }
        const lng = Number(center[0])
        const lat = Number(center[1])
        if (!Number.isFinite(lng) || !Number.isFinite(lat)) {
          return null
        }
        lngLat = [lng, lat]
      }

      return {
        name,
        adcode: props.adcode,
        lngLat
      }
    })
    .filter(Boolean)
}

export function getTownshipBounds(feature) {
  const ring = getPolygonOuterRing(feature)
  if (!ring?.length) {
    return null
  }

  let minLng = Infinity
  let maxLng = -Infinity
  let minLat = Infinity
  let maxLat = -Infinity
  ring.forEach(([lng, lat]) => {
    minLng = Math.min(minLng, lng)
    maxLng = Math.max(maxLng, lng)
    minLat = Math.min(minLat, lat)
    maxLat = Math.max(maxLat, lat)
  })

  if (!Number.isFinite(minLng) || !Number.isFinite(maxLng) || !Number.isFinite(minLat) || !Number.isFinite(maxLat)) {
    return null
  }

  return [
    [minLng, minLat],
    [maxLng, maxLat]
  ]
}

/** 根据点击坐标命中乡镇面 */
export function findTownshipFeatureByLngLat(lngLat, geojson = townshipGeoJson) {
  const lng = Number(lngLat?.lng ?? lngLat?.[0])
  const lat = Number(lngLat?.lat ?? lngLat?.[1])
  if (!Number.isFinite(lng) || !Number.isFinite(lat)) {
    return null
  }

  return (
    getTownshipFeatures(geojson).find((feature) => {
      const ring = getPolygonOuterRing(feature)
      return ring && pointInPolygon([lng, lat], ring)
    }) || null
  )
}

export function buildTownshipInfo(feature) {
  if (!feature) {
    return null
  }
  const props = feature.properties || {}
  const name = String(props.name || '')
  const labelPoint = getTownshipLabelPoints().find((item) => item.name === name)?.lngLat || null
  const drillCenter = getTownshipDrillCenter(feature)

  return {
    name,
    adcode: props.adcode,
    center: Array.isArray(props.center) ? [...props.center] : null,
    centroid: Array.isArray(props.centroid) ? [...props.centroid] : null,
    labelPoint: labelPoint ? [...labelPoint] : null,
    drillCenter: drillCenter ? [...drillCenter] : null,
    bounds: getTownshipBounds(feature)
  }
}

/** 点击乡镇后缩放到指定级别（默认 zoom 19，中心取标注点/中心点） */
export function flyToTownship(map, feature, options = {}) {
  if (!map || !feature) {
    return false
  }

  const duration = Number(options.duration) || 900
  const zoom = Number(options.zoom ?? options.maxZoom) || 19
  const center = getTownshipDrillCenter(feature)

  if (Array.isArray(center) && center.length >= 2 && typeof map.easeTo === 'function') {
    map.easeTo({
      center,
      zoom,
      duration,
      essential: true
    })
    return true
  }

  return false
}

export function addTownshipBoundaryLayers(map, geojson = townshipGeoJson) {
  if (!map || typeof map.addSource !== 'function') {
    return false
  }
  if (map.getSource(TOWNSHIP_SOURCE_ID)) {
    return true
  }

  map.addSource(TOWNSHIP_SOURCE_ID, {
    type: 'geojson',
    data: geojson
  })

  map.addLayer({
    id: TOWNSHIP_FILL_LAYER_ID,
    type: 'fill',
    source: TOWNSHIP_SOURCE_ID,
    paint: {
      'fill-color': 'rgba(0, 0, 0, 0)',
      'fill-outline-color': 'transparent'
    }
  })

  map.addLayer({
    id: TOWNSHIP_LINE_GLOW_LAYER_ID,
    type: 'line',
    source: TOWNSHIP_SOURCE_ID,
    paint: {
      'line-color': 'rgba(0, 229, 204, 0.5)',
      'line-width': 3.5,
      'line-blur': 2
    }
  })

  map.addLayer({
    id: TOWNSHIP_LINE_LAYER_ID,
    type: 'line',
    source: TOWNSHIP_SOURCE_ID,
    paint: {
      'line-color': '#b8fff2',
      'line-width': 1.2
    }
  })

  return true
}

export function removeTownshipBoundaryLayers(map) {
  if (!map) {
    return
  }
  ;[TOWNSHIP_LINE_LAYER_ID, TOWNSHIP_LINE_GLOW_LAYER_ID, TOWNSHIP_FILL_LAYER_ID].forEach((id) => {
    if (typeof map.getLayer === 'function' && map.getLayer(id)) {
      map.removeLayer(id)
    }
  })
  if (typeof map.getSource === 'function' && map.getSource(TOWNSHIP_SOURCE_ID)) {
    map.removeSource(TOWNSHIP_SOURCE_ID)
  }
}

/** 点击乡镇面触发下钻 */
export function bindTownshipBoundaryClick(map, onSelect) {
  if (!map || typeof map.on !== 'function' || typeof onSelect !== 'function') {
    return () => {}
  }

  const resolveFeature = (eventFeature) => {
    const adcode = eventFeature?.properties?.adcode
    if (adcode == null) {
      return eventFeature
    }
    return getTownshipFeatures().find((feature) => feature.properties?.adcode === adcode) || eventFeature
  }

  const onClick = (e) => {
    if (!e.features?.length) {
      return
    }
    const feature = resolveFeature(e.features[0])
    onSelect(feature, e)
  }

  const onEnter = () => {
    if (typeof map.getCanvas === 'function') {
      map.getCanvas().style.cursor = 'pointer'
    }
  }

  const onLeave = () => {
    if (typeof map.getCanvas === 'function') {
      map.getCanvas().style.cursor = ''
    }
  }

  map.on('click', TOWNSHIP_FILL_LAYER_ID, onClick)
  map.on('mouseenter', TOWNSHIP_FILL_LAYER_ID, onEnter)
  map.on('mouseleave', TOWNSHIP_FILL_LAYER_ID, onLeave)

  return () => {
    map.off('click', TOWNSHIP_FILL_LAYER_ID, onClick)
    map.off('mouseenter', TOWNSHIP_FILL_LAYER_ID, onEnter)
    map.off('mouseleave', TOWNSHIP_FILL_LAYER_ID, onLeave)
    onLeave()
  }
}
