/** * EvidencePreviewModal * * Shows evidence files inline: * - Images → rendered directly (same-origin cookie sent automatically) * - JSON → fetched via authenticated Axios, pretty-printed * - Text → fetched via authenticated Axios, shown in
 */

import { useEffect, useState, useCallback } from "react";
import { X, Loader2, AlertCircle, Download } from "lucide-react";
import { getEvidenceRawContent } from "../api/evidence";

// ── Helpers ────────────────────────────────────────────────────────

export type PreviewType = "image" | "json" | "text" | null;

const IMAGE_EXTS = new Set([
  "png", "jpg", "jpeg", "gif", "webp", "svg", "bmp", "ico", "tiff", "tif",
]);
const TEXT_EXTS = new Set([
  "txt", "log", "md", "csv", "xml", "html", "htm", "yaml", "yml",
  "ini", "cfg", "conf", "sh", "bat", "ps1", "py", "js", "ts",
]);

export function getPreviewType(fileName: string): PreviewType {
  const ext = fileName.split(".").pop()?.toLowerCase() ?? "";
  if (IMAGE_EXTS.has(ext)) return "image";
  if (ext === "json") return "json";
  if (TEXT_EXTS.has(ext)) return "text";
  return null;
}

// ── Component ──────────────────────────────────────────────────────

interface Props {
  evidenceId: string;
  fileName: string;
  previewType: PreviewType;
  downloadUrl: string;
  onClose: () => void;
  onDownload: () => void;
}

export default function EvidencePreviewModal({
  evidenceId,
  fileName,
  previewType,
  downloadUrl,
  onClose,
  onDownload,
}: Props) {
  const [text, setText] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  // Fetch text / JSON content on mount (not needed for images)
  useEffect(() => {
    if (previewType === "text" || previewType === "json") {
      setLoading(true);
      getEvidenceRawContent(evidenceId)
        .then(({ text: raw }) => {
          if (previewType === "json") {
            try {
              setText(JSON.stringify(JSON.parse(raw), null, 2));
            } catch {
              setText(raw); // not valid JSON — show raw
            }
          } else {
            setText(raw);
          }
        })
        .catch((e) => setError(e?.message ?? "Failed to load file"))
        .finally(() => setLoading(false));
    }
  }, [evidenceId, previewType]);

  // Close on Escape
  const handleKey = useCallback(
    (e: KeyboardEvent) => {
      if (e.key === "Escape") onClose();
    },
    [onClose],
  );
  useEffect(() => {
    document.addEventListener("keydown", handleKey);
    return () => document.removeEventListener("keydown", handleKey);
  }, [handleKey]);

  return (
    /* backdrop */
    
e.target === e.currentTarget && onClose()} > {/* panel */}
{/* header */}
{fileName}
{/* body */}
{/* ── IMAGE ─────────────────────────────────────── */} {previewType === "image" && (
{fileName} { (e.currentTarget as HTMLImageElement).style.display = "none"; setError("Image could not be loaded"); }} /> {error && }
)} {/* ── TEXT / JSON ────────────────────────────────── */} {(previewType === "text" || previewType === "json") && ( <> {loading && (
)} {error && !loading && } {text !== null && !loading && (
                  {text}
                
)} )}
); } function ErrorMessage({ message }: { message: string }) { return (

{message}

); }