'use client'

import * as React from 'react'
import { motion, AnimatePresence } from 'motion/react'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import { ArrowLeft, ArrowRight, Check, Loader2 } from 'lucide-react'

export interface WizardStep {
  id: string
  title: string
  description?: string
  isOptional?: boolean
}

interface FormWizardContextValue {
  currentStep: number
  totalSteps: number
  steps: WizardStep[]
  goToStep: (step: number) => void
  nextStep: () => void
  prevStep: () => void
  isFirstStep: boolean
  isLastStep: boolean
  canGoNext: boolean
  setCanGoNext: (can: boolean) => void
}

const FormWizardContext = React.createContext<FormWizardContextValue | null>(null)

export function useFormWizard() {
  const context = React.useContext(FormWizardContext)
  if (!context) {
    throw new Error('useFormWizard must be used within a FormWizard')
  }
  return context
}

interface FormWizardProps {
  steps: WizardStep[]
  children: React.ReactNode
  onComplete?: () => void | Promise<void>
  isSubmitting?: boolean
  submitLabel?: string
  className?: string
  showStepIndicator?: boolean
  allowStepNavigation?: boolean
}

export function FormWizard({
  steps,
  children,
  onComplete,
  isSubmitting = false,
  submitLabel = 'Submit',
  className,
  showStepIndicator = true,
  allowStepNavigation = false,
}: FormWizardProps) {
  const [currentStep, setCurrentStep] = React.useState(0)
  const [canGoNext, setCanGoNext] = React.useState(true)
  const [direction, setDirection] = React.useState(0) // -1 for back, 1 for forward

  const totalSteps = steps.length
  const isFirstStep = currentStep === 0
  const isLastStep = currentStep === totalSteps - 1

  const goToStep = React.useCallback((step: number) => {
    if (step >= 0 && step < totalSteps) {
      setDirection(step > currentStep ? 1 : -1)
      setCurrentStep(step)
    }
  }, [currentStep, totalSteps])

  const nextStep = React.useCallback(() => {
    if (currentStep < totalSteps - 1) {
      setDirection(1)
      setCurrentStep((prev) => prev + 1)
    }
  }, [currentStep, totalSteps])

  const prevStep = React.useCallback(() => {
    if (currentStep > 0) {
      setDirection(-1)
      setCurrentStep((prev) => prev - 1)
    }
  }, [currentStep])

  const handleNext = async () => {
    if (isLastStep && onComplete) {
      await onComplete()
    } else {
      nextStep()
    }
  }

  const contextValue: FormWizardContextValue = {
    currentStep,
    totalSteps,
    steps,
    goToStep,
    nextStep,
    prevStep,
    isFirstStep,
    isLastStep,
    canGoNext,
    setCanGoNext,
  }

  const childrenArray = React.Children.toArray(children)
  const currentChild = childrenArray[currentStep]

  const variants = {
    enter: (direction: number) => ({
      x: direction > 0 ? 100 : -100,
      opacity: 0,
    }),
    center: {
      x: 0,
      opacity: 1,
    },
    exit: (direction: number) => ({
      x: direction < 0 ? 100 : -100,
      opacity: 0,
    }),
  }

  return (
    <FormWizardContext.Provider value={contextValue}>
      <div className={cn('flex min-h-[600px] flex-col', className)}>
        {showStepIndicator && (
          <StepIndicator
            steps={steps}
            currentStep={currentStep}
            allowNavigation={allowStepNavigation}
            onStepClick={allowStepNavigation ? goToStep : undefined}
          />
        )}

        <div className="relative flex-1 overflow-hidden">
          <AnimatePresence initial={false} custom={direction} mode="wait">
            <motion.div
              key={currentStep}
              custom={direction}
              variants={variants}
              initial="enter"
              animate="center"
              exit="exit"
              transition={{
                x: { type: 'spring', stiffness: 300, damping: 30 },
                opacity: { duration: 0.2 },
              }}
              className="absolute inset-0"
            >
              <div className="h-full px-1 py-6">
                {currentChild}
              </div>
            </motion.div>
          </AnimatePresence>
        </div>

        <div className="flex items-center justify-between border-t pt-6">
          <Button
            type="button"
            variant="ghost"
            onClick={prevStep}
            disabled={isFirstStep || isSubmitting}
            className={cn(isFirstStep && 'invisible')}
          >
            <ArrowLeft className="mr-2 h-4 w-4" />
            Back
          </Button>

          <Button
            type="button"
            onClick={handleNext}
            disabled={!canGoNext || isSubmitting}
          >
            {isSubmitting ? (
              <>
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                Processing...
              </>
            ) : isLastStep ? (
              <>
                <Check className="mr-2 h-4 w-4" />
                {submitLabel}
              </>
            ) : (
              <>
                Continue
                <ArrowRight className="ml-2 h-4 w-4" />
              </>
            )}
          </Button>
        </div>
      </div>
    </FormWizardContext.Provider>
  )
}

