import { useRef, useState, useEffect, useCallback, useMemo } from 'react'
import { Plus } from 'lucide-react'
import JourneyMap from './JourneyMap'
import MobileEntryCard from './MobileEntryCard'
import type { JourneyMapHandle } from './JourneyMap'
import type { JourneyEntry } from '../../store/journeyStore'
import { DAY_COLORS } from './dayColors'

interface MapEntry {
  id: string
  lat: number
  lng: number
  title?: string | null
  mood?: string | null
  entry_date: string
}

interface Props {
  entries: JourneyEntry[] | any[]
  mapEntries: MapEntry[]
  trail?: { lat: number; lng: number }[]
  dark?: boolean
  readOnly?: boolean
  onEntryClick: (entry: any) => void
  onAddEntry?: () => void
  publicPhotoUrl?: (photoId: number) => string
  carouselBottom?: string
}

export default function MobileMapTimeline({
  entries,
  mapEntries,
  trail,
  dark,
  readOnly,
  onEntryClick,
  onAddEntry,
  publicPhotoUrl,
  carouselBottom = 'calc(var(--bottom-nav-h, 84px) + 8px)',
}: Props) {
  const mapRef = useRef<JourneyMapHandle>(null)
  const carouselRef = useRef<HTMLDivElement>(null)
  const [activeIndex, setActiveIndex] = useState(0)

  const entryDayMeta = useMemo(() => {
    const uniqueDates = [...new Set(entries.map((e: any) => e.entry_date).sort())]
    const counters = new Map<string, number>()
    return entries.map((e: any) => {
      const dayIdx = uniqueDates.indexOf(e.entry_date)
      const dayLabel = (counters.get(e.entry_date) ?? 0) + 1
      counters.set(e.entry_date, dayLabel)
      return { dayLabel, dayColor: DAY_COLORS[dayIdx % DAY_COLORS.length] }
    })
  }, [entries])
  const cardRefs = useRef<Map<number, HTMLDivElement>>(new Map())
  // Sync map focus when carousel scrolls (with guard for uninitialized map)
  const syncMapToCarousel = useCallback((index: number) => {
    const entry = entries[index]
    if (!entry) return

    const mapEntry = mapEntries.find(m => String(m.id) === String(entry.id))
    if (mapEntry) {
      try { mapRef.current?.focusMarker(String(mapEntry.id)) } catch {}
    } else {
      try { mapRef.current?.highlightMarker(null) } catch {}
    }
  }, [entries, mapEntries])

  // Pick the card that's currently closest to the carousel horizontal center.
  // More stable than IntersectionObserver thresholds when the active card can
  // drift toward the viewport edge with proximity snapping.
  const pickNearestCard = useCallback(() => {
    const el = carouselRef.current
    if (!el) return
    const containerCenter = el.getBoundingClientRect().left + el.clientWidth / 2
    let bestIdx = 0
    let bestDist = Infinity
    cardRefs.current.forEach((node, idx) => {
      const r = node.getBoundingClientRect()
      const cardCenter = r.left + r.width / 2
      const d = Math.abs(cardCenter - containerCenter)
      if (d < bestDist) { bestDist = d; bestIdx = idx }
    })
    setActiveIndex(prev => {
      if (prev !== bestIdx) syncMapToCarousel(bestIdx)
      return bestIdx
    })
  }, [syncMapToCarousel])

  // Defer all state updates until scrolling settles — updating activeIndex
  // mid-swipe resizes cards (240→320px), causing layout reflow every frame.
  useEffect(() => {
    const el = carouselRef.current
    if (!el || entries.length === 0) return
    let settleTimer: number | null = null
    const onScroll = () => {
      if (settleTimer != null) window.clearTimeout(settleTimer)
      settleTimer = window.setTimeout(pickNearestCard, 150)
    }
    el.addEventListener('scroll', onScroll, { passive: true })
    return () => {
      el.removeEventListener('scroll', onScroll)
      if (settleTimer != null) window.clearTimeout(settleTimer)
    }
  }, [entries.length, pickNearestCard])

  // Scroll a given card into the horizontal center of the carousel
  const scrollCardIntoCenter = useCallback((idx: number) => {
    const card = cardRefs.current.get(idx)
    card?.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'nearest' })
  }, [])

  // Scroll carousel to entry when map marker is clicked
  const handleMarkerClick = useCallback((id: string) => {
    const idx = entries.findIndex((e: any) => String(e.id) === id)
    if (idx === -1) return
    setActiveIndex(idx)
    scrollCardIntoCenter(idx)
  }, [entries, scrollCardIntoCenter])

  // Tap on a card: if it's already active, open the edit view; otherwise
  // activate + center it first (don't jump straight into the editor).
  const handleCardTap = useCallback((entry: any, idx: number) => {
    if (idx === activeIndex) {
      onEntryClick(entry)
    } else {
      setActiveIndex(idx)
      scrollCardIntoCenter(idx)
    }
  }, [activeIndex, onEntryClick, scrollCardIntoCenter])

  // Initial map focus — delay to let Leaflet initialize and fitBounds
  useEffect(() => {
    if (entries.length > 0) {
      const timer = setTimeout(() => syncMapToCarousel(0), 500)
      return () => clearTimeout(timer)
    }
  }, [entries.length])

  const activeEntryId = entries[activeIndex]
    ? String(entries[activeIndex].id)
    : null

  if (entries.length === 0) {
    return (
      <div
        className="fixed left-0 right-0 z-10"
        style={{ top: 'var(--nav-h, 0px)', bottom: 'env(safe-area-inset-bottom, 0px)' }}
      >
        <JourneyMap
          ref={mapRef}
          entries={mapEntries}
          checkins={[]}
          trail={trail}
          height={9999}
          dark={dark}
          onMarkerClick={handleMarkerClick}
          fullScreen
        />
        {!readOnly && onAddEntry && (
          <div className="fixed right-4 z-30" style={{ bottom: 'calc(var(--bottom-nav-h, 84px) + 16px)' }}>
            <button
              onClick={onAddEntry}
              className="w-12 h-12 rounded-full bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 shadow-lg flex items-center justify-center hover:scale-105 active:scale-95 transition-transform"
            >
              <Plus size={20} />
            </button>
          </div>
        )}
      </div>
    )
  }

  return (
    <div
      className="fixed left-0 right-0 z-10"
      style={{ top: 'var(--nav-h, 0px)', bottom: 'env(safe-area-inset-bottom, 0px)' }}
    >
      {/* Full-screen map */}
      <JourneyMap
        ref={mapRef}
        entries={mapEntries}
        checkins={[]}
        trail={trail}
        height={9999}
        dark={dark}
        activeMarkerId={activeEntryId}
        onMarkerClick={handleMarkerClick}
        fullScreen
        paddingBottom={200}
      />

      {/* Bottom carousel */}
      <div
        className="fixed left-0 right-0 z-40"
        style={{ touchAction: 'pan-x', bottom: carouselBottom }}
      >
        <div
          ref={carouselRef}
          className="flex gap-3 overflow-x-auto px-4 pb-3 pt-1"
          style={{
            scrollSnapType: 'x mandatory',
            WebkitOverflowScrolling: 'touch',
            scrollbarWidth: 'none',
            msOverflowStyle: 'none',
          }}
        >
          {entries.map((entry: any, i: number) => (
            <div
              key={entry.id}
              data-idx={i}
              ref={node => { if (node) cardRefs.current.set(i, node); else cardRefs.current.delete(i); }}
              style={{ scrollSnapAlign: 'center' }}
            >
              <MobileEntryCard
                entry={entry}
                dayLabel={entryDayMeta[i]?.dayLabel ?? i + 1}
                dayColor={entryDayMeta[i]?.dayColor ?? DAY_COLORS[0]}
                isActive={i === activeIndex}
                onClick={() => handleCardTap(entry, i)}
                publicPhotoUrl={publicPhotoUrl}
              />
            </div>
          ))}
        </div>
      </div>

      {/* FAB: add entry — bottom right, above the timeline carousel */}
      {!readOnly && onAddEntry && (
        <div
          className="fixed right-4 z-30"
          style={{ bottom: 'calc(var(--bottom-nav-h, 84px) + 168px)' }}
        >
          <button
            onClick={onAddEntry}
            className="w-12 h-12 rounded-full bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 shadow-lg flex items-center justify-center hover:scale-105 active:scale-95 transition-transform"
          >
            <Plus size={20} />
          </button>
        </div>
      )}
    </div>
  )
}
