import { jsx, jsxs, Fragment } from "react/jsx-runtime";
import * as React from "react";
import { ChevronDown, Check, X } from "lucide-react";
import { cva } from "class-variance-authority";
import { cn } from "../../lib/utils.js";
import { ItemPrefix, ItemSuffix } from "../../patterns/element-anatomy/item-anatomy.js";
const INDICATOR_SIZE = {
  sm: 8,
  md: 24,
  lg: 32
};
const INDICATOR_ICON_SIZE = {
  sm: 0,
  md: 16,
  lg: 20
};
const SM_HIT_AREA = 24;
const INDICATOR_BOX_WIDTH = {
  sm: SM_HIT_AREA,
  md: INDICATOR_SIZE.md,
  lg: INDICATOR_SIZE.lg
};
const RING_GAP_PX = 2;
const RING_WIDTH_PX = 2;
function getOuterRingShadow(ringColor) {
  return `0 0 0 ${RING_GAP_PX}px var(--surface), 0 0 0 ${RING_GAP_PX + RING_WIDTH_PX}px ${ringColor}`;
}
function resolveRingColor(state, linear) {
  if (state === "error") return "var(--error-hover)";
  if (state === "current" && !linear) return "var(--border-hover)";
  return "var(--info-hover)";
}
const StepsContext = React.createContext(null);
function useStepsContext() {
  const ctx = React.useContext(StepsContext);
  if (!ctx) throw new Error("Steps compound components must be rendered inside <Steps>");
  return ctx;
}
const StepItemContext = React.createContext(null);
function useStepItemContext() {
  const ctx = React.useContext(StepItemContext);
  if (!ctx) throw new Error("StepLabel / StepDescription / StepContent must be inside <StepItem>");
  return ctx;
}
const StepIndexContext = React.createContext(0);
function computeState(itemValue, value, completedValues, errorValues, reachableValues, linear, override) {
  if (override) return override;
  if (errorValues.has(itemValue)) return "error";
  if (completedValues.has(itemValue)) return "completed";
  if (itemValue === value) return "current";
  if (linear && reachableValues.has(itemValue)) return "reachable";
  return "upcoming";
}
function isClickable(state, linear, disabled) {
  if (disabled) return false;
  if (!linear) return true;
  return state !== "upcoming";
}
function normalizeExpanded(defaultExpanded, allValues) {
  if (defaultExpanded === "all") return new Set(allValues);
  if (!defaultExpanded || defaultExpanded === "none") return /* @__PURE__ */ new Set();
  return new Set(defaultExpanded);
}
function computeReachableValues(childValues, completedValues) {
  const completed = new Set(completedValues);
  const reachable = new Set(completed);
  for (const v of childValues) {
    if (!completed.has(v)) {
      reachable.add(v);
      break;
    }
  }
  return reachable;
}
const stepsRootVariants = cva("list-none p-0 m-0", {
  variants: {
    orientation: {
      vertical: "flex flex-col",
      horizontal: "flex flex-row items-start gap-3"
    }
  },
  defaultVariants: { orientation: "vertical" }
});
const Steps = React.forwardRef(
  ({
    value: valueProp,
    defaultValue,
    onValueChange,
    completedValues = [],
    errorValues = [],
    linear = true,
    size = "md",
    orientation = "vertical",
    expansion = "follow-active",
    defaultExpanded,
    className,
    children,
    ...props
  }, ref) => {
    const [internalValue, setInternalValue] = React.useState(defaultValue);
    const isControlled = valueProp !== void 0;
    const value = isControlled ? valueProp : internalValue;
    const setValue = React.useCallback(
      (next) => {
        if (!isControlled) setInternalValue(next);
        onValueChange == null ? void 0 : onValueChange(next);
      },
      [isControlled, onValueChange]
    );
    const childValues = React.useMemo(() => {
      const vals = [];
      React.Children.forEach(children, (child) => {
        if (React.isValidElement(child) && typeof child.props === "object" && child.props && "value" in child.props) {
          vals.push(String(child.props.value));
        }
      });
      return vals;
    }, [children]);
    const reachableValues = React.useMemo(
      () => computeReachableValues(childValues, completedValues),
      [childValues, completedValues]
    );
    const [expandedSet, setExpandedSet] = React.useState(
      () => normalizeExpanded(defaultExpanded, childValues)
    );
    const toggleExpanded = React.useCallback((itemValue) => {
      setExpandedSet((prev) => {
        const next = new Set(prev);
        if (next.has(itemValue)) next.delete(itemValue);
        else next.add(itemValue);
        return next;
      });
    }, []);
    const stepCount = React.Children.count(children);
    const ctxValue = React.useMemo(
      () => ({
        value,
        completedValues: new Set(completedValues),
        errorValues: new Set(errorValues),
        reachableValues,
        linear,
        size,
        orientation,
        expansion,
        expandedSet,
        setValue,
        toggleExpanded,
        total: stepCount
      }),
      [value, completedValues, errorValues, reachableValues, linear, size, orientation, expansion, expandedSet, setValue, toggleExpanded, stepCount]
    );
    const count = stepCount;
    const itemsWithIndex = [];
    React.Children.forEach(children, (child, index) => {
      if (!React.isValidElement(child)) {
        itemsWithIndex.push(child);
        return;
      }
      const isLast = index === count - 1;
      const cloned = React.cloneElement(
        child,
        { __isLast: isLast }
      );
      itemsWithIndex.push(
        /* @__PURE__ */ jsx(StepIndexContext.Provider, { value: index + 1, children: cloned }, `item-${index}`)
      );
    });
    return /* @__PURE__ */ jsx(StepsContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsx(
      "ol",
      {
        ref,
        "data-orientation": orientation,
        "data-size": size,
        className: cn(stepsRootVariants({ orientation }), className),
        ...props,
        children: itemsWithIndex
      }
    ) });
  }
);
Steps.displayName = "Steps";
const stepItemVariants = cva("group/step-item outline-none", {
  variants: {
    orientation: {
      // pb-6 on li provides spacing for next item; connector is absolute within li
      vertical: "relative flex flex-col",
      // Ant Design pattern:flex-1 等寬(最後一步用 last: 覆蓋成自然寬度)。
      // Connector 在 item 內部(不是 items 之間的獨立元素)。
      horizontal: "flex-1 min-w-0 last:flex-none last:shrink-0"
    },
    size: {
      sm: "text-body",
      md: "text-body",
      lg: "text-body-lg"
    }
  },
  defaultVariants: { orientation: "vertical", size: "md" }
});
const StepItem = React.forwardRef(
  ({ value, state: stateOverride, disabled = false, children, className, __isLast = false, ...props }, ref) => {
    const steps = useStepsContext();
    const state = computeState(
      value,
      steps.value,
      steps.completedValues,
      steps.errorValues,
      steps.reachableValues,
      steps.linear,
      stateOverride
    );
    const focused = value === steps.value;
    const clickable = isClickable(state, steps.linear, disabled);
    const expanded = steps.expansion === "follow-active" ? focused : steps.expandedSet.has(value);
    const activate = React.useCallback(() => {
      if (!clickable) return;
      steps.setValue(value);
      if (steps.expansion === "multiple") {
        steps.toggleExpanded(value);
      }
    }, [clickable, steps, value]);
    const itemCtx = React.useMemo(() => ({
      value,
      state,
      focused,
      disabled,
      clickable,
      expanded,
      isLast: __isLast,
      activate
    }), [value, state, focused, disabled, clickable, expanded, __isLast, activate]);
    const isVertical = steps.orientation === "vertical";
    return /* @__PURE__ */ jsx(StepItemContext.Provider, { value: itemCtx, children: /* @__PURE__ */ jsx(
      "li",
      {
        ref,
        "data-state": state,
        "data-focused": focused || void 0,
        "data-disabled": disabled || void 0,
        "data-clickable": clickable || void 0,
        "aria-current": focused ? "step" : void 0,
        "aria-disabled": disabled || void 0,
        className: cn(
          stepItemVariants({ orientation: steps.orientation, size: steps.size }),
          isVertical && !__isLast && "pb-6",
          !clickable && "cursor-not-allowed",
          className
        ),
        ...props,
        children: /* @__PURE__ */ jsx(StepItemLayout, { children })
      }
    ) });
  }
);
StepItem.displayName = "StepItem";
function StepItemLayout({ children }) {
  const steps = useStepsContext();
  const item = useStepItemContext();
  let labelNode = null;
  let descNode = null;
  let contentNode = null;
  React.Children.forEach(children, (child) => {
    if (!React.isValidElement(child)) return;
    if (child.type === StepLabel) labelNode = child;
    else if (child.type === StepDescription) descNode = child;
    else if (child.type === StepContent) contentNode = child;
  });
  if (steps.orientation === "horizontal") {
    return /* @__PURE__ */ jsx(HorizontalLayout, { label: labelNode, description: descNode });
  }
  return /* @__PURE__ */ jsx(VerticalLayout, { label: labelNode, description: descNode, content: contentNode, isLast: item.isLast });
}
const STEP_STATUS_TEXT = {
  completed: "已完成",
  current: "進行中",
  error: "錯誤",
  reachable: "未開始",
  upcoming: "未開始"
};
function StepItemHeader({ children, className, style }) {
  const item = useStepItemContext();
  const steps = useStepsContext();
  const index = React.useContext(StepIndexContext);
  const onKeyDown = (e) => {
    if (!item.clickable) return;
    if (e.key === "Enter" || e.key === " ") {
      e.preventDefault();
      item.activate();
    }
  };
  return /* @__PURE__ */ jsxs(
    "div",
    {
      role: item.clickable ? "button" : void 0,
      tabIndex: item.clickable ? 0 : void 0,
      onClick: item.clickable ? item.activate : void 0,
      onKeyDown: item.clickable ? onKeyDown : void 0,
      "aria-disabled": item.disabled || void 0,
      className: cn(
        "outline-none",
        item.clickable ? "cursor-pointer rounded-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring" : "cursor-not-allowed",
        className
      ),
      style,
      children: [
        /* @__PURE__ */ jsx("span", { className: "sr-only", children: `第 ${index} 步,共 ${steps.total} 步,${STEP_STATUS_TEXT[item.state]}` }),
        children
      ]
    }
  );
}
function VerticalLayout({
  label,
  description,
  content,
  isLast
}) {
  const steps = useStepsContext();
  const item = useStepItemContext();
  const showContent = !!content && item.expanded;
  const indicatorBox = INDICATOR_BOX_WIDTH[steps.size];
  return /* @__PURE__ */ jsxs(Fragment, { children: [
    /* @__PURE__ */ jsxs(StepItemHeader, { className: "flex items-start gap-3", children: [
      /* @__PURE__ */ jsx(ItemPrefix, { style: { width: indicatorBox }, children: /* @__PURE__ */ jsx(StepIndicator, {}) }),
      /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex items-start gap-2", children: [
        /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex flex-col", children: [
          label,
          description
        ] }),
        steps.expansion === "multiple" && !!content && /* @__PURE__ */ jsx(ItemSuffix, { "aria-hidden": true, children: /* @__PURE__ */ jsx(
          ChevronDown,
          {
            size: 16,
            className: cn(
              "text-fg-muted transition-transform duration-150",
              item.expanded && "rotate-180"
            )
          }
        ) })
      ] })
    ] }),
    showContent && /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 mt-3", children: [
      /* @__PURE__ */ jsx("div", { className: "shrink-0", style: { width: indicatorBox } }),
      /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: content })
    ] }),
    !isLast && /* @__PURE__ */ jsx(VerticalConnectorLine, {})
  ] });
}
function VerticalConnectorLine() {
  const steps = useStepsContext();
  const item = useStepItemContext();
  const isBlue = item.state === "completed";
  const radius = INDICATOR_SIZE[steps.size] / 2;
  const gap = 8;
  return /* @__PURE__ */ jsx(
    "div",
    {
      "aria-hidden": true,
      className: cn(
        "absolute w-px",
        isBlue ? "bg-info" : "bg-border"
      ),
      style: {
        left: INDICATOR_BOX_WIDTH[steps.size] / 2,
        top: `calc(0.5lh + ${radius}px + ${gap}px)`,
        bottom: `calc(${radius}px - 0.5lh + ${gap}px)`
      }
    }
  );
}
function HorizontalLayout({
  label,
  description
}) {
  const item = useStepItemContext();
  const steps = useStepsContext();
  const isBlue = item.state === "completed";
  const indicatorBox = INDICATOR_BOX_WIDTH[steps.size];
  return /* @__PURE__ */ jsxs(Fragment, { children: [
    /* @__PURE__ */ jsxs(StepItemHeader, { className: "flex items-start gap-3", children: [
      /* @__PURE__ */ jsx(ItemPrefix, { children: /* @__PURE__ */ jsx(StepIndicator, {}) }),
      /* @__PURE__ */ jsx("div", { className: "shrink-0 min-w-0", children: label }),
      !item.isLast && /* @__PURE__ */ jsx("div", { className: "h-[1lh] flex-1 flex items-center min-w-4", "aria-hidden": true, children: /* @__PURE__ */ jsx("div", { className: cn("h-px w-full", isBlue ? "bg-info" : "bg-border") }) })
    ] }),
    description && /* @__PURE__ */ jsx("div", { className: "min-w-0", style: { paddingLeft: indicatorBox + 12 }, children: description })
  ] });
}
function StepIndicator() {
  const steps = useStepsContext();
  const item = useStepItemContext();
  const { size, linear } = steps;
  const { state, focused, disabled } = item;
  if (size === "sm") return /* @__PURE__ */ jsx(SmIndicator, { state, focused, disabled, linear });
  return /* @__PURE__ */ jsx(MdLgIndicator, { size, state, focused, disabled, linear });
}
function SmIndicator({
  state,
  focused,
  disabled,
  linear
}) {
  const isHollow = state === "current" && linear || state === "reachable";
  let dotStyle;
  if (isHollow) {
    dotStyle = {
      width: INDICATOR_SIZE.sm,
      height: INDICATOR_SIZE.sm,
      background: "transparent",
      border: "2px solid var(--info-hover)",
      boxShadow: focused ? getOuterRingShadow(resolveRingColor(state, linear)) : void 0
    };
  } else {
    const dotBg = state === "completed" ? "var(--info)" : state === "error" ? "var(--error)" : state === "current" && !linear ? "var(--fg-disabled)" : "var(--fg-disabled)";
    dotStyle = {
      width: INDICATOR_SIZE.sm,
      height: INDICATOR_SIZE.sm,
      background: dotBg,
      boxShadow: focused ? getOuterRingShadow(resolveRingColor(state, linear)) : void 0
    };
  }
  return /* @__PURE__ */ jsx(
    "span",
    {
      "aria-hidden": true,
      className: "relative inline-flex items-center justify-center shrink-0",
      style: { width: SM_HIT_AREA, height: SM_HIT_AREA },
      children: /* @__PURE__ */ jsx(
        "span",
        {
          className: cn("block rounded-full", disabled && "opacity-disabled"),
          style: dotStyle
        }
      )
    }
  );
}
function MdLgIndicator({
  size,
  state,
  focused,
  disabled,
  linear
}) {
  const diameter = INDICATOR_SIZE[size];
  const iconPx = INDICATOR_ICON_SIZE[size];
  let fillBg;
  let contentColor;
  switch (state) {
    case "error":
      fillBg = "var(--error)";
      contentColor = "var(--on-emphasis)";
      break;
    case "completed":
      fillBg = "var(--info)";
      contentColor = "var(--on-emphasis)";
      break;
    case "current":
      if (linear) {
        fillBg = "var(--info)";
        contentColor = "var(--on-emphasis)";
      } else {
        fillBg = "var(--secondary)";
        contentColor = "var(--foreground)";
      }
      break;
    case "reachable":
      fillBg = "var(--info)";
      contentColor = "var(--on-emphasis)";
      break;
    default:
      if (linear) {
        fillBg = "var(--muted)";
        contentColor = "var(--fg-disabled)";
      } else {
        fillBg = "var(--secondary)";
        contentColor = "var(--foreground)";
      }
      break;
  }
  return /* @__PURE__ */ jsx(
    "span",
    {
      "aria-hidden": true,
      className: cn(
        "relative inline-flex items-center justify-center shrink-0 rounded-full",
        "font-medium leading-none transition-colors",
        disabled && "opacity-disabled"
      ),
      style: {
        width: diameter,
        height: diameter,
        background: fillBg,
        color: contentColor,
        // 2026-06-11 R2:對齊 spec canonical「indicator 數字與 label 同級」(steps.spec.md 狀態表 md=14/lg=16;spec 明文「之前寫小一號(md=12,lg=14)是錯的」)
        fontSize: size === "lg" ? "var(--font-body-lg-size)" : "var(--font-body-size)",
        boxShadow: focused ? getOuterRingShadow(resolveRingColor(state, linear)) : void 0
      },
      children: /* @__PURE__ */ jsx(IndicatorContent, { state, iconPx })
    }
  );
}
function IndicatorContent({ state, iconPx }) {
  if (state === "completed") return /* @__PURE__ */ jsx(Check, { size: iconPx, strokeWidth: 2.5 });
  if (state === "error") return /* @__PURE__ */ jsx(X, { size: iconPx, strokeWidth: 2.5 });
  return /* @__PURE__ */ jsx(StepNumber, {});
}
function StepNumber() {
  const index = React.useContext(StepIndexContext);
  return /* @__PURE__ */ jsx("span", { children: index });
}
const StepLabel = React.forwardRef(
  ({ className, children, ...props }, ref) => {
    const { size } = useStepsContext();
    const { state, focused, disabled } = useStepItemContext();
    return /* @__PURE__ */ jsx(
      "span",
      {
        ref,
        className: cn(
          "font-medium break-words",
          size === "lg" ? "text-body-lg" : "text-body",
          disabled ? "text-fg-disabled" : state === "error" ? "text-error-text" : focused ? "text-foreground" : "text-fg-secondary",
          className
        ),
        ...props,
        children
      }
    );
  }
);
StepLabel.displayName = "StepLabel";
const StepDescription = React.forwardRef(
  ({ className, children, style, ...props }, ref) => {
    const { size } = useStepsContext();
    const { disabled } = useStepItemContext();
    return /* @__PURE__ */ jsx(
      "span",
      {
        ref,
        className: cn(
          // Steps 跟 MenuItem 同 scanning-family:sm/md = scanning(body+caption),lg = scanning-lg(body-lg+body-compact)
          size === "lg" ? "mt-[var(--item-gap-label-desc-scanning-lg)]" : "mt-[var(--item-gap-label-desc-scanning)]",
          "leading-compact break-words",
          disabled ? "text-fg-disabled" : "text-fg-secondary",
          className
        ),
        style: {
          fontSize: size === "lg" ? "var(--font-body-size)" : "var(--font-caption-size)",
          ...style
        },
        ...props,
        children
      }
    );
  }
);
StepDescription.displayName = "StepDescription";
const StepContent = React.forwardRef(
  ({ className, children, ...props }, ref) => {
    const { orientation } = useStepsContext();
    if (orientation === "horizontal") return null;
    return /* @__PURE__ */ jsx(
      "div",
      {
        ref,
        className: cn("text-body text-foreground min-w-0", className),
        ...props,
        children
      }
    );
  }
);
StepContent.displayName = "StepContent";
const stepsMeta = {
  component: "Steps",
  family: 2,
  variants: {},
  sizes: {
    sm: { px: 8, when: "Sidebar / 緊湊 onboarding;indicator 8px dot" },
    md: { px: 24, when: "預設 — wizard / checkout / 註冊主流程;indicator 24px circle" },
    lg: { px: 32, when: "Marketing 流程展示 / 重要 onboarding;indicator 32px circle" }
  },
  states: ["upcoming", "reachable", "current", "completed", "error"],
  // 2026-06-11 R2:content-state 模型(spec 狀態表),非 Phase-1 boilerplate 互動 states,
  tokens: {
    bg: ["bg-info"],
    fg: ["--fg-disabled", "--foreground", "--on-emphasis", "text-error-text", "text-fg-disabled", "text-fg-muted", "text-fg-secondary", "text-foreground"],
    ring: []
  }
};
export {
  StepContent,
  StepDescription,
  StepItem,
  StepLabel,
  Steps,
  stepItemVariants,
  stepsMeta,
  stepsRootVariants
};
//# sourceMappingURL=steps.js.map
