'use client';

import { useState, useEffect, useCallback } from 'react';
import { motion } from 'framer-motion';
import {
  CheckCircle2,
  XCircle,
  Clock,
  Shield,
  FileCode2,
  Download,
  ChevronDown,
  ChevronRight,
  AlertTriangle,
  Loader2,
  Lock,
  Eye,
  BrainCircuit,
  X,
} from 'lucide-react';
import { api } from '../lib/api';
import { useSession } from '../lib/session-context';

interface ReviewFile {
  outputPath: string;
  sourcePath: string | null;
  sourceContent: string | null;
  outputContent: string;
  status: 'pending' | 'approved' | 'needs-rework';
  notes: string | null;
  reviewer: string | null;
  reviewedAt: string | null;
  annotations: Array<{ line: number | null; ruleId: string; severity: string; snippet: string }>;
}

interface ReviewState {
  runId: string;
  sealed: unknown;
  summary: { total: number; approved: number; needsRework: number; pending: number };
  property: unknown | null;
  files: ReviewFile[];
}

interface Props {
  runId: string;
  projectName?: string;
  onBack?: () => void;
}

export default function ReviewBoard({ runId, projectName, onBack }: Props) {
  const { user } = useSession();
  const [reviewState, setReviewState] = useState<ReviewState | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [expandedFile, setExpandedFile] = useState<string | null>(null);
  const [fileActioning, setFileActioning] = useState<Record<string, boolean>>({});
  const [sealing, setSealing] = useState(false);
  const [csvDownloading, setCsvDownloading] = useState(false);
  const [promptModal, setPromptModal] = useState<{ path: string; content: string } | null>(null);
  const [promptLoading, setPromptLoading] = useState<string | null>(null);

  const loadReview = useCallback(async () => {
    try {
      const data = await api.engine.getReview(runId);
      setReviewState(data as ReviewState);
      setError(null);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load review');
    } finally {
      setLoading(false);
    }
  }, [runId]);

  useEffect(() => {
    void loadReview();
  }, [loadReview]);

  const handleFileAction = async (
    outputPath: string,
    status: 'approved' | 'needs-rework',
  ) => {
    setFileActioning((prev) => ({ ...prev, [outputPath]: true }));
    try {
      await api.engine.setFileReview(runId, outputPath, {
        status,
        reviewer: user?.email ?? 'user',
      });
      await loadReview();
    } catch {
      // non-fatal: state refresh will reflect server truth
    } finally {
      setFileActioning((prev) => ({ ...prev, [outputPath]: false }));
    }
  };

  const handleSeal = async () => {
    setSealing(true);
    try {
      await api.engine.sealReview(runId, user?.email ?? 'user');
      await loadReview();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to seal bundle');
    } finally {
      setSealing(false);
    }
  };

  const handleViewPrompt = async (filePath: string) => {
    setPromptLoading(filePath);
    try {
      const content = await api.engine.getReviewFileContext(runId, filePath);
      setPromptModal({ path: filePath, content });
    } catch {
      // non-fatal
    } finally {
      setPromptLoading(null);
    }
  };

  const handleExportCsv = async () => {
    setCsvDownloading(true);
    try {
      const csv = await api.engine.getReviewAuditCsv(runId);
      const blob = new Blob([csv], { type: 'text/csv' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `review-audit-${runId}.csv`;
      a.click();
      URL.revokeObjectURL(url);
    } catch {
      // non-fatal
    } finally {
      setCsvDownloading(false);
    }
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center py-16">
        <Loader2 className="w-6 h-6 animate-spin text-accent-light" />
        <span className="ml-3 text-sm text-muted">Loading review state…</span>
      </div>
    );
  }

  if (error) {
    return (
      <div className="glass rounded-xl p-6 border border-red-500/30">
        <div className="flex items-center gap-3 text-danger">
          <AlertTriangle className="w-5 h-5 shrink-0" />
          <p className="text-sm">{error}</p>
        </div>
        {onBack && (
          <button
            onClick={onBack}
            className="mt-4 text-xs text-muted hover:text-foreground underline cursor-pointer"
          >
            Back
          </button>
        )}
      </div>
    );
  }

  if (!reviewState) return null;

  const { summary, files, sealed } = reviewState;
  const isSealed = sealed != null;
  const canSeal = !isSealed && summary.pending === 0 && summary.needsRework === 0;
  const sealDisabledReason =
    isSealed
      ? 'Already sealed'
      : summary.pending > 0 || summary.needsRework > 0
        ? 'All files must be approved before sealing'
        : null;
  const manifestPreview =
    isSealed && sealed != null
      ? JSON.stringify(sealed, null, 2).slice(0, 500)
      : null;

  return (
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      className="glass rounded-xl p-6 space-y-6 mt-6"
    >
      {/* Header */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <Eye className="w-5 h-5 text-accent-light shrink-0" />
          <div>
            <h3 className="text-sm font-semibold text-foreground">
              Review Board{projectName ? ` — ${projectName}` : ''}
            </h3>
            <p className="text-[10px] text-muted font-mono">{runId}</p>
          </div>
          {isSealed && (
            <span className="flex items-center gap-1 text-[10px] font-semibold px-2 py-0.5 rounded-full bg-success/15 text-success border border-success/30">
              <Lock className="w-3 h-3" /> SEALED
            </span>
          )}
        </div>
        <div className="flex items-center gap-2">
          <button
            onClick={handleExportCsv}
            disabled={csvDownloading}
            className="flex items-center gap-1.5 text-[10px] px-3 py-1.5 rounded-md border border-border hover:bg-surface-light transition-colors cursor-pointer disabled:opacity-50"
          >
            {csvDownloading ? <Loader2 className="w-3 h-3 animate-spin" /> : <Download className="w-3 h-3" />}
            Export CSV
          </button>
          {onBack && (
            <button
              onClick={onBack}
              className="text-[10px] px-3 py-1.5 rounded-md border border-border hover:bg-surface-light transition-colors cursor-pointer"
            >
              Back
            </button>
          )}
        </div>
      </div>

      {/* Summary pills */}
      <div className="flex flex-wrap gap-2">
        <span className="flex items-center gap-1.5 text-[11px] px-2.5 py-1 rounded-full bg-surface border border-border text-foreground">
          <Shield className="w-3.5 h-3.5 text-muted" />
          {summary.total} total
        </span>
        <span className="flex items-center gap-1.5 text-[11px] px-2.5 py-1 rounded-full bg-success/10 border border-success/30 text-success">
          <CheckCircle2 className="w-3.5 h-3.5" />
          {summary.approved} approved
        </span>
        <span className={`flex items-center gap-1.5 text-[11px] px-2.5 py-1 rounded-full border ${
          summary.needsRework > 0
            ? 'bg-orange-500/10 border-orange-400/30 text-orange-400'
            : 'bg-surface border-border text-muted'
        }`}>
          <XCircle className="w-3.5 h-3.5" />
          {summary.needsRework} needs rework
        </span>
        <span className={`flex items-center gap-1.5 text-[11px] px-2.5 py-1 rounded-full border ${
          summary.pending > 0
            ? 'bg-amber-500/10 border-amber-400/30 text-amber-400'
            : 'bg-surface border-border text-muted'
        }`}>
          <Clock className="w-3.5 h-3.5" />
          {summary.pending} pending
        </span>
      </div>

      {/* File list */}
      <div className="space-y-1">
        {files.map((file) => {
          const isExpanded = expandedFile === file.outputPath;
          const isActioning = fileActioning[file.outputPath] ?? false;
          const leaf = file.outputPath.split('/').pop() ?? file.outputPath;

          return (
            <div
              key={file.outputPath}
              className="glass-light rounded-lg border border-border overflow-hidden"
            >
              <div
                className="flex items-center gap-3 px-4 py-3 cursor-pointer hover:bg-surface-light/40 transition-colors"
                onClick={() => setExpandedFile(isExpanded ? null : file.outputPath)}
              >
                <FileCode2 className="w-4 h-4 text-muted shrink-0" />
                <span className="text-xs font-mono text-foreground truncate flex-1" title={file.outputPath}>
                  {leaf}
                </span>
                {file.annotations.length > 0 && (
                  <span className="flex items-center gap-1 text-[10px] text-amber-400">
                    <AlertTriangle className="w-3 h-3" />
                    {file.annotations.length}
                  </span>
                )}
                <span className={`text-[10px] font-semibold px-2 py-0.5 rounded-full border ${
                  file.status === 'approved'
                    ? 'bg-success/10 border-success/30 text-success'
                    : file.status === 'needs-rework'
                      ? 'bg-orange-500/10 border-orange-400/30 text-orange-400'
                      : 'bg-surface border-border text-muted'
                }`}>
                  {file.status === 'approved' ? 'Approved' : file.status === 'needs-rework' ? 'Needs Rework' : 'Pending'}
                </span>
                {!isSealed && (
                  <div className="flex gap-1.5 shrink-0" onClick={(e) => e.stopPropagation()}>
                    <button
                      disabled={file.status === 'approved' || isActioning}
                      onClick={() => handleFileAction(file.outputPath, 'approved')}
                      className="text-[10px] px-2.5 py-1 rounded border border-success/40 text-success hover:bg-success/10 disabled:opacity-40 disabled:cursor-not-allowed transition-colors cursor-pointer flex items-center gap-1"
                    >
                      {isActioning && file.status !== 'approved' ? <Loader2 className="w-2.5 h-2.5 animate-spin" /> : <CheckCircle2 className="w-2.5 h-2.5" />}
                      Approve
                    </button>
                    <button
                      disabled={file.status === 'needs-rework' || isActioning}
                      onClick={() => handleFileAction(file.outputPath, 'needs-rework')}
                      className="text-[10px] px-2.5 py-1 rounded border border-orange-400/40 text-orange-400 hover:bg-orange-500/10 disabled:opacity-40 disabled:cursor-not-allowed transition-colors cursor-pointer flex items-center gap-1"
                    >
                      {isActioning && file.status !== 'needs-rework' ? <Loader2 className="w-2.5 h-2.5 animate-spin" /> : <XCircle className="w-2.5 h-2.5" />}
                      Needs Rework
                    </button>
                  </div>
                )}
                {isExpanded ? <ChevronDown className="w-3.5 h-3.5 text-muted shrink-0" /> : <ChevronRight className="w-3.5 h-3.5 text-muted shrink-0" />}
              </div>

              {isExpanded && (
                <div className="border-t border-border px-4 py-3 space-y-3">
                  {/* Diff view */}
                  <div className={`grid gap-3 ${file.sourceContent ? 'grid-cols-2' : 'grid-cols-1'}`}>
                    {file.sourceContent && (
                      <div>
                        <p className="text-[9px] text-muted uppercase tracking-wider mb-1.5">Source</p>
                        <pre className="text-[10px] font-mono text-muted bg-surface rounded-md p-3 overflow-auto max-h-64 whitespace-pre-wrap break-all leading-relaxed">
                          {file.sourceContent}
                        </pre>
                      </div>
                    )}
                    <div>
                      <p className="text-[9px] text-muted uppercase tracking-wider mb-1.5">Output</p>
                      <pre className="text-[10px] font-mono text-foreground bg-surface rounded-md p-3 overflow-auto max-h-64 whitespace-pre-wrap break-all leading-relaxed">
                        {file.outputContent || '(empty)'}
                      </pre>
                    </div>
                  </div>

                  {/* Annotations */}
                  {file.annotations.length > 0 && (
                    <div>
                      <p className="text-[9px] text-amber-400 uppercase tracking-wider mb-2 flex items-center gap-1">
                        <AlertTriangle className="w-3 h-3" /> Annotations
                      </p>
                      <ul className="space-y-1.5">
                        {file.annotations.map((ann, i) => (
                          <li key={i} className="text-[10px] bg-surface rounded p-2 flex items-start gap-2">
                            <span className={`font-semibold shrink-0 ${
                              ann.severity === 'error' ? 'text-danger' : ann.severity === 'warning' ? 'text-amber-400' : 'text-muted'
                            }`}>
                              [{ann.severity}]
                            </span>
                            <span className="text-muted font-mono shrink-0">{ann.ruleId}{ann.line != null ? `:${ann.line}` : ''}</span>
                            <span className="text-foreground/80 break-all">{ann.snippet}</span>
                          </li>
                        ))}
                      </ul>
                    </div>
                  )}

                  {/* Notes */}
                  {file.notes && (
                    <p className="text-[10px] text-muted italic">Note: {file.notes}</p>
                  )}

                  {/* LLM prompt viewer */}
                  <button
                    onClick={() => handleViewPrompt(file.outputPath)}
                    disabled={promptLoading === file.outputPath}
                    className="flex items-center gap-1.5 text-[10px] px-2.5 py-1 rounded border border-border text-muted hover:text-foreground hover:border-accent/40 disabled:opacity-50 transition-colors cursor-pointer w-fit"
                  >
                    {promptLoading === file.outputPath
                      ? <Loader2 className="w-3 h-3 animate-spin" />
                      : <BrainCircuit className="w-3 h-3" />}
                    View LLM Prompt
                  </button>
                </div>
              )}
            </div>
          );
        })}
      </div>

      {/* Seal button */}
      <div className="flex items-center gap-3 pt-2 border-t border-border/40">
        <button
          onClick={handleSeal}
          disabled={!canSeal || sealing}
          title={sealDisabledReason ?? undefined}
          className="flex items-center gap-2 px-4 py-2 rounded-lg bg-accent/10 border border-accent/40 text-accent-light text-xs font-semibold hover:bg-accent/20 disabled:opacity-40 disabled:cursor-not-allowed transition-colors cursor-pointer"
        >
          {sealing ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Lock className="w-3.5 h-3.5" />}
          {isSealed ? 'Bundle Sealed' : 'Seal Bundle'}
        </button>
        {sealDisabledReason && !isSealed && (
          <span className="text-[10px] text-muted">{sealDisabledReason}</span>
        )}
      </div>

      {/* Manifest preview (only when sealed) */}
      {isSealed && manifestPreview && (
        <div className="pt-2 space-y-2">
          <p className="text-[10px] text-muted uppercase tracking-wider flex items-center gap-1.5 font-semibold">
            <Shield className="w-3.5 h-3.5 text-success" /> Sealed Manifest
          </p>
          <pre className="text-[10px] font-mono text-muted bg-surface rounded-md p-3 overflow-auto max-h-48 whitespace-pre-wrap break-all leading-relaxed">
            {manifestPreview}
            {JSON.stringify(sealed, null, 2).length > 500 ? '\n…' : ''}
          </pre>
        </div>
      )}

      {/* LLM prompt modal */}
      {promptModal && (
        <div
          className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4"
          onClick={() => setPromptModal(null)}
        >
          <motion.div
            initial={{ opacity: 0, scale: 0.96 }}
            animate={{ opacity: 1, scale: 1 }}
            className="glass rounded-xl border border-border w-full max-w-2xl max-h-[80vh] flex flex-col"
            onClick={(e) => e.stopPropagation()}
          >
            <div className="flex items-center justify-between px-4 py-3 border-b border-border shrink-0">
              <div className="flex items-center gap-2">
                <BrainCircuit className="w-4 h-4 text-accent-light shrink-0" />
                <span className="text-xs font-semibold text-foreground truncate">
                  LLM Prompt — {promptModal.path.split('/').pop()}
                </span>
              </div>
              <button
                onClick={() => setPromptModal(null)}
                className="text-muted hover:text-foreground transition-colors cursor-pointer"
              >
                <X className="w-4 h-4" />
              </button>
            </div>
            <pre className="text-[10px] font-mono text-muted p-4 overflow-auto whitespace-pre-wrap break-all leading-relaxed flex-1">
              {promptModal.content || '(no prompt context available)'}
            </pre>
          </motion.div>
        </div>
      )}
    </motion.div>
  );
}
