import clsx from 'clsx'

export function Card({
  children,
  className,
}: {
  children: React.ReactNode
  className?: string
}) {
  return (
    <div
      className={clsx(
        'rounded-xl border border-[var(--color-line)] bg-white p-5 shadow-[0_1px_2px_rgba(0,0,0,0.03)]',
        className,
      )}
    >
      {children}
    </div>
  )
}

export function Button({
  children,
  variant = 'primary',
  className,
  ...props
}: React.ButtonHTMLAttributes<HTMLButtonElement> & {
  variant?: 'primary' | 'secondary' | 'quiet' | 'danger'
}) {
  const styles = {
    primary: 'bg-[var(--color-accent)] text-white hover:opacity-90',
    secondary:
      'bg-white text-[var(--color-ink)] border border-[var(--color-line)] hover:bg-[var(--color-paper)]',
    quiet: 'text-[var(--color-muted)] hover:text-[var(--color-ink)]',
    danger: 'bg-white text-[#9b3232] border border-[#e8cfcf] hover:bg-[#fdf5f5]',
  }[variant]
  return (
    <button
      {...props}
      className={clsx(
        'inline-flex items-center justify-center rounded-lg px-4 py-2 text-sm font-medium transition disabled:cursor-not-allowed disabled:opacity-50',
        styles,
        className,
      )}
    >
      {children}
    </button>
  )
}

/** A caveat the reader needs before believing a number on the same screen. */
export function Caveat({ children }: { children: React.ReactNode }) {
  return (
    <p className="rounded-lg border border-[#f0e2cd] bg-[var(--color-warn-soft)] px-3 py-2 text-xs leading-relaxed text-[var(--color-warn)]">
      {children}
    </p>
  )
}

export function Label({ children }: { children: React.ReactNode }) {
  return (
    <span className="text-[11px] font-medium uppercase tracking-wide text-[var(--color-muted)]">
      {children}
    </span>
  )
}

/**
 * A per-dimension estimate. Shows n alongside the number, always — 8-12
 * AI-graded items is a noisy instrument and a bare percentage reads as far more
 * settled than the evidence is.
 */
export function DimensionBar({
  label,
  estimate,
  itemsObserved,
  itemsFlagged,
  itemsHinted = 0,
  movement,
}: {
  label: string
  estimate: number | null
  itemsObserved: number
  itemsFlagged: number
  /** Scored items that needed a nudge. Included in the estimate, so it is
   *  shown beside it rather than left to be discovered elsewhere. */
  itemsHinted?: number
  /** Responses the two graders could not agree on, held out until scored by
   *  hand. Deliberately NOT called "flagged" in the UI: the review screen uses
   *  that word for something else entirely, and one word for two meanings in
   *  one app is a way to be misread. */
  movement: number | null
}) {
  const pct = estimate === null ? null : Math.round(estimate * 100)
  return (
    <div className="space-y-1">
      <div className="flex items-baseline justify-between gap-2">
        <span className="text-sm">{label}</span>
        <span className="text-sm tabular-nums text-[var(--color-muted)]">
          {pct === null ? 'no evidence' : `${pct}%`}
          <span className="ml-1.5 text-xs">
            {itemsObserved > 0 && `n=${itemsObserved}`}
            {itemsHinted > 0 && `, ${itemsHinted} hinted`}
            {itemsFlagged > 0 && `, ${itemsFlagged} needs your score`}
          </span>
        </span>
      </div>
      <div className="h-1.5 overflow-hidden rounded-full bg-[var(--color-line)]">
        <div
          className="h-full rounded-full bg-[var(--color-accent)]"
          style={{ width: `${pct ?? 0}%` }}
        />
      </div>
      {movement !== null && Math.abs(movement) >= 10 && (
        <span className="text-xs text-[var(--color-muted)]">
          {movement > 0 ? `up ${movement}` : `down ${-movement}`} points since the previous round
        </span>
      )}
    </div>
  )
}
