//  File:    score-marks.tsx
//  Path:    apps/web/components/score-marks.tsx
//  Project: AI Risk Index — airiskindex.io
//  Author:  Simon-Pierre Boucher
//  Contact: contact@spboucher.ai
//  Copyright © 2026 Simon-Pierre Boucher. All rights reserved.
//
//  Description: Chart marks: score bars with CI whiskers, stat tiles, interval strips, meter.

/**
 * Chart marks for 0–100 scores with confidence bounds.
 * Specs per the dataviz skill: thin bars (≤24px) with a 4px rounded data-end
 * and a square baseline, track = lighter step of the same ramp, CI whisker in
 * muted ink, values in text tokens (never the series color).
 */

export interface Band {
  low: number;
  score: number;
  high: number;
}

const pct = (value: number): string => `${Math.max(0, Math.min(100, value))}%`;

/** Horizontal score bar with CI whisker on a 0–100 track. */
export function ScoreBar({ band, thick = 10 }: { band: Band; thick?: number }): JSX.Element {
  return (
    <div
      aria-hidden="true"
      className="relative w-full rounded-r-[4px] bg-[var(--seq-track)]"
      style={{ height: thick }}
    >
      <div
        className="absolute inset-y-0 left-0 rounded-r-[4px] bg-[var(--seq)]"
        style={{ width: pct(band.score) }}
      />
      {/* CI whisker: hairline + end ticks, muted ink over the track */}
      <div
        className="absolute top-1/2 h-px -translate-y-1/2 bg-[var(--muted)]"
        style={{ left: pct(band.low), width: pct(band.high - band.low) }}
      />
      <div
        className="absolute top-1/2 h-[7px] w-px -translate-y-1/2 bg-[var(--muted)]"
        style={{ left: pct(band.low) }}
      />
      <div
        className="absolute top-1/2 h-[7px] w-px -translate-y-1/2 bg-[var(--muted)]"
        style={{ left: pct(band.high) }}
      />
    </div>
  );
}

/** Compact interval strip for stat tiles: band wash + point marker. */
export function IntervalStrip({ band }: { band: Band }): JSX.Element {
  return (
    <div aria-hidden="true" className="relative h-[6px] w-full rounded-[3px] bg-[var(--seq-track)]">
      <div
        className="absolute inset-y-0 rounded-[3px] bg-[var(--seq)] opacity-40"
        style={{ left: pct(band.low), width: pct(band.high - band.low) }}
      />
      {/* point marker ≥8px with a 2px surface ring */}
      <div
        className="absolute top-1/2 h-[10px] w-[10px] -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-[var(--surface-1)] bg-[var(--seq)]"
        style={{ left: pct(band.score) }}
      />
    </div>
  );
}

/** Stat tile: label · value · CI, with the interval strip underneath. */
export function ScoreTile({
  label,
  band,
  hint,
}: {
  label: string;
  band: Band;
  hint: string;
}): JSX.Element {
  return (
    <div className="card p-5">
      <p className="text-sm font-medium text-[var(--ink-2)]">{label}</p>
      <p className="mt-1 text-4xl font-semibold">
        {band.score.toFixed(0)}
        <span className="ml-2 align-middle text-sm font-normal text-[var(--muted)]">
          CI {band.low.toFixed(0)}–{band.high.toFixed(0)}
        </span>
      </p>
      <div className="mt-3">
        <IntervalStrip band={band} />
      </div>
      <p className="mt-3 text-xs leading-relaxed text-[var(--muted)]">{hint}</p>
    </div>
  );
}

/**
 * Dot plot of labeled scores on a shared 0–100 axis: hairline gridlines,
 * CI band wash, ≥10px point marker with a 2px surface ring. Rows are
 * direct-labeled, single hue — no legend needed.
 */
