import * as React from 'react';
import { ClipboardCheck } from 'lucide-react';
import { cn } from '../../lib/utils';

/** One guardrail/dimension the reviewer scores (key drives storage, label is shown). */
export interface ReviewDimension {
  key: string;
  label: string;
}

/**
 * A reviewer's structured judgement of an AI-generated draft: an overall verdict
 * plus per-guardrail scores/notes and a free-text overall note. Drives the
 * downstream AI revise loop.
 */
export interface ReviewScore {
  /** Overall verdict — the primary signal for the revise loop. */
  verdict?: 'approve' | 'revise' | 'reject';
  /** Per-dimension score (1–5) + optional note, keyed by dimension key. */
  dimensions?: Record<string, { score?: number; note?: string }>;
  /** Free-text overall note. */
  overallNote?: string;
}

/**
 * The default guardrail dimensions, mirroring a content-guardrail judge. Callers
 * can override with any dimension set — the scorecard renders whatever it's given,
 * so it stays generic (this is one sensible instance, not the design driver).
 */
export const DEFAULT_REVIEW_DIMENSIONS: ReviewDimension[] = [
  { key: 'political-sensitivity', label: 'Political sensitivity' },
  { key: 'source-reliability', label: 'Source reliability' },
  { key: 'recency', label: 'Recency' },
  { key: 'tone-and-voice', label: 'Tone and voice' },
  { key: 'accuracy', label: 'Accuracy' },
];

type Verdict = NonNullable<ReviewScore['verdict']>;

/** Redundant (color + label) tone per verdict — never rely on color alone. */
const VERDICT_TONE: Record<Verdict, { label: string; bg: string; text: string }> = {
  approve: { label: 'Approve', bg: 'bg-emerald-600', text: 'text-white' },
  revise: { label: 'Revise', bg: 'bg-amber-500', text: 'text-white' },
  reject: { label: 'Reject', bg: 'bg-red-600', text: 'text-white' },
};

const VERDICTS: Verdict[] = ['approve', 'revise', 'reject'];
const SCORE_VALUES = [1, 2, 3, 4, 5];

export interface ReviewScorecardProps {
  /** Controlled value — the reviewer's current judgement. */
  value: ReviewScore;
  /** Called with the next value on every change (immutable). */
  onChange: (next: ReviewScore) => void;
  /** The dimensions to score. Defaults to DEFAULT_REVIEW_DIMENSIONS. */
  dimensions?: ReviewDimension[];
  /** Render values as read-only (no inputs). */
  readOnly?: boolean;
  title?: string;
  className?: string;
}

/** A 1–5 score picker (clickable dots), read-only when the scorecard is. */
function ScorePicker({
  label,
  value,
  onChange,
  readOnly,
}: {
  label: string;
  value?: number;
  onChange: (score: number) => void;
  readOnly?: boolean;
}) {
  return (
    <div className="flex items-center gap-1" role="group" aria-label={`${label} score`}>
      {SCORE_VALUES.map((n) => {
        const filled = value != null && n <= value;
        if (readOnly) {
          return (
            <span
              key={n}
              className={cn('inline-block w-3.5 h-3.5 rounded-full', filled ? 'bg-gray-900' : 'bg-gray-200')}
              aria-hidden="true"
            />
          );
        }
        return (
          <button
            key={n}
            type="button"
            onClick={() => onChange(n)}
            aria-label={`${label} score ${n}`}
            aria-pressed={value === n}
            className={cn(
              'w-4 h-4 rounded-full transition-colors',
              filled ? 'bg-gray-900' : 'bg-gray-200 hover:bg-gray-300',
            )}
          />
        );
      })}
      <span className="ml-1.5 text-xs text-gray-500 tabular-nums">{value != null ? `${value}/5` : '—'}</span>
    </div>
  );
}

/**
 * A controlled scorecard for a reviewer's structured judgement of an AI-generated
 * draft (768w.16.10.4). Presentational + bring-your-own-data: it renders a verdict
 * segmented control, one scored row per guardrail dimension, and an overall note —
 * emitting the next ReviewScore (immutably) on every change. It never fetches or
 * persists; the app owns the data and the downstream revise loop.
 */