interface StepIndicatorProps {
  steps: WizardStep[]
  currentStep: number
  allowNavigation?: boolean
  onStepClick?: (step: number) => void
}

export function StepIndicator({
  steps,
  currentStep,
  allowNavigation = false,
  onStepClick,
}: StepIndicatorProps) {
  return (
    <div className="mb-8">
      {/* Progress bar */}
      <div className="mb-4">
        <div className="flex items-center justify-between text-sm text-muted-foreground">
          <span>Step {currentStep + 1} of {steps.length}</span>
          <span>{Math.round(((currentStep + 1) / steps.length) * 100)}% complete</span>
        </div>
        <div className="mt-2 h-2 w-full overflow-hidden rounded-full bg-secondary">
          <motion.div
            className="h-full bg-gradient-to-r from-primary to-primary/80"
            initial={{ width: 0 }}
            animate={{ width: `${((currentStep + 1) / steps.length) * 100}%` }}
            transition={{ duration: 0.3, ease: 'easeInOut' }}
          />
        </div>
      </div>

      {/* Step indicators */}
      <div className="flex items-center justify-between">
        {steps.map((step, index) => {
          const isCompleted = index < currentStep
          const isCurrent = index === currentStep
          const isClickable = allowNavigation && (isCompleted || isCurrent)

          return (
            <React.Fragment key={step.id}>
              <button
                type="button"
                onClick={() => isClickable && onStepClick?.(index)}
                disabled={!isClickable}
                className={cn(
                  'flex flex-col items-center gap-2',
                  isClickable && 'cursor-pointer',
                  !isClickable && 'cursor-default'
                )}
              >
                <div
                  className={cn(
                    'flex h-10 w-10 items-center justify-center rounded-full border-2 text-sm font-semibold transition-colors',
                    isCompleted && 'border-primary bg-primary text-primary-foreground',
                    isCurrent && 'border-primary text-primary',
                    !isCompleted && !isCurrent && 'border-muted text-muted-foreground'
                  )}
                >
                  {isCompleted ? (
                    <Check className="h-5 w-5" />
                  ) : (
                    <span>{index + 1}</span>
                  )}
                </div>
                <span
                  className={cn(
                    'hidden text-xs font-medium md:block',
                    isCurrent && 'text-primary',
                    !isCurrent && 'text-muted-foreground'
                  )}
                >
                  {step.title}
                </span>
              </button>
              {index < steps.length - 1 && (
                <div
                  className={cn(
                    'h-0.5 flex-1 mx-2',
                    index < currentStep ? 'bg-primary' : 'bg-muted'
                  )}
                />
              )}
            </React.Fragment>
          )
        })}
      </div>
    </div>
  )
}

interface WizardStepContentProps {
  children: React.ReactNode
  title?: string
  description?: string
  className?: string
}

export function WizardStepContent({
  children,
  title,
  description,
  className,
}: WizardStepContentProps) {
  return (
    <div className={cn('flex h-full flex-col', className)}>
      {(title || description) && (
        <div className="mb-8 text-center">
          {title && (
            <h2 className="text-2xl font-semibold tracking-tight md:text-3xl">
              {title}
            </h2>
          )}
          {description && (
            <p className="mt-2 text-muted-foreground">
              {description}
            </p>
          )}
        </div>
      )}
      <div className="flex-1">
        {children}
      </div>
    </div>
  )
}