export function SubScoreDotPlot({
  rows,
}: {
  rows: Array<{ label: string; band: Band }>;
}): JSX.Element {
  return (
    <div>
      {rows.map((row) => (
        <div key={row.label} className="flex items-center gap-3 py-2.5">
          <span className="w-24 shrink-0 text-sm font-medium text-[var(--ink-2)] sm:w-28">
            {row.label}
          </span>
          <div aria-hidden="true" className="relative h-[26px] min-w-0 flex-1">
            {[0, 25, 50, 75, 100].map((tick) => (
              <div
                key={tick}
                className="absolute inset-y-0 w-px bg-[var(--grid)]"
                style={{ left: pct(tick) }}
              />
            ))}
            <div
              className="absolute top-1/2 h-[10px] -translate-y-1/2 rounded-full bg-[var(--seq-track)]"
              style={{ left: pct(row.band.low), width: pct(row.band.high - row.band.low) }}
            />
            <div
              className="absolute top-1/2 h-[13px] w-[13px] -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-[var(--surface-1)] bg-[var(--seq)]"
              style={{ left: pct(row.band.score) }}
            />
          </div>
          <span className="w-9 shrink-0 text-right text-lg font-semibold tabular-nums">
            {row.band.score.toFixed(0)}
          </span>
        </div>
      ))}
      <div className="flex items-center gap-3" aria-hidden="true">
        <span className="w-24 shrink-0 sm:w-28" />
        <div className="relative h-4 min-w-0 flex-1 text-[10px] text-[var(--muted)]">
          <span className="absolute left-0">0</span>
          <span className="absolute left-1/4 -translate-x-1/2">25</span>
          <span className="absolute left-1/2 -translate-x-1/2">50</span>
          <span className="absolute left-3/4 -translate-x-1/2">75</span>
          <span className="absolute right-0">100</span>
        </div>
        <span className="w-9 shrink-0" />
      </div>
    </div>
  );
}

/**
 * Compact histogram over the 0–100 scale (bins of equal width). Emphasis
 * form: recessive context columns with an optional accent marker line
 * ("this occupation"). Columns are thin with rounded caps, square baseline.
 */
export function DistributionChart({
  bins,
  marker,
  markerLabel,
  height = 96,
  accent = false,
}: {
  bins: number[];
  marker?: number;
  markerLabel?: string;
  height?: number;
  accent?: boolean;
}): JSX.Element {
  const max = Math.max(1, ...bins);
  const binWidth = 100 / bins.length;
  return (
    <div>
      <div aria-hidden="true" className="relative" style={{ height }}>
        {/* baseline */}
        <div className="absolute inset-x-0 bottom-0 h-px bg-[var(--baseline)]" />
        {bins.map((count, index) => (
          <div
            key={index}
            className={`absolute bottom-0 rounded-t-[3px] ${accent && marker === undefined ? "bg-[var(--seq)]" : marker !== undefined ? "bg-[var(--seq-track)]" : "bg-[var(--seq)]"}`}
            style={{
              left: `calc(${index * binWidth}% + 1px)`,
              width: `calc(${binWidth}% - 2px)`,
              height: `${Math.max(count > 0 ? 3 : 0, (count / max) * 100)}%`,
            }}
          />
        ))}
        {marker !== undefined && (
          <>
            <div
              className="absolute inset-y-0 w-[2px] rounded bg-[var(--seq)]"
              style={{ left: pct(marker) }}
            />
            {markerLabel && (
              <span
                className="absolute -top-1 -translate-x-1/2 whitespace-nowrap rounded-full bg-[var(--seq)] px-2 py-0.5 text-[10px] font-semibold text-white"
                style={{ left: `clamp(3.5rem, ${pct(marker)}, calc(100% - 3.5rem))` }}
              >
                {markerLabel}
              </span>
            )}
          </>
        )}
      </div>
      <div aria-hidden="true" className="relative mt-1 h-4 text-[10px] text-[var(--muted)]">
        <span className="absolute left-0">0</span>
        <span className="absolute left-1/4 -translate-x-1/2">25</span>
        <span className="absolute left-1/2 -translate-x-1/2">50</span>
        <span className="absolute left-3/4 -translate-x-1/2">75</span>
        <span className="absolute right-0">100</span>
      </div>
    </div>
  );
}

/** Meter: fill + same-ramp track (marks-and-anatomy §Figures). */
export function ShareMeter({ share, label }: { share: number; label: string }): JSX.Element {
  const value = Math.round(share * 100);
  return (
    <div className="card p-5">
      <div className="flex items-baseline justify-between">
        <p className="text-sm font-medium text-[var(--ink-2)]">{label}</p>
        <p className="text-2xl font-semibold">{value}%</p>
      </div>
      <div className="mt-3 h-[10px] w-full rounded-[4px] bg-[var(--seq-track)]">
        <div
          className="h-full rounded-[4px] bg-[var(--seq)]"
          style={{ width: `${value}%` }}
          aria-hidden="true"
        />
      </div>
    </div>
  );
}
