import { useEffect, useMemo, useState } from 'react'
import { MapContainer, TileLayer, Popup, Tooltip, useMap, Marker } from 'react-leaflet'
import L from 'leaflet'
import { formatCurrency } from '@/lib/utils'

// 修复 Leaflet 默认 marker icon（本组件使用 CircleMarker，不需要默认 icon，但预防性修复）
delete (L.Icon.Default.prototype as any)._getIconUrl
L.Icon.Default.mergeOptions({
  iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',
  iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',
  shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',
})

const SCENE_COLORS: Record<string, string> = {
  '办公园区': '#3b82f6',
  '商场商业体': '#a855f7',
  '社区居民': '#22c55e',
  '街边综合': '#dc2626',
  '交通枢纽': '#f97316',
  '校园档口': '#06b6d4',
  '特殊业态': '#6b7280',
}

export interface StoreMapItem {
  store_code: string
  store_name: string
  site_scene: string
  latitude_gcj02: number | null
  longitude_gcj02: number | null
  received?: number | null
  monthly_received_per_sqm?: number | null
  area_sqm?: number | null
  business_address?: string | null
  district?: string | null
  action_priority?: string | null
  problem_count?: number | null
}

interface StoreMapProps {
  stores: StoreMapItem[]
  height?: number
}

/**
 * 自动适配地图视野到所有标记点
 */
function FitBounds({ points }: { points: [number, number][] }) {
  const map = useMap()
  useEffect(() => {
    // 只适配北京区域内的点，避免外地门店导致地图缩放过远
    const beijingPoints = points.filter(([lat, lng]) =>
      lat >= 39.4 && lat <= 41.1 && lng >= 115.4 && lng <= 117.4
    )
    const targetPoints = beijingPoints.length > 0 ? beijingPoints : points
    if (targetPoints.length === 0) return
    if (targetPoints.length === 1) {
      map.setView(targetPoints[0], 13)
    } else {
      const bounds = L.latLngBounds(targetPoints)
      map.fitBounds(bounds, { padding: [30, 30] })
    }
  }, [points, map])
  return null
}

/** 门店类型 → 形状 */
type StoreCategory = 'benchmark' | 'normal' | 'p1' | 'p0'

type ShapeType = 'circle' | 'triangle' | 'square' | 'diamond'

const CATEGORY_SHAPES: { key: StoreCategory; label: string; shape: ShapeType; match: (s: StoreMapItem) => boolean }[] = [
  { key: 'benchmark', label: '标杆门店', shape: 'circle', match: (s) => !s.action_priority?.startsWith('P0') && !s.action_priority?.startsWith('P1') && (s.problem_count ?? 99) <= 1 },
  { key: 'normal', label: '正常门店', shape: 'diamond', match: (s) => !s.action_priority?.startsWith('P0') && !s.action_priority?.startsWith('P1') && (s.problem_count ?? 99) > 1 },
  { key: 'p1', label: 'P1 重点整改', shape: 'triangle', match: (s) => !!s.action_priority?.startsWith('P1') },
  { key: 'p0', label: 'P0 紧急整改', shape: 'square', match: (s) => !!s.action_priority?.startsWith('P0') },
]

/** 创建 SVG 形状图标 */
function createShapeIcon(shape: ShapeType, color: string, size: number): L.DivIcon {
  const half = size / 2
  let svg = ''
  if (shape === 'circle') {
    svg = `<circle cx="${half}" cy="${half}" r="${half - 1}" fill="${color}" fill-opacity="0.85" stroke="${color}" stroke-width="2"/>`
  } else if (shape === 'triangle') {
    svg = `<polygon points="${half},1 ${size - 1},${size - 1} 1,${size - 1}" fill="${color}" fill-opacity="0.85" stroke="${color}" stroke-width="2"/>`
  } else if (shape === 'square') {
    svg = `<rect x="2" y="2" width="${size - 4}" height="${size - 4}" fill="${color}" fill-opacity="0.85" stroke="${color}" stroke-width="2"/>`
  } else {
    svg = `<polygon points="${half},1 ${size - 1},${half} ${half},${size - 1} 1,${half}" fill="${color}" fill-opacity="0.85" stroke="${color}" stroke-width="2"/>`
  }
  return L.divIcon({
    className: 'store-shape-marker',
    html: `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" style="filter: drop-shadow(0 1px 2px rgba(0,0,0,0.3));">${svg}</svg>`,
    iconSize: [size, size],
    iconAnchor: [half, half],
  })
}

/** 形状图例 */
function ShapeGlyph({ shape, color }: { shape: ShapeType; color: string }) {
  if (shape === 'circle') return <span className="inline-block h-2.5 w-2.5 rounded-full" style={{ background: color }} />
  if (shape === 'triangle') return <span className="inline-block h-0 w-0" style={{ borderLeft: '5px solid transparent', borderRight: '5px solid transparent', borderBottom: `8px solid ${color}` }} />
  if (shape === 'square') return <span className="inline-block h-2.5 w-2.5 rounded-sm" style={{ background: color }} />
  return <span className="inline-block h-2.5 w-2.5 rotate-45 rounded-sm" style={{ background: color }} />
}

/**
 * 门店分布地图组件
 * 使用 Leaflet + 高德地图瓦片渲染门店地理分布
 * 数据库存储 GCJ-02 坐标，高德地图原生支持 GCJ-02，无需坐标转换
 * 支持排除多选叠加：点击按钮排除该类型，可叠加排除多个类型
 */
