import * as React from "react";
import { Check, Circle } from "lucide-react";

import { cn } from "@/lib/utils";
import { Typography } from "@/components/ui/typography";

type StepperOrientation = "horizontal" | "vertical";

export type StepperStep = {
  id?: string | number;
  label?: React.ReactNode;
  description?: React.ReactNode;
  center?: React.ReactNode;
  side?: React.ReactNode;
  state?: "complete" | "active" | "inactive";
};

type StepperProps = {
  steps: StepperStep[];
  orientation?: StepperOrientation;
  showSide?: boolean;
  className?: string;
  trackClassName?: string;
  stepClassName?: string;
  centerClassName?: string;
  sideClassName?: string;
  labelClassName?: string;
  descriptionClassName?: string;
  connectorClassName?: string;
};

const baseDotClass =
  "relative z-10 flex shrink-0 items-center justify-center rounded-full border-2 transition-colors";

function StepperStepContent({
  step,
  index,
  total,
  isVertical,
  showSide,
  stepClassName,
  centerClassName,
  sideClassName,
  labelClassName,
  descriptionClassName,
  connectorClassName,
}: {
  step: StepperStep;
  index: number;
  total: number;
  isVertical: boolean;
  showSide: boolean;
  stepClassName?: string;
  centerClassName?: string;
  sideClassName?: string;
  labelClassName?: string;
  descriptionClassName?: string;
  connectorClassName?: string;
}) {
  const state =
    step.state ??
    (index < total - 1 ? "complete" : index === 0 ? "active" : "inactive");
  const isComplete = state === "complete";
  const isActive = state === "active";

  const dotTone = isComplete
    ? "border-[var(--stepper-color-complete)] bg-[var(--stepper-color-complete)] text-[var(--stepper-color-on)]"
    : isActive
      ? "border-[var(--stepper-color-active)] bg-[var(--stepper-color-active)] text-[var(--stepper-color-on)]"
      : "border-[var(--stepper-color-inactive)] bg-[var(--stepper-color-on)] text-[var(--stepper-color-active)]";

  const connectorTone = isComplete
    ? "bg-[var(--stepper-color-complete)]"
    : isActive
      ? "bg-[var(--stepper-color-active)]"
      : "bg-[var(--stepper-color-inactive)]";

  const dotSize = isVertical ? "size-6" : "size-8";

  return (
    <div
      className={cn(
        "min-w-0",
        isVertical ? "flex w-full gap-3" : "flex flex-1 items-center gap-3",
        stepClassName,
      )}
    >
      {isVertical ? (
        <>
          <div className="relative flex w-6 shrink-0 justify-center overflow-visible">
            {index < total - 1 ? (
              <div
                aria-hidden="true"
                className={cn(
                  "pointer-events-none absolute top-6 left-1/2 h-[calc(100%+0.75rem)] w-[2px] -translate-x-1/2 rounded-full",
                  connectorTone,
                  connectorClassName,
                )}
              />
            ) : null}

            <div
              className={cn(baseDotClass, dotSize, dotTone, centerClassName)}
            >
              {step.center ??
                (isComplete ? (
                  <Check className="size-3.5" strokeWidth={3} />
                ) : isActive ? (
                  <span className="text-[11px] font-semibold leading-none">
                    {index + 1}
                  </span>
                ) : (
                  <Circle className="size-3" strokeWidth={3} />
                ))}
            </div>
          </div>

          {showSide && (step.label || step.description || step.side) ? (
            <div className={cn("min-w-0 flex-1 pt-0.5", sideClassName)}>
              {step.side ?? (
                <>
                  {step.label ? (
                    <Typography
                      as="div"
                      variant="body"
                      className={cn("truncate font-medium", labelClassName)}
                    >
                      {step.label}
                    </Typography>
                  ) : null}
                  {step.description ? (
                    <Typography
                      as="div"
                      variant="caption"
                      color="secondary"
                      className={cn("truncate", descriptionClassName)}
                    >
                      {step.description}
                    </Typography>
                  ) : null}
                </>
              )}
            </div>
          ) : null}
        </>
      ) : (
        <>
          <div className={cn(baseDotClass, dotSize, dotTone, centerClassName)}>
            {step.center ??
              (isComplete ? (
                <Check className="size-3.5" strokeWidth={3} />
              ) : isActive ? (
                <span className="text-[11px] font-semibold leading-none">
                  {index + 1}
                </span>
              ) : (
                <Circle className="size-3" strokeWidth={3} />
              ))}
          </div>

          {showSide && (step.label || step.description || step.side) ? (
            <div className={cn("min-w-0 flex-1", sideClassName)}>
              {step.side ?? (
                <>
                  {step.label ? (
                    <Typography
                      as="div"
                      variant="body"
                      className={cn("truncate font-medium", labelClassName)}
                    >
                      {step.label}
                    </Typography>
                  ) : null}
                  {step.description ? (
                    <Typography
                      as="div"
                      variant="caption"
                      color="secondary"
                      className={cn("truncate", descriptionClassName)}
                    >
                      {step.description}
                    </Typography>
                  ) : null}
                </>
              )}
            </div>
          ) : null}

          {index < total - 1 ? (
            <div
              className={cn(
                "h-0.5 min-w-8 flex-1 shrink-0 rounded-full",
                connectorTone,
                connectorClassName,
              )}
            />
          ) : null}
        </>
      )}
    </div>
  );
}

function Stepper({
  steps,
  orientation = "horizontal",
  showSide = true,
  className,
  trackClassName,
  stepClassName,
  centerClassName,
  sideClassName,
  labelClassName,
  descriptionClassName,
  connectorClassName,
}: StepperProps) {
  const isVertical = orientation === "vertical";

  return (
    <div
      className={cn(
        "w-full",
        isVertical
          ? "relative mx-auto flex w-fit flex-col gap-3 pl-3"
          : "flex items-center",
        trackClassName,
        className,
      )}
    >
      {steps.map((step, index) => (
        <div
          key={step.id ?? index}
          className={cn(
            "relative",
            // Horizontal: every step but the last flexes so its connector fills
            // the gap evenly across the full width.
            !isVertical && index < steps.length - 1 && "flex-1",
          )}
        >
          <StepperStepContent
            step={step}
            index={index}
            total={steps.length}
            isVertical={isVertical}
            showSide={showSide}
            stepClassName={stepClassName}
            centerClassName={centerClassName}
            sideClassName={sideClassName}
            labelClassName={labelClassName}
            descriptionClassName={descriptionClassName}
            connectorClassName={connectorClassName}
          />
        </div>
      ))}
    </div>
  );
}

export { Stepper };
