// [nexus] Phase 11 — Projects list hero-stat card.
//
// A single card in the Projects list grid. The visual focal point is the
// 72px Inter Black volt percentage (DESIGN.md §4 "performance stat"). The
// card renders:
//
//   • Title row    — project name in Inter 700 uppercase 16px + status dot
//   • Hero stat    — Inter Black 900, 72px, volt — the milestone %
//   • Sub-line     — "Phase N of M · Next gate: {name}" in silver
//   • Progress bar — 8px charcoal track, volt fill, sharp 4px corners
//   • Footer       — "$X burned · last activity {when}" in silver
//
// Data gaps (Phase 11): the shared `Project` type has no milestoneProgress,
// no phasesCompleted/phasesTotal, no nextGate, no costBurned, no
// lastActivity fields. When those values aren't available we render an
// em-dash placeholder rather than fabricate a value. See the Phase 11
// report for the backend gap list.
import type { ReactNode } from "react";
import { cn } from "@/lib/utils";

export type ProjectCardStatus = "idle" | "working" | "waiting";

export interface ProjectCardProps {
  /** Uppercase slug displayed as the title (e.g. "NEXUS-DESIGN-MIGRATION"). */
  slug: string;
  /** Status dot mapping — priority is waiting > working > idle. */
  status: ProjectCardStatus;
  /** Milestone progress 0–100, or null when no data is available. */
  progress: number | null;
  /** Optional "Phase N of M" counter (both null when no data). */
  phase?: { current: number; total: number } | null;
  /** Optional next-gate display name. Null when unknown. */
  nextGateName?: string | null;
  /** Burn total in cents. Null when no cost data available. */
  costBurnedCents?: number | null;
  /** Last-activity relative string (already formatted). Null when unknown. */
  lastActivity?: string | null;
  /** Click handler — the parent is responsible for routing. */
  onClick?: () => void;
  /** Aria-label override when the slug alone is insufficient. */
  ariaLabel?: string;
}

function StatusDot({ status }: { status: ProjectCardStatus }) {
  if (status === "waiting") {
    // Pale yellow literal hex — token doesn't ship until MIGRATION-PLAN §3.
    return (
      <span
        data-testid="project-card-status-dot"
        data-status="waiting"
        aria-label="Waiting on gate"
        className="h-2 w-2 rounded-full bg-[#f4f692]"
      />
    );
  }
  if (status === "working") {
    return (
      <span
        data-testid="project-card-status-dot"
        data-status="working"
        aria-label="Working"
        className="h-2 w-2 rounded-full bg-primary animate-pulse"
      />
    );
  }
  return (
    <span
      data-testid="project-card-status-dot"
      data-status="idle"
      aria-label="Idle"
      className="h-2 w-2 rounded-full bg-[#166534]"
    />
  );
}

function formatCostUSD(cents: number | null | undefined): string {
  if (cents === null || cents === undefined) return "—";
  const dollars = cents / 100;
  return `$${dollars.toFixed(2)}`;
}

function formatProgress(progress: number | null): ReactNode {
  if (progress === null) return "—%";
  return `${Math.round(progress)}%`;
}

function formatPhase(phase: { current: number; total: number } | null | undefined): string {
  if (!phase) return "Phase — of —";
  return `Phase ${phase.current} of ${phase.total}`;
}

export function ProjectCard({
  slug,
  status,
  progress,
  phase,
  nextGateName,
  costBurnedCents,
  lastActivity,
  onClick,
  ariaLabel,
}: ProjectCardProps) {
  const nextGateText = nextGateName ? `Next gate: ${nextGateName}` : "Next gate: —";
  const subLine = `${formatPhase(phase)} · ${nextGateText}`;
  const costText = formatCostUSD(costBurnedCents);
  const activityText = lastActivity ? `last activity ${lastActivity}` : "last activity —";
  const footerLine = `${costText} burned · ${activityText}`;

  // Progress bar width — clamp to 0..100.
  const barWidth =
    progress === null ? 0 : Math.max(0, Math.min(100, progress));

  return (
    <button
      type="button"
      onClick={onClick}
      aria-label={ariaLabel ?? slug}
      data-testid="project-card"
      className={cn(
        "group block w-full text-left",
        "rounded-lg border border-border bg-transparent",
        "px-6 py-6",
        "transition-colors hover:border-primary/40",
        "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background",
      )}
    >
      {/* Title row: slug + status dot */}
      <div className="flex items-center justify-between gap-3">
        <span
          data-testid="project-card-title"
          className="font-bold uppercase text-[16px] tracking-[0.04em] text-foreground"
        >
          {slug}
        </span>
        <StatusDot status={status} />
      </div>

      {/* Hero stat — 72px Inter Black volt */}
      <div
        data-testid="project-card-hero"
        className="mt-4 font-black text-[72px] leading-none text-primary"
      >
        {formatProgress(progress)}
      </div>

      {/* Sub-line */}
      <div
        data-testid="project-card-subline"
        className="mt-3 text-[14px] font-medium text-muted-foreground"
      >
        {subLine}
      </div>

      {/* Progress bar — 8px tall charcoal track, volt fill, sharp 4px corners */}
      <div
        data-testid="project-card-progress-track"
        className="mt-4 h-2 w-full rounded-[4px] bg-border overflow-hidden"
      >
        <div
          data-testid="project-card-progress-fill"
          className="h-full rounded-[4px] bg-primary transition-[width]"
          style={{ width: `${barWidth}%` }}
        />
      </div>

      {/* Footer line */}
      <div
        data-testid="project-card-footer"
        className="mt-4 text-[12px] font-normal text-muted-foreground"
      >
        {footerLine}
      </div>
    </button>
  );
}
