import { useState, useMemo, useCallback, useEffect, useRef } from 'react'
import { Map, useControl, useMap } from '@vis.gl/react-maplibre'
import { MapboxOverlay } from '@deck.gl/mapbox'
import { PathLayer, ScatterplotLayer } from '@deck.gl/layers'
import type { StyleSpecification } from 'maplibre-gl'
import 'maplibre-gl/dist/maplibre-gl.css'
import type { ScatSegment } from './scatTypes'
import type { ApiZoneItem } from '../services/scatApi'
import { esiColor, jejuCoastCoords } from './scatConstants'
import { hexToRgba } from '@common/components/map/mapUtils'

const BASE_STYLE: StyleSpecification = {
  version: 8,
  sources: {
    'carto-dark': {
      type: 'raster',
      tiles: [
        'https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png',
        'https://b.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png',
        'https://c.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png',
      ],
      tileSize: 256,
      attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OSM</a> &copy; <a href="https://carto.com/">CARTO</a>',
    },
  },
  layers: [{ id: 'carto-dark-layer', type: 'raster', source: 'carto-dark' }],
}

interface ScatMapProps {
  segments: ScatSegment[]
  zones: ApiZoneItem[]
  selectedSeg: ScatSegment
  jurisdictionFilter: string
  onSelectSeg: (s: ScatSegment) => void
  onOpenPopup: (idx: number) => void
}

// ── DeckGLOverlay ──────────────────────────────────────
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function DeckGLOverlay({ layers }: { layers: any[] }) {
  const overlay = useControl<MapboxOverlay>(() => new MapboxOverlay({ interleaved: true }))
  overlay.setProps({ layers })
  return null
}

// ── FlyTo Controller: 선택 구간 변경 시 맵 이동 ─────────
function FlyToController({ selectedSeg, zones }: { selectedSeg: ScatSegment; zones: ApiZoneItem[] }) {
  const { current: map } = useMap()
  const prevIdRef = useRef<number | undefined>(undefined)
  const prevZonesLenRef = useRef<number>(0)

  // 선택 구간 변경 시
  useEffect(() => {
    if (!map) return
    if (prevIdRef.current !== undefined && prevIdRef.current !== selectedSeg.id) {
      map.flyTo({ center: [selectedSeg.lng, selectedSeg.lat], zoom: 12, duration: 600 })
    }
    prevIdRef.current = selectedSeg.id
  }, [map, selectedSeg])

  // 관할해경(zones) 변경 시 지도 중심 이동
  useEffect(() => {
    if (!map || zones.length === 0) return
    if (prevZonesLenRef.current === zones.length) return
    prevZonesLenRef.current = zones.length
    const validZones = zones.filter(z => z.latCenter && z.lngCenter)
    if (validZones.length === 0) return
    const avgLat = validZones.reduce((a, z) => a + z.latCenter, 0) / validZones.length
    const avgLng = validZones.reduce((a, z) => a + z.lngCenter, 0) / validZones.length
    map.flyTo({ center: [avgLng, avgLat], zoom: 9, duration: 800 })
  }, [map, zones])

  return null
}

// ── 줌 기반 스케일 계산 ─────────────────────────────────
function getZoomScale(zoom: number) {
  const zScale = Math.max(0, zoom - 9) / 5
  return {
    polyWidth: 1 + zScale * 4,
    selPolyWidth: 2 + zScale * 5,
    glowWidth: 4 + zScale * 14,
    halfLenScale: 0.15 + zScale * 0.85,
    markerRadius: Math.round(6 + zScale * 16),
    showStatusMarker: zoom >= 11,
  }
}

// ── 세그먼트 폴리라인 좌표 생성 (lng, lat 순서) ──────────
function buildSegCoords(seg: ScatSegment, halfLenScale: number): [number, number][] {
  const coastIdx = seg.id % (jejuCoastCoords.length - 1)
  const [clat1, clng1] = jejuCoastCoords[coastIdx]
  const [clat2, clng2] = jejuCoastCoords[(coastIdx + 1) % jejuCoastCoords.length]
  const dlat = clat2 - clat1
  const dlng = clng2 - clng1
  const dist = Math.sqrt(dlat * dlat + dlng * dlng)
  const nDlat = dist > 0 ? dlat / dist : 0
  const nDlng = dist > 0 ? dlng / dist : 1
  const halfLen = Math.min(seg.lengthM / 200000, 0.012) * halfLenScale
  return [
    [seg.lng - nDlng * halfLen, seg.lat - nDlat * halfLen],
    [seg.lng, seg.lat],
    [seg.lng + nDlng * halfLen, seg.lat + nDlat * halfLen],
  ]
}