export function ReviewScorecard({
  value,
  onChange,
  dimensions = DEFAULT_REVIEW_DIMENSIONS,
  readOnly,
  title = 'Review',
  className,
}: ReviewScorecardProps) {
  const setDimension = (key: string, patch: { score?: number; note?: string }) => {
    const prev = value.dimensions?.[key] ?? {};
    onChange({
      ...value,
      dimensions: { ...value.dimensions, [key]: { ...prev, ...patch } },
    });
  };

  return (
    <div className={cn('rounded-xl border bg-card text-card-foreground shadow p-5 space-y-4', className)}>
      {/* Header + verdict */}
      <div className="flex items-center justify-between gap-3">
        <div className="flex items-center gap-2 min-w-0">
          <ClipboardCheck className="w-4 h-4 text-gray-400 flex-shrink-0" aria-hidden="true" />
          <h3 className="text-sm font-semibold text-gray-900 truncate">{title}</h3>
        </div>
        {readOnly ? (
          value.verdict ? (
            <span
              className={cn(
                'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium flex-shrink-0',
                VERDICT_TONE[value.verdict].bg,
                VERDICT_TONE[value.verdict].text,
              )}
            >
              {VERDICT_TONE[value.verdict].label}
            </span>
          ) : (
            <span className="text-xs text-gray-500 flex-shrink-0">No verdict</span>
          )
        ) : (
          <div className="inline-flex rounded-lg border bg-gray-50 p-0.5 flex-shrink-0" role="group" aria-label="Verdict">
            {VERDICTS.map((v) => {
              const tone = VERDICT_TONE[v];
              const selected = value.verdict === v;
              return (
                <button
                  key={v}
                  type="button"
                  onClick={() => onChange({ ...value, verdict: v })}
                  aria-pressed={selected}
                  className={cn(
                    'px-3 py-1 text-xs font-medium rounded-md transition-colors',
                    selected ? cn(tone.bg, tone.text) : 'text-gray-600 hover:text-gray-900',
                  )}
                >
                  {tone.label}
                </button>
              );
            })}
          </div>
        )}
      </div>

      {/* Per-dimension rows */}
      <div className="space-y-3">
        {dimensions.map((dim) => {
          const dimVal = value.dimensions?.[dim.key] ?? {};
          return (
            <div key={dim.key} className="space-y-1.5">
              <div className="flex items-center justify-between gap-3">
                <span className="text-sm text-gray-900">{dim.label}</span>
                <ScorePicker
                  label={dim.label}
                  value={dimVal.score}
                  onChange={(score) => setDimension(dim.key, { score })}
                  readOnly={readOnly}
                />
              </div>
              {readOnly ? (
                dimVal.note ? <p className="text-xs text-gray-500 break-words">{dimVal.note}</p> : null
              ) : (
                <input
                  type="text"
                  value={dimVal.note ?? ''}
                  onChange={(e) => setDimension(dim.key, { note: e.target.value })}
                  aria-label={`${dim.label} note`}
                  placeholder="Add a note…"
                  className="w-full rounded-md border px-2 py-1 text-xs"
                />
              )}
            </div>
          );
        })}
      </div>

      {/* Overall note */}
      <div className="border-t pt-3 space-y-1.5">
        <span className="text-xs font-medium text-gray-600">Overall note</span>
        {readOnly ? (
          <p className="text-sm text-gray-700 break-words">{value.overallNote || <span className="text-gray-400">—</span>}</p>
        ) : (
          <textarea
            value={value.overallNote ?? ''}
            onChange={(e) => onChange({ ...value, overallNote: e.target.value })}
            aria-label="Overall note"
            rows={2}
            placeholder="Summarise your feedback…"
            className="w-full rounded-md border px-2 py-1 text-sm"
          />
        )}
      </div>
    </div>
  );
}
