'use client'

import React, { useEffect, useRef, useState, useCallback } from 'react'
import { motion, useReducedMotion } from 'framer-motion'
import { SpotCard } from '@/components/ui/SpotCard'
import type { Difficulty } from '@/components/ui/SpotCard'

interface MapSpot {
  id: string
  name: string
  description: string
  difficulty: Difficulty
  coverImage: string | null
  tags: string[]
  avgRating: number | null
  reviewCount: number
  lat: number
  lng: number
}

interface SpotsMapListProps {
  spots: MapSpot[]
  emptyMessage?: string
}

const DIFF_MARKER: Record<string, string> = {
  BEGINNER:     '/brand/markers/ondevoar-marker-livre.svg',
  INTERMEDIATE: '/brand/markers/ondevoar-marker-condicionada.svg',
  ADVANCED:     '/brand/markers/ondevoar-marker-proibida.svg',
  EXPERT:       '/brand/markers/ondevoar-marker-proibida.svg',
}

export function SpotsMapList({ spots, emptyMessage = 'Nenhum spot encontrado.' }: SpotsMapListProps) {
  const reduced = useReducedMotion()
  const [hoveredId, setHoveredId] = useState<string | null>(null)
  const [mobileView, setMobileView] = useState<'list' | 'map'>('list')

  const mapContainer = useRef<HTMLDivElement>(null)
  const mapRef = useRef<any>(null)
  const markersRef = useRef<Record<string, any>>({})
  const leafletRef = useRef<any>(null)
  const cardRefs = useRef<Record<string, HTMLDivElement | null>>({})

  const makeIcon = useCallback((L: any, difficulty: string, active: boolean) => {
    const url = active
      ? '/brand/markers/ondevoar-pin-azul.svg'
      : (DIFF_MARKER[difficulty] ?? '/brand/markers/ondevoar-marker-azul.svg')
    return L.icon({
      iconUrl: url,
      iconSize: active ? [36, 46] : [28, 36],
      iconAnchor: active ? [18, 46] : [14, 36],
      popupAnchor: [0, -40],
    })
  }, [])

  // Update marker icons when hover changes
  useEffect(() => {
    const L = leafletRef.current
    if (!L) return
    Object.entries(markersRef.current).forEach(([id, marker]) => {
      const spot = spots.find((s) => s.id === id)
      if (!spot) return
      const active = id === hoveredId
      marker.setIcon(makeIcon(L, spot.difficulty, active))
      marker.setZIndexOffset(active ? 1000 : 0)
    })
  }, [hoveredId, spots, makeIcon])

  // Init map once
  useEffect(() => {
    if (!mapContainer.current || mapRef.current || spots.length === 0) return
    let destroyed = false

    ;(async () => {
      const L = (await import('leaflet')).default
      // @ts-ignore
      await import('leaflet/dist/leaflet.css')
      if (destroyed || !mapContainer.current) return

      leafletRef.current = L

      const map = L.map(mapContainer.current!, {
        center: [39.4, -8.2],
        zoom: 7,
        zoomControl: true,
        scrollWheelZoom: true,
        attributionControl: false,
      })
      mapRef.current = map

      L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
        subdomains: 'abcd', maxZoom: 19,
      }).addTo(map)

      L.control.attribution({ position: 'bottomright', prefix: '' }).addTo(map)

      spots.forEach((spot) => {
        const marker = L.marker([spot.lat, spot.lng], { icon: makeIcon(L, spot.difficulty, false) })
          .bindPopup(
            `<div style="font-family:sans-serif;min-width:160px">
              <a href="/spots/${spot.id}" style="font-weight:700;font-size:13px;color:#0096FF;text-decoration:none;display:block;margin-bottom:3px">${spot.name}</a>
              <span style="font-size:11px;color:#64748B">${spot.difficulty === 'BEGINNER' ? 'Iniciante' : spot.difficulty === 'INTERMEDIATE' ? 'Intermédio' : 'Avançado'}</span>
            </div>`,
            { maxWidth: 220 }
          )
          .addTo(map)

        marker.on('click', () => {
          setHoveredId(spot.id)
          cardRefs.current[spot.id]?.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
        })
        marker.on('mouseover', () => setHoveredId(spot.id))
        marker.on('mouseout', () => setHoveredId(null))

        markersRef.current[spot.id] = marker
      })

      if (spots.length > 1) {
        map.fitBounds(
          L.latLngBounds(spots.map((s) => [s.lat, s.lng] as [number, number])),
          { padding: [40, 40], maxZoom: 12 }
        )
      } else if (spots.length === 1) {
        map.setView([spots[0].lat, spots[0].lng], 12)
      }
    })()

    return () => {
      destroyed = true
      if (mapRef.current) { mapRef.current.remove(); mapRef.current = null }
      markersRef.current = {}
      leafletRef.current = null
    }
  }, []) // eslint-disable-line react-hooks/exhaustive-deps

  if (spots.length === 0) {
    return (
      <div style={{ textAlign: 'center', padding: 'var(--ov-space-20)', color: 'var(--ov-slate)', fontFamily: 'var(--ov-font-sans)' }}>
        {emptyMessage}
      </div>
    )
  }

  const container = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.05 } } }
  const item = { hidden: { opacity: 0, y: 14 }, visible: { opacity: 1, y: 0, transition: { duration: 0.2 } } }

  return (
    <div className="sml-root">
      {/* Mobile toggle */}
      <div className="sml-mobile-toggle">
        <button
          className={`sml-toggle-btn${mobileView === 'list' ? ' active' : ''}`}
          onClick={() => setMobileView('list')}
          aria-pressed={mobileView === 'list'}
        >
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
          Lista
        </button>
        <button
          className={`sml-toggle-btn${mobileView === 'map' ? ' active' : ''}`}
          onClick={() => setMobileView('map')}
          aria-pressed={mobileView === 'map'}
        >
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
          Mapa
        </button>
      </div>

      <div className="sml-layout">
        {/* Scrollable list */}
        <div className={`sml-list${mobileView === 'map' ? ' sml-hidden-mobile' : ''}`}>
          <p className="sml-count">{spots.length} spot{spots.length !== 1 ? 's' : ''}</p>
          <motion.div
            className="sml-grid"
            variants={reduced ? undefined : container}
            initial="hidden"
            animate="visible"
          >
            {spots.map((spot) => (
              <motion.div
                key={spot.id}
                variants={reduced ? undefined : item}
                ref={(el) => { cardRefs.current[spot.id] = el }}
                className={`sml-card-wrap${hoveredId === spot.id ? ' sml-card-active' : ''}`}
                onMouseEnter={() => { setHoveredId(spot.id); markersRef.current[spot.id]?.openPopup() }}
                onMouseLeave={() => { setHoveredId(null); markersRef.current[spot.id]?.closePopup() }}
              >
                <SpotCard spot={spot} />
              </motion.div>
            ))}
          </motion.div>
        </div>

        {/* Sticky map column */}
        <div className={`sml-map-col${mobileView === 'list' ? ' sml-hidden-mobile' : ''}`}>
          <div className="sml-map-sticky">
            <div ref={mapContainer} className="sml-map" />
          </div>
        </div>
      </div>
    </div>
  )
}
