'use client'

import { useEffect, useRef, useState, useCallback } from 'react'

import { createLeafletMapProvider, type MapProvider, type MapBounds } from '@/lib/map'
import { useAuth } from '@/hooks/useAuth'
import { useWebSocket } from '@/hooks/useWebSocket'
import type { Place } from '@/types'
import { api } from '@/lib/api'

/**
 * Основной компонент карты. Инициализирует Яндекс.Карту, загружает места,
 * отображает маркеры и показывает карточку места при клике.
 * Для неавторизованных пользователей через WebSocket показывает точки других посетителей на карте.
 */
export default function MapView() {
  const containerRef = useRef<HTMLDivElement>(null)
  const mapRef = useRef<MapProvider | null>(null)
  const { user, isLoading } = useAuth()
  const [places, setPlaces] = useState<Place[]>([])
  const [selectedPlace, setSelectedPlace] = useState<Place | null>(null)
  const [mapError, setMapError] = useState(false)

  const fetchPlaces = useCallback(async (bounds?: MapBounds) => {
    try {
      const params = new URLSearchParams()
      if (bounds) {
        params.set('bounds', `${bounds.swLat},${bounds.swLng},${bounds.neLat},${bounds.neLng}`)
      }
      params.set('limit', '50')

      const res = await api.get<{ data: Place[] }>(`/places?${params}`)
      setPlaces(res.data)
    } catch {
      // Ошибка загрузки мест — карта продолжает работать с текущими данными
    }
  }, [])

  /** Реф для актуальной версии fetchPlaces — предотвращает проблему устаревшего замыкания */
  const fetchPlacesRef = useRef(fetchPlaces)
  fetchPlacesRef.current = fetchPlaces

  useEffect(() => {
    if (!containerRef.current || mapRef.current) return

    const provider = createLeafletMapProvider()
    mapRef.current = provider

    provider.init(containerRef.current, [37.6173, 55.7558], 10).then(() => {
      if (!provider.isReady()) {
        setMapError(true)
        return
      }

      if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(
          (pos) => {
            provider.setCenter(pos.coords.latitude, pos.coords.longitude)
            provider.addMarker('_user_location', pos.coords.latitude, pos.coords.longitude, {
              type: 'location',
            })
          },
          () => {},
        )
      }

      provider.onMove((center, zoom, bounds) => {
        fetchPlacesRef.current(bounds)
      })

      const b = provider.getBounds?.()
      if (b) fetchPlaces(b)
    }).catch(() => {
      setMapError(true)
    })

    return () => {
      provider.destroy()
      mapRef.current = null
    }
  }, [])

  useEffect(() => {
    const provider = mapRef.current
    if (!provider || !provider.isReady()) return

    const isGuest = !user
    places.forEach((place) => {
      provider.addMarker(place.id, place.lat, place.lng, {
        type: place.type as 'place' | 'studio',
        title: isGuest ? undefined : place.title,
        onClick: isGuest ? undefined : () => setSelectedPlace(place),
        ghost: isGuest,
      })
    })

    return () => {
      places.forEach((place) => provider.removeMarker(place.id))
    }
  }, [places])

  const { visitors } = useWebSocket(!user)

  useEffect(() => {
    const provider = mapRef.current
    if (!provider || !provider.isReady()) return

    visitors.forEach((v, i) => {
      provider.addMarker(`ws-visitor-${i}`, v.lat, v.lng, { type: 'visitor' })
    })

    return () => {
      visitors.forEach((_, i) => provider.removeMarker(`ws-visitor-${i}`))
    }
  }, [visitors])

  return (
    <div className="relative h-full w-full">
      {mapError ? (
        <div className="flex h-full w-full items-center justify-center">
          <div className="text-center">
            <p className="mb-2 text-lg text-white/60">Карта временно недоступна</p>
            <p className="text-sm text-white/40">Попробуйте обновить страницу позже</p>
          </div>
        </div>
      ) : (
        <div ref={containerRef} className="z-0 h-full w-full" />
      )}

      {!user && !isLoading && !mapError && (
        <div className="absolute left-1/2 top-1/2 z-10 -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white/10 px-6 py-3 text-center text-white backdrop-blur-md">
          <p className="text-sm">Зарегистрируйтесь, чтобы исследовать места для фотосъёмок</p>
        </div>
      )}

      {selectedPlace && (
        <PlaceCardModal
          place={selectedPlace}
          onClose={() => setSelectedPlace(null)}
        />
      )}
    </div>
  )
}

/**
 * Модальная карточка места, отображаемая в нижней части экрана.
 * Показывает название, адрес, описание, теги и рейтинг места.
 * @param place - Данные выбранного места
 * @param onClose - Функция закрытия карточки
 */
function PlaceCardModal({ place, onClose }: { place: Place; onClose: () => void }) {
  return (
    <div className="absolute bottom-0 left-0 right-0 z-20 max-h-[60vh] overflow-y-auto rounded-t-2xl bg-[#1e293b] p-6 shadow-xl">
      <button onClick={onClose} className="mb-4 text-white/60 hover:text-white">
        ✕
      </button>
      <h2 className="mb-2 text-xl font-bold text-white">{place.title}</h2>
      {place.address && (
        <p className="mb-2 text-sm text-white/60">{place.address}</p>
      )}
      {place.description && (
        <p className="mb-4 text-sm text-white/80">{place.description}</p>
      )}
      <div className="mb-4 flex flex-wrap gap-2">
        {place.tags?.map((tag) => (
          <span key={tag.id} className="rounded-full bg-white/10 px-3 py-1 text-xs text-white/80">
            {tag.name}
          </span>
        ))}
      </div>
      <div className="flex items-center gap-4 text-sm text-white/60">
        <span>★ {place.rating?.toFixed(1) || 'Нет оценок'}</span>
        {place.type === 'studio' && place.pricing?.hourly_rate && (
          <span>{place.pricing.hourly_rate} ₽/час</span>
        )}
      </div>
    </div>
  )
}
