"use client";

import * as React from "react";
import { CheckIcon, XIcon } from "lucide-react";

import { cn } from "@/lib/utils";

export type StepDef = { label: string; sub?: string };

/**
 * Stepper / wizard header (spec 03-structure-and-navigation §10). Horizontal when there is room, compact
 * ("Step 2 of 4 · Choose items" + a progress line) when narrow, decided by its own width. Upcoming steps are
 * not focusable (no skipping ahead); completed steps are buttons for going back; error steps say "Needs attention".
 */
export function Stepper({
  steps,
  current,
  done,
  errors,
  reached,
  onStepClick,
  className,
}: {
  steps: StepDef[];
  current: number;
  /** Indexes already completed (they can be revisited). */
  done: Set<number>;
  /** Indexes a later check sent the user back to. */
  errors?: Set<number>;
  /** Furthest step index already visited: steps up to it can be revisited (still no skipping ahead). */
  reached?: number;
  onStepClick?: (index: number) => void;
  className?: string;
}) {
  return (
    <nav aria-label="Steps" className={cn("@container", className)}>
      {/* Compact */}
      <div className="@xl:hidden">
        <p className="text-sm">
          <span className="font-semibold">
            Step {current + 1} of {steps.length}
          </span>
          <span className="text-muted-foreground"> · {steps[current].label}</span>
        </p>
        <div className="mt-2 h-1 overflow-hidden rounded-full bg-muted" aria-hidden>
          <div className="h-full rounded-full bg-primary transition-[width]" style={{ width: `${((current + 1) / steps.length) * 100}%` }} />
        </div>
      </div>

      {/* Horizontal */}
      <ol className="hidden items-start @xl:flex">
        {steps.map((s, i) => {
          const isCurrent = i === current;
          const isDone = done.has(i) && !isCurrent;
          const isError = errors?.has(i) && !isCurrent;
          const clickable = !isCurrent && (isDone || isError || i <= (reached ?? -1)) && !!onStepClick;
          const marker = (
            <span
              className={cn(
                "flex size-6 shrink-0 items-center justify-center rounded-full border text-xs font-semibold tabular-nums",
                isError
                  ? "border-status-error-border bg-status-error-bg text-status-error-text"
                  : isCurrent || isDone
                    ? "border-primary bg-primary text-primary-foreground"
                    : "border-[var(--color-border-panel)] bg-card text-muted-foreground",
              )}
              aria-hidden
            >
              {isError ? <XIcon className="size-3.5" /> : isDone ? <CheckIcon className="size-3.5" /> : i + 1}
            </span>
          );
          const label = (
            <span className="flex flex-col items-start text-left">
              <span className={cn("text-sm font-medium", isError ? "text-status-error-text" : isCurrent || isDone ? "text-foreground" : "text-muted-foreground")}>{s.label}</span>
              {s.sub ? <span className="text-xs text-muted-foreground">{s.sub}</span> : null}
              <span className="sr-only">{isError ? ", needs attention" : isDone ? ", done" : isCurrent ? ", current step" : ", upcoming"}</span>
            </span>
          );
          return (
            <li key={s.label} className="flex flex-1 items-start last:flex-none" aria-current={isCurrent ? "step" : undefined}>
              {clickable ? (
                <button type="button" onClick={() => onStepClick!(i)} className="flex cursor-pointer items-start gap-2 rounded-md outline-none focus-visible:ring-2 focus-visible:ring-ring">
                  {marker}
                  {label}
                </button>
              ) : (
                <span className="flex items-start gap-2">
                  {marker}
                  {label}
                </span>
              )}
              {i < steps.length - 1 ? (
                <span className={cn("mx-3 mt-3 h-px min-w-6 flex-1", done.has(i) ? "bg-[var(--color-border-strong)]" : "bg-border")} aria-hidden />
              ) : null}
            </li>
          );
        })}
      </ol>
    </nav>
  );
}
