import { type JSX, useMemo } from "react";
import { cn } from "../../lib/utils";
import type { StopReason } from "../../lib/stopReason";
import { getCrabVariant, getInteriorCrabVariant } from "../ui/crab-variants";

export type ThreadConnectorProps = {
  stopReason: StopReason;
  isPending: boolean;
  isFirst: boolean;
  /** True when this entry starts a new turn (first overall, or after end_turn/stop). */
  isTurnStart: boolean;
  /** True when this entry is the turn's only request. */
  isOnlyEntry?: boolean;
  /** Seed for crab variant selection (0-11). */
  crabIndex?: number;
  /** When true the crab is clickable (collapse / expand a turn). */
  collapsible?: boolean;
  onToggle?: () => void;
};

/**
 * Vertical timeline connector.  Top spacer uses a calc() that
 * mixes rem (py-1 + half-line) and px (border) so the crab
 * centre-line matches the LogEntry `#id` index regardless of the
 * root font-size.  The bottom spacer is flex-1 so the outgoing
 * line adapts to whatever height the LogEntry occupies.
 */
export function ThreadConnector({
  stopReason,
  isPending,
  isFirst,
  isTurnStart,
  isOnlyEntry = false,
  crabIndex = 0,
  collapsible = false,
  onToggle,
}: ThreadConnectorProps): JSX.Element {
  const isBoundary = stopReason === "end_turn" || stopReason === "stop";
  const isFusedBoundary = isOnlyEntry && isTurnStart && isBoundary;
  const isRunning = isPending && !isBoundary;
  const Crab = useMemo(() => getCrabVariant(crabIndex), [crabIndex]);
  const FusedCrab = useMemo(() => getInteriorCrabVariant(crabIndex), [crabIndex]);

  const interactiveProps =
    collapsible && onToggle
      ? ({
          role: "button" as const,
          tabIndex: 0,
          className: "cursor-pointer",
          onClick: (e: React.MouseEvent) => {
            e.stopPropagation();
            onToggle();
          },
          onKeyDown: (e: React.KeyboardEvent) => {
            if (e.key === "Enter" || e.key === " ") {
              e.preventDefault();
              onToggle();
            }
          },
        } as const)
      : ({} as const);

  return (
    <div className="flex flex-col items-center w-6 shrink-0 pt-0.5 pb-0.5">
      {/* Top spacer — crab centre must land on the LogEntry index midline.
       *  Index midline from container top = border(1px) + py-1(0.25rem) + ½line(0.5rem)
       *  = 1px + 0.75rem.  Crab centre = pt(2px) + spacer + 7px(half crab).
       *  ∴ spacer = 0.75rem - 8px.  (at 16px root: 12-8=4px; 2+4+7=13px). */}
      <div className="flex justify-center h-[calc(0.75rem-8px)]">
        {!isFirst && <div className="w-0.5 bg-muted-foreground/30 h-full" />}
      </div>

      {/* Crab — pinned to the fixed offset above so it never drifts
       *  when the LogEntry expands / collapses.  Clickable when the
       *  turn is collapsible (replaces the old chevron toggle). */}
      {isFusedBoundary ? (
        <span title="Start and end of turn">
          <FusedCrab
            className={cn(
              "size-3.5 text-[#80FF00]",
              "animate-crab-settle",
              "drop-shadow-[0_0_4px_rgba(128,255,0,0.5)]",
            )}
          />
        </span>
      ) : isBoundary ? (
        <span
          title={stopReason === "end_turn" ? "End of Turn (Anthropic)" : "End of Turn (OpenAI)"}
          {...interactiveProps}
        >
          <Crab
            className={cn(
              "size-3.5 text-amber-400",
              "animate-crab-settle",
              "drop-shadow-[0_0_4px_rgba(251,191,36,0.5)]",
            )}
          />
        </span>
      ) : isTurnStart ? (
        <span title="Start of turn" {...interactiveProps}>
          <Crab
            className={cn(
              "size-3.5 text-emerald-400",
              "animate-crab-appear",
              "drop-shadow-[0_0_4px_rgba(52,211,153,0.5)]",
            )}
          />
        </span>
      ) : isRunning ? (
        <span title="Processing…">
          <Crab className={cn("size-3.5 text-amber-300/80", "animate-crab-crawl")} />
        </span>
      ) : (
        <span>
          <Crab className="size-3.5 text-muted-foreground/40" />
        </span>
      )}

      {/* Bottom spacer — flex-1 fills whatever height the LogEntry
       *  consumes (header + expanded content).  Turn boundaries have
       *  no outgoing line. */}
      <div className="flex-1 flex justify-center min-h-0">
        {!isBoundary && (
          <div
            className={cn(
              "w-0.5 h-full",
              isPending
                ? "border-dashed bg-transparent border-l-2 border-muted-foreground/20"
                : "bg-muted-foreground/30",
            )}
          />
        )}
      </div>
    </div>
  );
}
