import * as React from 'react'
import { cva, type VariantProps } from 'class-variance-authority'

import { cn } from '@/lib/utils'

type StepStatus = 'complete' | 'current' | 'upcoming' | 'error'

const stepperVariants = cva('group/stepper flex w-full', {
  variants: {
    orientation: {
      horizontal: 'items-start',
      vertical: 'flex-col',
    },
  },
  defaultVariants: {
    orientation: 'horizontal',
  },
})

export interface StepperProps
  extends React.OlHTMLAttributes<HTMLOListElement>,
    VariantProps<typeof stepperVariants> {}

export interface StepperItemProps extends React.LiHTMLAttributes<HTMLLIElement> {
  status?: StepStatus
}

export type StepperIndicatorProps = React.HTMLAttributes<HTMLSpanElement>
export type StepperContentProps = React.HTMLAttributes<HTMLDivElement>
export type StepperTitleProps = React.HTMLAttributes<HTMLDivElement>
export type StepperDescriptionProps = React.HTMLAttributes<HTMLDivElement>
export type StepperSeparatorProps = React.HTMLAttributes<HTMLSpanElement>

function CheckIcon() {
  return (
    <svg aria-hidden="true" viewBox="0 0 16 16" className="size-3.5">
      <path
        fill="currentColor"
        d="M6.2 11.3 2.9 8l1-1 2.3 2.3 5-5 1 1-6 6z"
      />
    </svg>
  )
}

function Stepper({
  className,
  orientation = 'horizontal',
  ...props
}: StepperProps) {
  return (
    <ol
      data-slot="stepper"
      data-orientation={orientation}
      className={cn(stepperVariants({ orientation }), className)}
      {...props}
    />
  )
}

function StepperItem({
  className,
  status = 'upcoming',
  ...props
}: StepperItemProps) {
  return (
    <li
      data-slot="stepper-item"
      data-status={status}
      className={cn(
        'group/stepper-item relative flex min-w-0 flex-1 gap-3',
        'group-data-[orientation=horizontal]/stepper:flex-col group-data-[orientation=horizontal]/stepper:items-center group-data-[orientation=horizontal]/stepper:gap-2 group-data-[orientation=horizontal]/stepper:text-center',
        'data-[status=current]:text-text data-[status=upcoming]:text-text-tertiary',
        'data-[status=complete]:text-text data-[status=error]:text-error',
        className
      )}
      {...props}
    />
  )
}

function StepperIndicator({ className, children, ...props }: StepperIndicatorProps) {
  return (
    <span
      data-slot="stepper-indicator"
      className={cn(
        'z-10 flex size-7 shrink-0 items-center justify-center rounded-full border text-xs font-semibold transition-colors',
        'border-border-tertiary bg-bg-container text-text-tertiary',
        'group-data-[status=complete]/stepper-item:border-primary group-data-[status=complete]/stepper-item:bg-primary group-data-[status=complete]/stepper-item:text-text-on-primary',
        'group-data-[status=current]/stepper-item:border-primary group-data-[status=current]/stepper-item:text-primary',
        'group-data-[status=error]/stepper-item:border-error group-data-[status=error]/stepper-item:bg-error-bg group-data-[status=error]/stepper-item:text-error',
        className
      )}
      {...props}
    >
      <span className="group-data-[status=complete]/stepper-item:hidden">
        {children}
      </span>
      <span className="hidden group-data-[status=complete]/stepper-item:inline-flex">
        <CheckIcon />
      </span>
    </span>
  )
}

function StepperContent({ className, ...props }: StepperContentProps) {
  return (
    <div
      data-slot="stepper-content"
      className={cn(
        'min-w-0 flex-1 pb-6 group-data-[orientation=horizontal]/stepper:pb-0',
        className
      )}
      {...props}
    />
  )
}

function StepperTitle({ className, ...props }: StepperTitleProps) {
  return (
    <div
      data-slot="stepper-title"
      className={cn('text-sm font-medium leading-5 text-current', className)}
      {...props}
    />
  )
}

function StepperDescription({ className, ...props }: StepperDescriptionProps) {
  return (
    <div
      data-slot="stepper-description"
      className={cn('mt-1 text-sm leading-5 text-text-tertiary', className)}
      {...props}
    />
  )
}

function StepperSeparator({ className, ...props }: StepperSeparatorProps) {
  return (
    <span
      aria-hidden="true"
      data-slot="stepper-separator"
      className={cn(
        'absolute left-3.5 top-7 h-[calc(100%-1.75rem)] w-px -translate-x-1/2 bg-border-tertiary',
        'group-data-[orientation=horizontal]/stepper:left-[calc(50%+1rem)] group-data-[orientation=horizontal]/stepper:right-[calc(-50%+1rem)] group-data-[orientation=horizontal]/stepper:top-3.5 group-data-[orientation=horizontal]/stepper:h-px group-data-[orientation=horizontal]/stepper:w-auto group-data-[orientation=horizontal]/stepper:translate-x-0',
        'group-data-[status=complete]/stepper-item:bg-primary',
        className
      )}
      {...props}
    />
  )
}

export {
  Stepper,
  StepperItem,
  StepperIndicator,
  StepperContent,
  StepperTitle,
  StepperDescription,
  StepperSeparator,
}
export type { StepStatus }