export function StoreMap({ stores, height = 400 }: StoreMapProps) {
  const [excluded, setExcluded] = useState<Set<StoreCategory>>(new Set())

  const toggleExclude = (key: StoreCategory) => {
    setExcluded((prev) => {
      const next = new Set(prev)
      if (next.has(key)) {
        next.delete(key)
      } else {
        // 至少保留一个有数据可显示的类型
        const activeKeys = CATEGORY_SHAPES.filter((f) => stores.some((s) => s.latitude_gcj02 != null && f.match(s)))
        const remaining = activeKeys.filter((f) => !next.has(f.key) && f.key !== key)
        if (remaining.length === 0) return prev
        next.add(key)
      }
      return next
    })
  }

  const points = useMemo(() => {
    return stores
      .filter((s) => s.latitude_gcj02 != null && s.longitude_gcj02 != null)
      .filter((s) => {
        // 排除被选中的类型
        return !CATEGORY_SHAPES.some((f) => excluded.has(f.key) && f.match(s))
      })
      .map((s) => {
        return { store: s, lat: Number(s.latitude_gcj02), lng: Number(s.longitude_gcj02) }
      })
  }, [stores, excluded])

  const latLngs = useMemo(() => points.map((p) => [p.lat, p.lng] as [number, number]), [points])

  if (points.length === 0) {
    return (
      <div className="flex items-center justify-center rounded border bg-muted/30 text-sm text-muted-foreground" style={{ height }}>
        暂无门店坐标数据
      </div>
    )
  }

  return (
    <div className="space-y-2">
      {/* 排除按钮 — 形状图例 */}
      <div className="flex flex-wrap items-center gap-2">
        <span className="text-xs text-muted-foreground">点击排除：</span>
        {CATEGORY_SHAPES.map((f) => {
          const count = stores.filter((s) => s.latitude_gcj02 != null && f.match(s)).length
          if (count === 0) return null
          const isExcluded = excluded.has(f.key)
          return (
            <button
              key={f.key}
              onClick={() => toggleExclude(f.key)}
              className={`flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium transition-all ${
                isExcluded ? 'opacity-40 line-through' : 'hover:bg-muted'
              }`}
            >
              <ShapeGlyph shape={f.shape} color="#6b7280" />
              {f.label} ({count})
            </button>
          )
        })}
        {excluded.size > 0 && (
          <button
            onClick={() => setExcluded(new Set())}
            className="rounded-md border px-2.5 py-1 text-xs font-medium text-primary hover:bg-primary/10"
          >
            重置
          </button>
        )}
      </div>

      {/* 场景颜色图例 */}
      <div className="flex flex-wrap gap-3 text-xs">
        {Object.entries(SCENE_COLORS).map(([scene, color]) => {
          const count = stores.filter((s) => s.latitude_gcj02 != null && s.site_scene === scene).length
          if (count === 0) return null
          return (
            <span key={scene} className="flex items-center gap-1">
              <span className="inline-block h-3 w-3 rounded-full" style={{ background: color }} />
              {scene} ({count})
            </span>
          )
        })}
      </div>

      <div style={{ height, borderRadius: '0.5rem', overflow: 'hidden' }}>
      <MapContainer
        center={[39.9, 116.4]}
        zoom={11}
        style={{ height: '100%', width: '100%' }}
        scrollWheelZoom={true}
      >
        <TileLayer
          attribution='&copy; 高德地图'
          url="https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"
          subdomains={['1', '2', '3', '4']}
        />
        <FitBounds points={latLngs} />
        {points.map(({ store, lat, lng }) => {
          const cat = CATEGORY_SHAPES.find((f) => f.match(store))
          const shape = cat?.shape || 'circle'
          const color = SCENE_COLORS[store.site_scene] || '#999'
          const size = store.received ? Math.max(12, Math.min(24, Math.sqrt(Number(store.received)) / 15)) : 14
          const icon = createShapeIcon(shape, color, size)
          return (
            <Marker
              key={store.store_code}
              position={[lat, lng]}
              icon={icon}
            >
              <Popup>
                <div className="min-w-[200px] text-xs">
                  <p className="mb-1 font-bold text-sm">{store.store_name}</p>
                  <p>场景: <span className="font-medium" style={{ color }}>{store.site_scene}</span></p>
                  <p>类型: {cat?.label || '未知'}</p>
                  {store.district && <p>区域: {store.district}</p>}
                  {store.business_address && <p>地址: {store.business_address}</p>}
                  {store.area_sqm && <p>面积: {store.area_sqm}㎡</p>}
                  {store.received != null && <p>实收: {formatCurrency(Number(store.received))}</p>}
                  {store.monthly_received_per_sqm != null && (
                    <p>坪效: {formatCurrency(Number(store.monthly_received_per_sqm))}</p>
                  )}
                  {store.action_priority && (
                    <p>优先级: <span className="font-medium" style={{ color: store.action_priority.startsWith('P0') ? '#ef4444' : store.action_priority.startsWith('P1') ? '#f97316' : '#22c55e' }}>{store.action_priority}</span></p>
                  )}
                  {store.problem_count != null && <p>问题数: {store.problem_count}</p>}
                </div>
              </Popup>
              <Tooltip direction="top" offset={[0, -8]}>
                {store.store_name}
              </Tooltip>
            </Marker>
          )
        })}
      </MapContainer>
      </div>
    </div>
  )
}
