import { useCoreServices } from '@learnitive/context';
import { projectFilePath } from '@learnitive/project-storage';
import type {
  PaperReviewEngineMode,
  PaperReviewFinding,
  PaperReviewMode,
  PaperReviewRun,
} from '@learnitive/service-core';
import { Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, toast } from '@learnitive/ui-components';
import { WsPath } from '@learnitive/ws-path';
import { useAtomValue } from 'jotai';
import { CheckCircle2, Circle, Cloud, FileText, HardDrive, LoaderCircle, OctagonX, Server, Settings2, Sparkles } from 'lucide-react';
import React from 'react';
import type { SourceAnchor } from '@learnitive/latex-source';
import { openAiSettingsDialog } from './ai-settings-events';
import { AI_LARGE_DIALOG_CONTENT_CLASS } from './ai-modal-layout';

// Kept for API compatibility with the pre-BF50 dialog. Selection review now
// lives in AI Suggest; Paper Review modes operate on a revision-bound project.
export type AiReviewScope = 'full-manuscript' | 'current-section' | 'selection';
export type AiReviewFixAction = 'suggest-rewrite' | 'find-evidence' | 'find-citation' | 'explain' | 'ignore';
export type AiReviewResult = PaperReviewRun;

type LegacyReviewFragment = {
  id: string;
  filePath: string;
  text: string;
  anchor: SourceAnchor;
};

const MODE_COPY: Record<PaperReviewMode, { title: string; description: string }> = {
  quick: {
    title: 'Quick Review',
    description: 'Fast writing, clarity and LaTeX-aware review with one reviewer.',
  },
  paper: {
    title: 'Paper Review',
    description: 'Structured scientific review of claims, experiments, references, figures and tables.',
  },
  deep: {
    title: 'Deep Review',
    description: 'Reviewer committee, literature context, disagreement resolution, meta-review and verification.',
  },
};

function modeCopy(value: PaperReviewMode): { title: string; description: string } {
  return MODE_COPY[value]!;
}

const SCORE_LABELS: Array<[keyof NonNullable<PaperReviewRun['metaReview']>['scores'], string]> = [
  ['novelty', 'Novelty'],
  ['technicalSoundness', 'Technical soundness'],
  ['experimentalQuality', 'Experimental quality'],
  ['clarity', 'Clarity'],
  ['reproducibility', 'Reproducibility'],
  ['relatedWork', 'Related work'],
  ['overall', 'Overall'],
];

function providerDescription(settings: { enabled: boolean; provider: string; model?: string; localModelId?: string; hasApiKey?: boolean }, ollamaRemote = false): string {
  if (!settings.enabled || settings.provider === 'disabled') return 'AI is disabled. Choose Local AI, Ollama or configure BYOK AI first.';
  if (settings.provider === 'local') return `Local AI${settings.localModelId ? ` · ${settings.localModelId}` : ''}`;
  if (settings.provider === 'ollama') return `${ollamaRemote ? 'Ollama Cloud' : 'Local Ollama'}${settings.model ? ` · ${settings.model}` : ''}`;
  const names: Record<string, string> = {
    openai: 'OpenAI',
    anthropic: 'Anthropic',
    gemini: 'Gemini',
    openrouter: 'OpenRouter',
    'openai-compatible': 'OpenAI-compatible',
  };
  return `${names[settings.provider] ?? settings.provider}${settings.model ? ` · ${settings.model}` : ''} · using your browser-stored BYOK credential`;
}

function reviewStageIcon(run: PaperReviewRun, stage: string) {
  if (run.completedStages.includes(stage)) {
    return <span className="flex size-6 shrink-0 items-center justify-center rounded-full bg-yellow-400 text-yellow-950"><CheckCircle2 aria-hidden="true" className="size-4" /></span>;
  }
  if (run.status === 'running' && run.currentStage === stage) {
    return <span className="flex size-6 shrink-0 items-center justify-center rounded-full bg-yellow-100 text-yellow-700 dark:bg-yellow-950/50 dark:text-yellow-300"><LoaderCircle aria-hidden="true" className="size-4 animate-spin" /></span>;
  }
  if (run.status === 'failed' && run.currentStage === stage) {
    return <span className="flex size-6 shrink-0 items-center justify-center rounded-full bg-destructive/10 text-destructive"><OctagonX aria-hidden="true" className="size-4" /></span>;
  }
  return <span className="flex size-6 shrink-0 items-center justify-center rounded-full border bg-background text-muted-foreground/50"><Circle aria-hidden="true" className="size-3" /></span>;
}

