import * as React from "react";

const COVERAGE_GLYPH_MAP: Record<
  EvalCoverageState,
  { sym: string; label: string }
> = {
  pass: { sym: "✓", label: "covered" },
  fail: { sym: "✓", label: "covered (fail)" },
  pending: { sym: "·", label: "evaluating" },
  errored: { sym: "!", label: "judge errored" },
  skip: { sym: "–", label: "not yet covered" },
  miss: { sym: "?", label: "no coverage" },
};

const EVAL_PILL_MAP: Record<EvalCoverageState, { sym: string; label: string }> =
  {
    pass: { sym: "✓", label: "PASS" },
    fail: { sym: "✗", label: "FAIL" },
    pending: { sym: "·", label: "EVAL" },
    errored: { sym: "!", label: "ERR" },
    skip: { sym: "–", label: "SKIP" },
    miss: { sym: "?", label: "MISS" },
  };

export type KeeperState =
  | "primary"
  | "candidate"
  | "empty"
  | "blocked"
  | "pending";

export interface KeeperGlyphProps {
  state: KeeperState;
  count?: number;
  total?: number;
  title?: string;
}

export function KeeperGlyph({ state, count, total, title }: KeeperGlyphProps) {
  // 2026-05-12: hide the empty-rollup placeholder entirely. Projects/episodes
  // with no takes were rendering a free-floating em-dash next to the name
  // (e.g. `▾tartarus—`) that read as "broken data" instead of "nothing here
  // yet." Pre-leaf nodes (project/episode/scene) get cleaner labels; leaf
  // beats with explicit state="empty" still call the renderer with count/total
  // so the caller can inspect, but we just don't paint a glyph.
  if (state === "empty" && (total ?? 0) === 0) {
    return null;
  }
  const tip =
    title ||
    (state === "primary"
      ? `keeper set${count != null ? ` · ${count}/${total}` : ""}`
      : state === "candidate"
        ? `${total || 0} take${total === 1 ? "" : "s"}, no primary yet`
        : state === "empty"
          ? "no takes yet"
          : state === "blocked"
            ? "blocked — cannot generate"
            : state === "pending"
              ? "in-flight"
              : "—");
  let glyph: React.ReactNode;
  if (state === "primary")
    glyph = (
      <svg className="kg-svg" viewBox="0 0 12 12" aria-hidden="true">
        <path
          d="M6 1.2 L7.5 4.5 L11 5 L8.5 7.4 L9.1 11 L6 9.3 L2.9 11 L3.5 7.4 L1 5 L4.5 4.5 Z"
          fill="currentColor"
        />
      </svg>
    );
  else if (state === "candidate")
    glyph = (
      <svg className="kg-svg" viewBox="0 0 12 12" aria-hidden="true">
        <circle
          cx="6"
          cy="6"
          r="4"
          fill="none"
          stroke="currentColor"
          strokeWidth="1.4"
        />
      </svg>
    );
  else if (state === "blocked")
    glyph = (
      <svg className="kg-svg" viewBox="0 0 12 12" aria-hidden="true">
        <path d="M6 2 L11 10 L1 10 Z" fill="currentColor" />
        <rect x="5.4" y="4.5" width="1.2" height="3" fill="var(--bg-1)" />
        <rect x="5.4" y="8.2" width="1.2" height="1.2" fill="var(--bg-1)" />
      </svg>
    );
  else if (state === "pending")
    glyph = (
      <svg className="kg-svg" viewBox="0 0 12 12" aria-hidden="true">
        <circle cx="6" cy="6" r="2" fill="currentColor" />
      </svg>
    );
  else glyph = <span className="kg-dash">—</span>;

  return (
    <span className={`keeper-glyph kg-${state}`} title={tip}>
      {glyph}
      {count != null &&
        total != null &&
        state !== "empty" &&
        state !== "blocked" && (
          <span className="kg-count tabular">
            {count}
            <span className="kg-slash">/</span>
            {total}
          </span>
        )}
    </span>
  );
}

export type EvalCoverageState =
  | "pass"
  | "fail"
  | "pending"
  | "errored"
  | "skip"
  | "miss";

export interface EvalCoverageGlyphProps {
  state: EvalCoverageState;
  score?: number | null;
  showScore?: boolean;
}

export function EvalCoverageGlyph({
  state,
  score,
  showScore,
}: EvalCoverageGlyphProps) {
  const m = COVERAGE_GLYPH_MAP[state] || COVERAGE_GLYPH_MAP.miss;
  return (
    <span className={`eval-cov ${state}`} title={m.label}>
      <span className="ec-sym">{m.sym}</span>
      {showScore && score != null && (
        <span className="ec-score tabular">{score.toFixed(2)}</span>
      )}
    </span>
  );
}

export interface EvalPillProps {
  state: EvalCoverageState;
  score?: number | null;
  showScores?: boolean;
}

export function EvalPill({ state, score, showScores }: EvalPillProps) {
  const m = EVAL_PILL_MAP[state] || EVAL_PILL_MAP.miss;
  return (
    <span className={`eval-pill ${state}`}>
      <span className="ep-sym">{m.sym}</span>
      <span className="ep-label">{m.label}</span>
      {showScores && score != null && (
        <span className="ep-score tabular">{score.toFixed(2)}</span>
      )}
    </span>
  );
}

export function Crown() {
  return (
    <svg
      className="crown"
      width="10"
      height="10"
      viewBox="0 0 12 12"
      fill="currentColor"
    >
      <path d="M1 4l2 4h6l2-4-2.5 1.5L6 2 3.5 5.5z" />
    </svg>
  );
}

export interface CircleMarkProps {
  idx: number | string;
}

export function CircleMark({ idx }: CircleMarkProps) {
  return <div className="circle-mark mono">{idx}</div>;
}

export interface StatusDotProps {
  status: string;
}

export function StatusDot({ status }: StatusDotProps) {
  return <span className={`status-dot ${status}`}></span>;
}

export type MediaKind = "still" | "video";

export interface MediaGlyphProps {
  media: MediaKind;
}

export function MediaGlyph({ media }: MediaGlyphProps) {
  if (media === "still") {
    return (
      <span className="media-glyph still" title="still image">
        <svg width="9" height="9" viewBox="0 0 12 12" aria-hidden="true">
          <rect
            x="1"
            y="2"
            width="10"
            height="8"
            rx="1"
            fill="none"
            stroke="currentColor"
            strokeWidth="1.2"
          />
          <circle cx="4" cy="5" r="0.9" fill="currentColor" />
          <path
            d="M2 9 L5 6 L7 8 L9 6.5 L11 9 L11 10 L1 10 L1 9 Z"
            fill="currentColor"
            opacity="0.85"
          />
        </svg>
      </span>
    );
  }
  return (
    <span className="media-glyph video" title="video">
      <svg width="9" height="9" viewBox="0 0 12 12" aria-hidden="true">
        <path d="M2.5 1.5 L10 6 L2.5 10.5 Z" fill="currentColor" />
      </svg>
    </span>
  );
}
