import React, {
  createContext,
  useCallback,
  useContext,
  useMemo,
  useState,
  type ReactElement,
  type ReactNode
} from 'react'

type WizardContextProps = (name: string) => void

const WizardContext = createContext<WizardContextProps | null>(null)

export function useWizard(): WizardContextProps {
  const ctx = useContext(WizardContext)

  if (!ctx) {
    throw new Error('useWizard must be used within <Wizard />')
  }

  return ctx
}

type WizardProps = {
  children: ReactNode
  index?: number
  onChange?: (index: number) => void
}

export function Wizard({
  children,
  index: initIndex = 0,
  onChange
}: WizardProps) {
  const [index, setIndex] = useState<number>(initIndex)

  const components = useMemo(
    () => React.Children.toArray(children) as ReactElement<WizardStepProps>[],
    [children]
  )

  const steps = useMemo(
    () => components.map((child) => child.props.name),
    [components]
  )

  const child = components[index]

  const onChange_ = useCallback<WizardContextProps>(
    (name) => {
      const nextIndex = steps.findIndex((n) => n === name)

      if (nextIndex >= 0) {
        setIndex(nextIndex)
        onChange?.(nextIndex)
      }
    },
    [steps]
  )

  return (
    <WizardContext.Provider value={onChange_}>
      {React.isValidElement(child) ? React.cloneElement(child) : child}
    </WizardContext.Provider>
  )
}

export type WizardStepProps = {
  name: string
  children: React.ReactNode
}

export function WizardStep({ children }: WizardStepProps) {
  return <>{children}</>
}
