'use client'

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react'
import { usePathname, useRouter } from 'next/navigation'
import { tourById, tourForPath, type TourDefinition, type TourStep } from '@/lib/tours'

type TourContextValue = {
  activeTour: TourDefinition | null
  stepIndex: number
  step: TourStep | null
  isOpen: boolean
  startTour: (tourId?: string) => void
  next: () => void
  prev: () => void
  close: () => void
  currentModuleTourId: string | null
}

const TourContext = createContext<TourContextValue | null>(null)

export function TourProvider({ children }: { children: ReactNode }) {
  const router = useRouter()
  const pathname = usePathname()
  const [tourId, setTourId] = useState<string | null>(null)
  const [stepIndex, setStepIndex] = useState(0)
  const [pendingStep, setPendingStep] = useState(0)

  const activeTour = tourId ? tourById(tourId) ?? null : null
  const step = activeTour?.steps[stepIndex] ?? null
  const isOpen = Boolean(activeTour && step)

  const currentModuleTourId = useMemo(() => tourForPath(pathname)?.id ?? null, [pathname])

  const goToStep = useCallback(
    async (tour: TourDefinition, index: number) => {
      const nextStep = tour.steps[index]
      if (!nextStep) {
        setTourId(null)
        setStepIndex(0)
        return
      }
      if (nextStep.route) {
        const needsNav =
          nextStep.route === '/'
            ? pathname !== '/'
            : !(pathname === nextStep.route || pathname.startsWith(`${nextStep.route}/`))
        if (needsNav) {
          setPendingStep(index)
          setTourId(tour.id)
          router.push(nextStep.route)
          return
        }
      }
      setTourId(tour.id)
      setStepIndex(index)
      setPendingStep(index)
    },
    [pathname, router],
  )

  const startTour = useCallback(
    (id?: string) => {
      const tour = id ? tourById(id) : tourForPath(pathname)
      if (!tour) return
      setTourId(tour.id)
      setStepIndex(0)
      void goToStep(tour, 0)
    },
    [goToStep, pathname],
  )

  const close = useCallback(() => {
    setTourId(null)
    setStepIndex(0)
    setPendingStep(0)
    if (typeof window !== 'undefined' && tourId) {
      localStorage.setItem(`tour-done:${tourId}`, '1')
    }
  }, [tourId])

  const next = useCallback(() => {
    if (!activeTour) return
    if (stepIndex >= activeTour.steps.length - 1) {
      close()
      return
    }
    void goToStep(activeTour, stepIndex + 1)
  }, [activeTour, close, goToStep, stepIndex])

  const prev = useCallback(() => {
    if (!activeTour || stepIndex <= 0) return
    void goToStep(activeTour, stepIndex - 1)
  }, [activeTour, goToStep, stepIndex])

  // After route change during a tour, show the pending step
  useEffect(() => {
    if (!tourId || !activeTour) return
    const desired = activeTour.steps[pendingStep]
    if (!desired) return
    if (desired.route) {
      const ok =
        desired.route === '/'
          ? pathname === '/'
          : pathname.startsWith(desired.route)
      if (ok) {
        setStepIndex(pendingStep)
      }
    }
  }, [pathname, tourId, activeTour, pendingStep])

  const value: TourContextValue = {
    activeTour,
    stepIndex,
    step,
    isOpen,
    startTour,
    next,
    prev,
    close,
    currentModuleTourId,
  }

  return <TourContext.Provider value={value}>{children}</TourContext.Provider>
}

export function useTour() {
  const ctx = useContext(TourContext)
  if (!ctx) throw new Error('useTour must be used within TourProvider')
  return ctx
}