function severityClass(severity: PaperReviewFinding['severity']): string {
  return severity === 'critical' || severity === 'major'
    ? 'border-destructive/30 bg-destructive/5'
    : 'border-border bg-background';
}

export function AiReviewDialog({
  open,
  onOpenChange,
  wsName,
  currentFile: _currentFile,
  selection: _selection,
  onFix,
  onOpenReview,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  wsName: string;
  currentFile: string;
  selection?: { anchor: SourceAnchor; text: string };
  onFix?: (action: AiReviewFixAction, fragment?: LegacyReviewFragment) => void;
  onOpenReview?: () => void;
}) {
  const { projectAi, projectAiWriting, navigation, latexSource, fileSystem } = useCoreServices();
  const aiSettings = useAtomValue(projectAi.$settings);
  const localAi = useAtomValue(projectAi.$localAi);
  const ollama = useAtomValue(projectAi.$ollama);
  const reviewVersion = useAtomValue(projectAiWriting.$version);
  const [mode, setMode] = React.useState<PaperReviewMode>('deep');
  const [multiModelReview, setMultiModelReview] = React.useState(false);
  const [includePaperMemory, setIncludePaperMemory] = React.useState(true);
  const [includeLiterature, setIncludeLiterature] = React.useState(true);
  const [includeReproducibility, setIncludeReproducibility] = React.useState(false);
  const [starting, setStarting] = React.useState(false);
  const [fixingId, setFixingId] = React.useState<string>();
  const [loadedRun, setLoadedRun] = React.useState<PaperReviewRun>();
  const [showSetup, setShowSetup] = React.useState(false);
  const [fullReport, setFullReport] = React.useState<{ path: string; markdown: string }>();
  const [reportLoading, setReportLoading] = React.useState(false);

  const liveRun = showSetup ? undefined : (projectAiWriting.getLatestReviewRun(wsName) ?? loadedRun);
  const selectedOllamaModel = ollama.models.find((item) => item.model === aiSettings.model || item.name === aiSettings.model);
  const providerLabel = providerDescription(aiSettings, selectedOllamaModel?.remote === true);
  const cloudProfiles = projectAi.getEphemeralCloudProfiles().filter((profile) => profile.model.trim());
  const localReady = localAi.model?.status === 'ready' || localAi.model?.status === 'installed';
  const configuredEngineMode: PaperReviewEngineMode = aiSettings.provider === 'local' ? 'local' : 'current-provider';
  const engineMode: PaperReviewEngineMode = multiModelReview && cloudProfiles.length >= 2 ? 'multi-model' : configuredEngineMode;
  const ollamaReady = aiSettings.enabled && aiSettings.provider === 'ollama' && Boolean(aiSettings.model.trim()) && ollama.status === 'connected' && ollama.baseUrl === aiSettings.baseUrl && Boolean(selectedOllamaModel) && !(selectedOllamaModel?.remote && aiSettings.privacyMode);
  const byokReady = aiSettings.enabled && aiSettings.provider !== 'disabled' && aiSettings.provider !== 'local' && aiSettings.provider !== 'ollama' && aiSettings.hasApiKey;
  const engineReady = engineMode === 'local'
    ? localReady
    : engineMode === 'multi-model'
      ? cloudProfiles.length >= 2 && !aiSettings.privacyMode
      : aiSettings.provider === 'ollama'
        ? ollamaReady
        : Boolean(byokReady) && !aiSettings.privacyMode;


  void reviewVersion;

  React.useEffect(() => {
    if (!open) return;
    setShowSetup(false);
    setFullReport(undefined);
    let cancelled = false;
    void projectAiWriting.loadLatestReviewRun(wsName).then((run) => {
      if (!cancelled) setLoadedRun(run);
    });
    return () => { cancelled = true; };
  }, [open, projectAiWriting, wsName]);

  React.useEffect(() => {
    if (cloudProfiles.length < 2 && multiModelReview) setMultiModelReview(false);
  }, [cloudProfiles.length, multiModelReview]);

  const start = async () => {
    setShowSetup(false);
    setStarting(true);
    try {
      const run = await projectAiWriting.startPaperReview(wsName, {
        mode,
        engineMode,
        includePaperMemory,
        includeLiterature: mode === 'quick' ? false : includeLiterature,
        includeReproducibilityReviewer: mode === 'deep' && includeReproducibility,
      });
      setLoadedRun(run);
    } catch (reason) {
      toast.error(reason instanceof Error ? reason.message : 'AI Review failed.');
    } finally {
      setStarting(false);
    }
  };

  const resume = async () => {
    setShowSetup(false);
    setStarting(true);
    try {
      const run = await projectAiWriting.resumePaperReview(wsName);
      setLoadedRun(run);
    } catch (reason) {
      toast.error(reason instanceof Error ? reason.message : 'Unable to resume Paper Review.');
    } finally {
      setStarting(false);
    }
  };

  const openSource = (finding: PaperReviewFinding) => {
    if (!finding.location) return;
    const wsPath = WsPath.fromParts(wsName, projectFilePath(finding.location.filePath)).wsPath;
    latexSource.requestSelect(wsPath, finding.location.line || 1);
    navigation.goWsPath(wsPath);
  };

  const openReport = async () => {
    const reportPath = liveRun?.artifacts.reportPath;
    if (!reportPath || reportLoading) return;
    setReportLoading(true);
    try {
      // Review artifacts intentionally live below hidden `.learnitive/` and are
      // therefore not part of the visible workspace file index. Read the
      // artifact directly instead of navigating the editor to a path that its
      // visibility policy correctly excludes.
      const wsPath = WsPath.fromParts(wsName, projectFilePath(reportPath)).wsPath;
      const markdown = await fileSystem.readFileAsText(wsPath);
      if (markdown === undefined) throw new Error(`Review report not found: ${reportPath}`);
      setFullReport({ path: reportPath, markdown });
    } catch (reason) {
      toast.error(reason instanceof Error ? reason.message : 'Unable to open the full review report.');
    } finally {
      setReportLoading(false);
    }
  };

  const suggestFix = async (finding: PaperReviewFinding) => {
    setFixingId(finding.id);
    try {
      const suggestion = await projectAiWriting.suggestFindingFix(wsName, finding);
      if (!suggestion) {
        toast.info('Learnitive AI did not find a safe source change for this finding.');
        return;
      }
      toast.success('Suggested fix added to Review. The manuscript is unchanged until you accept it.');
      onOpenReview?.();
    } catch (reason) {
      toast.error(reason instanceof Error ? reason.message : 'Unable to suggest a fix.');
    } finally {
      setFixingId(undefined);
    }
  };

  const newReview = () => {
    setFullReport(undefined);
    setLoadedRun(undefined);
    setShowSetup(true);
    setMode('deep');
    setMultiModelReview(false);
  };

  const cancelAndReturnToSetup = async () => {
    try {
      await projectAiWriting.discardPaperReview(wsName);
      setLoadedRun(undefined);
      setShowSetup(true);
      toast.success('Review cancelled.');
    } catch (reason) {
      toast.error(reason instanceof Error ? reason.message : 'Unable to cancel Review.');
    }
  };

  const running = liveRun?.status === 'running' || liveRun?.status === 'queued';
  const resumable = liveRun && ['paused', 'cancelled', 'failed'].includes(liveRun.status);
  const completed = liveRun && (liveRun.status === 'complete' || liveRun.status === 'outdated');

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className={`${AI_LARGE_DIALOG_CONTENT_CLASS} p-4`} data-testid="ai-review-dialog">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2 pr-10">
            <Sparkles className="size-4" />AI Review
          </DialogTitle>
          <DialogDescription>
            Quick, Paper and Deep Review use the same source-grounded Review architecture as AI Suggest. Cloud reasoning uses only your browser-held BYOK credential; Learnitive never stores it in a review checkpoint.{' '}
            <a className="underline underline-offset-2" href="/docs/ai-review">AI Review guide</a>
          </DialogDescription>
        </DialogHeader>


        {fullReport ? (
          <section className="min-h-0 space-y-3" data-testid="ai-review-full-report">
            <div className="flex flex-wrap items-center justify-between gap-2 rounded-lg border bg-muted/20 p-3">
              <div className="min-w-0">
                <h3 className="font-semibold">Full review report</h3>
                <p className="mt-1 break-all font-mono text-[10px] text-muted-foreground">{fullReport.path}</p>
              </div>
              <Button type="button" variant="outline" size="sm" onClick={() => setFullReport(undefined)}>Back to review</Button>
            </div>
            <div className="max-h-[70dvh] overflow-auto rounded-lg border bg-background p-4 sm:p-6">
              <pre className="whitespace-pre-wrap break-words font-sans text-sm leading-6 text-foreground">{fullReport.markdown}</pre>
            </div>
          </section>
        ) : !liveRun || (!running && !completed && !resumable) ? (
          <div className="space-y-4">
            <div className="grid gap-3 md:grid-cols-3">
              {(Object.keys(MODE_COPY) as PaperReviewMode[]).map((value) => (
                <button
                  type="button"
                  key={value}
                  className={`rounded-lg border p-4 text-left ${mode === value ? 'border-foreground/30 bg-muted' : 'hover:bg-muted/40'}`}
                  onClick={() => setMode(value)}
                  data-testid={`ai-review-mode-${value}`}
                >
                  <div className="font-medium">{modeCopy(value).title}</div>
                  <p className="mt-1 text-xs leading-5 text-muted-foreground">{modeCopy(value).description}</p>
                </button>
              ))}
            </div>

            <div className="flex flex-wrap items-center gap-3 rounded-lg border bg-muted/20 p-3" data-testid="ai-review-provider-summary">
              <span className={`flex size-8 shrink-0 items-center justify-center rounded-full ${engineMode === 'local' ? 'bg-muted' : aiSettings.provider === 'ollama' && engineMode === 'current-provider' ? 'bg-emerald-500/10 text-emerald-700 dark:text-emerald-300' : 'bg-sky-500/10 text-sky-700 dark:text-sky-300'}`}>
                {engineMode === 'local' ? <HardDrive className="size-4" /> : aiSettings.provider === 'ollama' && engineMode === 'current-provider' ? <Server className="size-4" /> : <Cloud className="size-4" />}
              </span>
              <div className="min-w-0 flex-1">
                <div className="text-xs font-medium uppercase tracking-wide text-muted-foreground">AI</div>
                <div className="truncate text-sm font-medium">
                  {engineMode === 'multi-model'
                    ? `Multi-model committee · ${cloudProfiles.length} BYOK profiles`
                    : providerLabel}
                </div>
              </div>
              <Button type="button" size="sm" variant="outline" onClick={openAiSettingsDialog}>
                <Settings2 className="mr-1 size-3.5" />Change AI setting
              </Button>
            </div>

            <section className="rounded-lg border p-3">
              <div className="mb-2">
                <h3 className="text-sm font-medium">Review options</h3>
                <p className="mt-0.5 text-xs text-muted-foreground">Add research context only when it helps this review.</p>
              </div>
              <div className="divide-y">
                <label className="flex cursor-pointer items-start gap-3 py-2.5 text-xs">
                  <input role="switch" aria-checked={includePaperMemory} type="checkbox" className="mt-0.5 size-4" checked={includePaperMemory} onChange={(event) => setIncludePaperMemory(event.currentTarget.checked)} />
                  <span className="flex-1"><strong>Paper Memory</strong><span className="mt-0.5 block text-muted-foreground">Use evidence already indexed in this project.</span></span>
                </label>
                <label className={`flex items-start gap-3 py-2.5 text-xs ${mode === 'quick' ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}`}>
                  <input role="switch" aria-checked={includeLiterature} type="checkbox" className="mt-0.5 size-4" disabled={mode === 'quick'} checked={includeLiterature} onChange={(event) => setIncludeLiterature(event.currentTarget.checked)} />
                  <span className="flex-1"><strong>Research search</strong><span className="mt-0.5 block text-muted-foreground">Query real scholarly sources; unavailable search is skipped rather than invented.</span></span>
                </label>
                <label className={`flex items-start gap-3 py-2.5 text-xs ${mode !== 'deep' ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}`}>
                  <input role="switch" aria-checked={includeReproducibility} type="checkbox" className="mt-0.5 size-4" disabled={mode !== 'deep'} checked={includeReproducibility} onChange={(event) => setIncludeReproducibility(event.currentTarget.checked)} />
                  <span className="flex-1"><strong>Reproducibility reviewer</strong><span className="mt-0.5 block text-muted-foreground">Add a reviewer focused on implementation and replication details.</span></span>
                </label>
              </div>
            </section>

            {cloudProfiles.length >= 2 && (
              <details className="rounded-lg border px-3 py-2 text-xs" data-testid="ai-review-advanced">
                <summary className="cursor-pointer font-medium">Advanced</summary>
                <label className="mt-3 flex cursor-pointer items-start gap-3 rounded-md bg-muted/30 p-3">
                  <input role="switch" aria-checked={multiModelReview} type="checkbox" className="mt-0.5 size-4" checked={multiModelReview} onChange={(event) => setMultiModelReview(event.currentTarget.checked)} />
                  <span><strong>Multi-model reviewer committee</strong><span className="mt-0.5 block text-muted-foreground">Assign reviewer roles across {cloudProfiles.length} browser-stored BYOK profiles. Keys are never stored in the checkpoint.</span></span>
                </label>
              </details>
            )}

            {!engineReady && (
              <div className="rounded-lg border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-800 dark:text-amber-200">
                {engineMode === 'local'
                  ? 'Download and load the selected Local AI model before starting Review.'
                  : engineMode === 'current-provider' && aiSettings.provider === 'ollama'
                    ? selectedOllamaModel?.remote && aiSettings.privacyMode ? 'Privacy Mode blocks Ollama Cloud Review. Choose a local Ollama model or turn Privacy Mode off.' : ollama.error ?? 'Test the Ollama connection and choose an available Ollama model before starting Review.'
                    : aiSettings.privacyMode
                      ? 'Privacy Mode is on. Use Local AI or a local Ollama model, or turn it off before sending manuscript context to Ollama Cloud/BYOK AI.'
                      : aiSettings.provider === 'disabled'
                        ? 'AI is disabled. Choose Local AI, Ollama or configure BYOK AI.'
                        : engineMode === 'multi-model'
                          ? 'Multi-model Review needs at least two configured browser-stored BYOK AI profiles.'
                          : 'Add a browser-stored API key for the current BYOK AI provider before starting Review.'}
              </div>
            )}

            <div className="sticky bottom-0 z-10 flex flex-wrap items-center gap-3 rounded-lg border bg-background/95 p-3 shadow-sm backdrop-blur">
              <div className="min-w-0 flex-1 text-xs text-muted-foreground">
                <strong className="text-foreground">{modeCopy(mode).title}</strong>
                {' · '}
                {engineMode === 'multi-model' ? 'Multi-model committee' : providerLabel.replace(' · using your browser-stored BYOK credential', '')}
                {includePaperMemory ? ' · Paper Memory' : ''}
                {mode !== 'quick' && includeLiterature ? ' · Research search' : ''}
                {mode === 'deep' && includeReproducibility ? ' · Reproducibility' : ''}
              </div>
              <Button disabled={starting || !engineReady} onClick={() => void start()}>
                {starting ? <LoaderCircle className="mr-1 size-4 animate-spin" /> : <Sparkles className="mr-1 size-4" />}
                Start {modeCopy(mode).title}
              </Button>
            </div>
          </div>
        ) : liveRun && (running || resumable) ? (
          <div className="space-y-4" data-testid="ai-review-progress">
            <div className="rounded-lg border p-4">
              <div className="flex items-center justify-between gap-3">
                <div>
                  <div className="font-medium">{modeCopy(liveRun.mode).title}</div>
                  <div className="mt-1 text-xs text-muted-foreground">{liveRun.completedStages.length} / {liveRun.stages.length} stages completed</div>
                </div>
                <span className="rounded bg-muted px-2 py-1 text-xs">{liveRun.status}</span>
              </div>
              <div
                className="mt-4 h-1.5 overflow-hidden rounded-full bg-muted"
                role="progressbar"
                aria-label="AI Review progress"
                aria-valuemin={0}
                aria-valuemax={liveRun.stages.length}
                aria-valuenow={liveRun.completedStages.length}
              >
                <div
                  className="h-full rounded-full bg-yellow-400 transition-[width] duration-300"
                  style={{ width: `${liveRun.stages.length ? Math.round((liveRun.completedStages.length / liveRun.stages.length) * 100) : 0}%` }}
                />
              </div>
              <div className="mt-4 grid gap-1.5 sm:grid-cols-2">
                {liveRun.stages.map((stage) => {
                  const activeStage = liveRun.status === 'running' && liveRun.currentStage === stage;
                  const completedStage = liveRun.completedStages.includes(stage);
                  return (
                    <div
                      key={stage}
                      className={`flex items-center gap-2 rounded-md px-2 py-1.5 text-xs transition-colors ${
                        activeStage
                          ? 'bg-yellow-100/80 font-medium text-yellow-950 dark:bg-yellow-950/35 dark:text-yellow-100'
                          : completedStage
                            ? 'bg-yellow-50/60 dark:bg-yellow-950/15'
                            : ''
                      }`}
                    >
                      {reviewStageIcon(liveRun, stage)}<span>{stage}</span>
                    </div>
                  );
                })}
              </div>
              {liveRun.error && <p className="mt-3 rounded bg-destructive/10 p-2 text-xs text-destructive">{liveRun.error}</p>}
              {liveRun.artifacts.reviewerWarnings?.length ? <div className="mt-3 space-y-1 rounded bg-amber-500/10 p-2 text-xs"><strong>Local reviewer warnings</strong>{liveRun.artifacts.reviewerWarnings.map((warning) => <div key={`${warning.role}:${warning.message}`}>{warning.role}: {warning.message}</div>)}</div> : null}
            </div>
            <div className="flex justify-end gap-2">
              {running && <Button variant="outline" onClick={() => projectAiWriting.cancelPaperReview(wsName)}>Cancel Review</Button>}
              {resumable && <Button variant="outline" disabled={starting} onClick={() => void resume()}>{starting ? <LoaderCircle className="mr-1 size-4 animate-spin" /> : null}Resume from checkpoint</Button>}
              {resumable && <Button variant="destructive" onClick={() => void cancelAndReturnToSetup()}>Cancel Review</Button>}
            </div>
          </div>
        ) : liveRun && completed ? (
          <div className="space-y-4" data-testid="ai-review-result">
            <div className="rounded-lg border p-4">
              <div className="flex flex-wrap items-center justify-between gap-3">
                <div>
                  <div className="text-xs font-medium uppercase tracking-wide text-muted-foreground">AI reviewer assessment</div>
                  <div className="mt-1 text-2xl font-semibold">Paper Review {liveRun.status === 'outdated' ? 'Completed on older revision' : 'Complete'} ✓</div>
                </div>
                {liveRun.metaReview && <div className="rounded bg-muted px-3 py-2 text-xl font-semibold">{liveRun.metaReview.scores.overall.toFixed(1)} / 10</div>}
              </div>
              {liveRun.metaReview?.summary && <p className="mt-3 text-sm leading-6">{liveRun.metaReview.summary}</p>}
              {liveRun.error && <p className="mt-3 rounded bg-amber-500/10 p-2 text-xs">{liveRun.error}</p>}
              {liveRun.artifacts.reviewerWarnings?.length ? <div className="mt-3 rounded bg-amber-500/10 p-2 text-xs"><strong>Reviewer limitations:</strong> {liveRun.artifacts.reviewerWarnings.map((warning) => `${warning.role}: ${warning.message}`).join(' · ')}</div> : null}
            </div>

            {liveRun.metaReview && (
              <div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
                {SCORE_LABELS.map(([key, label]) => (
                  <div key={key} className="rounded-lg border p-3">
                    <div className="text-[10px] text-muted-foreground">{label}</div>
                    <div className="text-xl font-semibold">{liveRun.metaReview!.scores[key].toFixed(1)}</div>
                  </div>
                ))}
              </div>
            )}

            {liveRun.metaReview?.strengths.length ? (
              <section className="rounded-lg border p-3">
                <h3 className="font-semibold">Strengths</h3>
                <ul className="mt-2 list-disc space-y-1 pl-5 text-sm">{liveRun.metaReview.strengths.map((item) => <li key={item}>{item}</li>)}</ul>
              </section>
            ) : null}

            <section>
              <h3 className="mb-2 font-semibold">Review findings</h3>
              <div className="space-y-2">
                {liveRun.findings.length ? liveRun.findings.map((finding) => (
                  <div key={finding.id} className={`rounded-lg border p-3 text-xs ${severityClass(finding.severity)}`}>
                    <div className="flex flex-wrap items-start justify-between gap-2">
                      <div>
                        <div className="font-medium">{finding.title}</div>
                        <div className="mt-0.5 text-[10px] uppercase text-muted-foreground">{finding.reviewer} · {finding.severity} · {finding.verification}</div>
                      </div>
                      <div className="flex flex-wrap gap-1">
                        {finding.location && <Button size="sm" variant="ghost" onClick={() => openSource(finding)}>View Source</Button>}
                        {finding.actionable !== false && finding.location && (
                          <Button size="sm" variant="outline" disabled={fixingId === finding.id || finding.verification === 'outdated'} onClick={() => void suggestFix(finding)}>
                            {fixingId === finding.id ? <LoaderCircle className="mr-1 size-3.5 animate-spin" /> : <Sparkles className="mr-1 size-3.5" />}Suggest Fix
                          </Button>
                        )}
                      </div>
                    </div>
                    <p className="mt-2 leading-5 text-muted-foreground">{finding.detail}</p>
                    {finding.disagreement && <p className="mt-2 rounded bg-muted p-2"><strong>Reviewer disagreement:</strong> {finding.disagreement}</p>}
                    {finding.location && <div className="mt-2 font-mono text-[10px] text-muted-foreground">{finding.location.filePath}:{finding.location.line || '?'} · {finding.location.from}-{finding.location.to}</div>}
                    {onFix && finding.category === 'citations' && (
                      <button type="button" className="mt-2 text-[10px] underline" onClick={() => onFix('find-evidence')}>Search evidence in Paper Memory</button>
                    )}
                  </div>
                )) : <div className="rounded border p-3 text-sm text-muted-foreground">No actionable concerns were recorded.</div>}
              </div>
            </section>

            <div className="rounded-lg border p-3 text-xs text-muted-foreground">
              <div><strong>Reviewed revision:</strong> <code>{liveRun.sourceRevision}</code></div>
              <div className="mt-1"><strong>Report:</strong> {liveRun.artifacts.reportPath ?? 'No report artifact recorded.'}</div>
              <div className="mt-1"><strong>Literature records:</strong> {liveRun.artifacts.literatureCount ?? liveRun.literature.length} · <strong>Paper Memory passages:</strong> {liveRun.artifacts.paperMemoryEvidenceCount ?? 0}</div>
            </div>

            <div className="flex flex-wrap justify-end gap-2">
              <Button variant="outline" onClick={newReview}>New Review</Button>
              {liveRun.artifacts.reportPath && <Button variant="outline" disabled={reportLoading} onClick={() => void openReport()}>{reportLoading ? <LoaderCircle className="mr-1 size-4 animate-spin" /> : <FileText className="mr-1 size-4" />}Open Full Review</Button>}
              <Button onClick={() => { onOpenReview?.(); onOpenChange(false); }}>View Suggestions</Button>
            </div>
          </div>
        ) : null}
      </DialogContent>
    </Dialog>
  );
}