// ── 툴팁 상태 ───────────────────────────────────────────
interface TooltipState {
  x: number
  y: number
  seg: ScatSegment
}

// ── ScatMap ─────────────────────────────────────────────
function ScatMap({ segments, zones, selectedSeg, jurisdictionFilter, onSelectSeg, onOpenPopup }: ScatMapProps) {
  const [zoom, setZoom] = useState(10)
  const [tooltip, setTooltip] = useState<TooltipState | null>(null)

  const handleClick = useCallback(
    (seg: ScatSegment) => {
      onSelectSeg(seg)
      onOpenPopup(seg.id)
    },
    [onSelectSeg, onOpenPopup],
  )

  const zs = useMemo(() => getZoomScale(zoom), [zoom])

  // 제주도 해안선 레퍼런스 라인
  const coastlineLayer = useMemo(
    () =>
      new PathLayer({
        id: 'jeju-coastline',
        data: [{ path: jejuCoastCoords.map(([lat, lng]) => [lng, lat] as [number, number]) }],
        getPath: (d: { path: [number, number][] }) => d.path,
        getColor: [6, 182, 212, 46],
        getWidth: 1.5,
        getDashArray: [8, 6],
        dashJustified: true,
        widthMinPixels: 1,
      }),
    [],
  )

  // 선택된 구간 글로우 레이어
  const glowLayer = useMemo(
    () =>
      new PathLayer({
        id: 'scat-glow',
        data: [selectedSeg],
        getPath: (d: ScatSegment) => buildSegCoords(d, zs.halfLenScale),
        getColor: [34, 197, 94, 38],
        getWidth: zs.glowWidth,
        capRounded: true,
        jointRounded: true,
        widthMinPixels: 4,
        updateTriggers: {
          getPath: [zs.halfLenScale],
          getWidth: [zs.glowWidth],
        },
      }),
    [selectedSeg, zs.glowWidth, zs.halfLenScale],
  )

  // ESI 색상 세그먼트 폴리라인
  const segPathLayer = useMemo(
    () =>
      new PathLayer({
        id: 'scat-segments',
        data: segments,
        getPath: (d: ScatSegment) => buildSegCoords(d, zs.halfLenScale),
        getColor: (d: ScatSegment) => {
          const isSelected = selectedSeg.id === d.id
          const hexCol = isSelected ? '#22c55e' : esiColor(d.esiNum)
          return hexToRgba(hexCol, isSelected ? 242 : 178)
        },
        getWidth: (d: ScatSegment) => (selectedSeg.id === d.id ? zs.selPolyWidth : zs.polyWidth),
        capRounded: true,
        jointRounded: true,
        widthMinPixels: 1,
        pickable: true,
        onHover: (info: { object?: ScatSegment; x: number; y: number }) => {
          if (info.object) {
            setTooltip({ x: info.x, y: info.y, seg: info.object })
          } else {
            setTooltip(null)
          }
        },
        onClick: (info: { object?: ScatSegment }) => {
          if (info.object) handleClick(info.object)
        },
        updateTriggers: {
          getColor: [selectedSeg.id],
          getWidth: [selectedSeg.id, zs.selPolyWidth, zs.polyWidth],
          getPath: [zs.halfLenScale],
        },
      }),
    [segments, selectedSeg, zs, handleClick],
  )

  // 조사 상태 마커 (줌 >= 11 시 표시)
  const markerLayer = useMemo(() => {
    if (!zs.showStatusMarker) return null
    return new ScatterplotLayer({
      id: 'scat-status-markers',
      data: segments,
      getPosition: (d: ScatSegment) => [d.lng, d.lat],
      getRadius: zs.markerRadius,
      getFillColor: (d: ScatSegment) => {
        if (d.status === '완료') return [34, 197, 94, 51]
        if (d.status === '진행중') return [234, 179, 8, 51]
        return [100, 116, 139, 51]
      },
      getLineColor: (d: ScatSegment) => {
        if (d.status === '완료') return [34, 197, 94, 200]
        if (d.status === '진행중') return [234, 179, 8, 200]
        return [100, 116, 139, 200]
      },
      getLineWidth: 1,
      stroked: true,
      radiusMinPixels: 4,
      radiusMaxPixels: 22,
      radiusUnits: 'pixels',
      pickable: true,
      onClick: (info: { object?: ScatSegment }) => {
        if (info.object) handleClick(info.object)
      },
      updateTriggers: {
        getRadius: [zs.markerRadius],
      },
    })
  }, [segments, zs.showStatusMarker, zs.markerRadius, handleClick])

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const deckLayers: any[] = useMemo(() => {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const layers: any[] = [coastlineLayer, glowLayer, segPathLayer]
    if (markerLayer) layers.push(markerLayer)
    return layers
  }, [coastlineLayer, glowLayer, segPathLayer, markerLayer])

  const doneCount = segments.filter(s => s.status === '완료').length
  const progCount = segments.filter(s => s.status === '진행중').length
  const totalLen = segments.reduce((a, s) => a + s.lengthM, 0)
  const doneLen = segments.filter(s => s.status === '완료').reduce((a, s) => a + s.lengthM, 0)
  const highSens = segments
    .filter(s => s.sensitivity === '최상' || s.sensitivity === '상')
    .reduce((a, s) => a + s.lengthM, 0)
  const donePct = Math.round((doneCount / segments.length) * 100)
  const progPct = Math.round((progCount / segments.length) * 100)
  const notPct = 100 - donePct - progPct

  return (
    <div className="absolute inset-0 overflow-hidden">
      <Map
        initialViewState={(() => {
          if (zones.length > 0) {
            const avgLng = zones.reduce((a, z) => a + z.lngCenter, 0) / zones.length;
            const avgLat = zones.reduce((a, z) => a + z.latCenter, 0) / zones.length;
            return { longitude: avgLng, latitude: avgLat, zoom: 10 };
          }
          return { longitude: 126.55, latitude: 33.38, zoom: 10 };
        })()}
        mapStyle={BASE_STYLE}
        className="w-full h-full"
        attributionControl={false}
        onZoom={e => setZoom(e.viewState.zoom)}
      >
        <DeckGLOverlay layers={deckLayers} />
        <FlyToController selectedSeg={selectedSeg} zones={zones} />
      </Map>

      {/* 호버 툴팁 */}
      {tooltip && (
        <div
          className="pointer-events-none"
          style={{
            position: 'absolute',
            left: tooltip.x + 12,
            top: tooltip.y - 48,
            background: 'rgba(15,21,36,0.92)',
            border: '1px solid rgba(30,42,66,0.8)',
            color: '#e4e8f1',
            borderRadius: 6,
            padding: '4px 8px',
            boxShadow: '0 4px 12px rgba(0,0,0,0.4)',
            fontSize: 11,
            fontFamily: "'Noto Sans KR', sans-serif",
            zIndex: 1000,
            whiteSpace: 'nowrap',
          }}
        >
          <div style={{ fontWeight: 700 }}>
            {tooltip.seg.code} {tooltip.seg.area}
          </div>
          <div style={{ fontSize: 10, opacity: 0.7 }}>
            ESI {tooltip.seg.esi} · {tooltip.seg.length} ·{' '}
            {tooltip.seg.status === '완료' ? '✓' : tooltip.seg.status === '진행중' ? '⏳' : '—'}{' '}
            {tooltip.seg.status}
          </div>
        </div>
      )}

      {/* Status chips */}
      <div className="absolute top-3.5 left-3.5 flex gap-2 z-[1000]">
        <div className="flex items-center gap-1.5 px-3 py-1.5 bg-[rgba(18,25,41,0.92)] backdrop-blur-xl border border-border rounded-full text-[11px] text-text-2 font-korean">
          <span className="w-1.5 h-1.5 rounded-full bg-status-green shadow-[0_0_6px_var(--green)]" />
          Pre-SCAT 사전조사
        </div>
        <div className="flex items-center gap-1.5 px-3 py-1.5 bg-[rgba(18,25,41,0.92)] backdrop-blur-xl border border-border rounded-full text-[11px] text-text-2 font-korean">
          {jurisdictionFilter || '전체'} 관할 해안 · {segments.length}개 구간
        </div>
      </div>

      {/* Right info cards */}
      <div className="absolute top-3.5 right-3.5 w-[260px] flex flex-col gap-2 z-[1000] max-h-[calc(100%-100px)] overflow-y-auto scrollbar-thin">
        {/* ESI Legend */}
        <div className="bg-[rgba(18,25,41,0.92)] backdrop-blur-xl border border-border rounded-md p-3.5 shadow-[0_4px_20px_rgba(0,0,0,0.3)]">
          <div className="text-[10px] font-bold uppercase tracking-wider text-text-3 mb-2.5">ESI 민감도 분류 범례</div>
          {[
            { esi: 'ESI 10', label: '갯벌·습지·맹그로브', color: '#991b1b' },
            { esi: 'ESI 9', label: '쉘터 갯벌', color: '#b91c1c' },
            { esi: 'ESI 8', label: '쉘터 암반 해안', color: '#dc2626' },
            { esi: 'ESI 7', label: '노출 갯벌', color: '#ef4444' },
            { esi: 'ESI 6', label: '자갈·혼합 해안', color: '#f97316' },
            { esi: 'ESI 5', label: '혼합 모래/자갈', color: '#fb923c' },
            { esi: 'ESI 3-4', label: '모래 해안', color: '#facc15' },
            { esi: 'ESI 1-2', label: '암반·인공 구조물', color: '#4ade80' },
          ].map((item, i) => (
            <div key={i} className="flex items-center gap-2 py-1 text-[11px]">
              <span className="w-3.5 h-1.5 rounded-sm flex-shrink-0" style={{ background: item.color }} />
              <span className="text-text-2 font-korean">{item.label}</span>
              <span className="ml-auto font-mono text-[10px] text-text-1">{item.esi}</span>
            </div>
          ))}
        </div>

        {/* Progress */}
        <div className="bg-[rgba(18,25,41,0.92)] backdrop-blur-xl border border-border rounded-md p-3.5 shadow-[0_4px_20px_rgba(0,0,0,0.3)]">
          <div className="text-[10px] font-bold uppercase tracking-wider text-text-3 mb-2.5">조사 진행률</div>
          <div className="flex gap-0.5 h-3 rounded overflow-hidden mb-1">
            <div className="h-full transition-all duration-500" style={{ width: `${donePct}%`, background: 'var(--green)' }} />
            <div className="h-full transition-all duration-500" style={{ width: `${progPct}%`, background: 'var(--orange)' }} />
            <div className="h-full transition-all duration-500" style={{ width: `${notPct}%`, background: 'var(--bd)' }} />
          </div>
          <div className="flex justify-between mt-1">
            <span className="text-[9px] font-mono text-status-green">완료 {donePct}%</span>
            <span className="text-[9px] font-mono text-status-orange">진행 {progPct}%</span>
            <span className="text-[9px] font-mono text-text-3">미조사 {notPct}%</span>
          </div>
          <div className="mt-2.5">
            {[
              ['총 해안선', `${(totalLen / 1000).toFixed(1)} km`, ''],
              ['조사 완료', `${(doneLen / 1000).toFixed(1)} km`, 'var(--green)'],
              ['고민감 구간', `${(highSens / 1000).toFixed(1)} km`, 'var(--red)'],
              ['방제 우선 구간', `${segments.filter(s => s.sensitivity === '최상').length}개`, 'var(--orange)'],
            ].map(([label, val, color], i) => (
              <div key={i} className="flex justify-between py-1.5 border-b border-[rgba(30,42,74,0.3)] last:border-b-0 text-[11px]">
                <span className="text-text-2 font-korean">{label}</span>
                <span className="font-mono font-medium text-[11px]" style={{ color: color || undefined }}>
                  {val}
                </span>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Coordinates */}
      {/* <div className="absolute bottom-3 left-3 z-[1000] bg-[rgba(18,25,41,0.85)] backdrop-blur-xl border border-border rounded-sm px-3 py-1.5 font-mono text-[11px] text-text-2 flex gap-3.5">
        <span>
          위도 <span className="text-status-green font-medium">{selectedSeg.lat.toFixed(4)}°N</span>
        </span>
        <span>
          경도 <span className="text-status-green font-medium">{selectedSeg.lng.toFixed(4)}°E</span>
        </span>
        <span>
          축척 <span className="text-status-green font-medium">1:25,000</span>
        </span>
      </div> */}
    </div>
  )
}

export default ScatMap
