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

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<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(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 */
    <div
      className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 p-4 backdrop-blur-sm"
      onClick={(e) => e.target === e.currentTarget && onClose()}
    >
      {/* panel */}
      <div className="flex max-h-[90vh] w-full max-w-4xl flex-col rounded-xl border border-gray-700 bg-gray-900 shadow-2xl">
        {/* header */}
        <div className="flex items-center justify-between border-b border-gray-800 px-5 py-3">
          <span className="truncate text-sm font-medium text-gray-200">
            {fileName}
          </span>
          <div className="flex items-center gap-2">
            <button
              onClick={onDownload}
              title="Download"
              className="flex items-center gap-1.5 rounded-lg border border-gray-700 bg-gray-800 px-3 py-1.5 text-sm text-gray-300 hover:border-cyan-500/50 hover:text-cyan-400 transition-colors"
            >
              <Download className="h-4 w-4" />
              Download
            </button>
            <button
              onClick={onClose}
              className="rounded-lg p-1.5 text-gray-400 hover:bg-gray-800 hover:text-white transition-colors"
              title="Close (Esc)"
            >
              <X className="h-5 w-5" />
            </button>
          </div>
        </div>

        {/* body */}
        <div className="flex-1 overflow-auto p-4">
          {/* ── IMAGE ─────────────────────────────────────── */}
          {previewType === "image" && (
            <div className="flex items-center justify-center">
              <img
                src={downloadUrl}
                alt={fileName}
                className="max-h-[75vh] max-w-full rounded-lg object-contain"
                onError={(e) => {
                  (e.currentTarget as HTMLImageElement).style.display = "none";
                  setError("Image could not be loaded");
                }}
              />
              {error && <ErrorMessage message={error} />}
            </div>
          )}

          {/* ── TEXT / JSON ────────────────────────────────── */}
          {(previewType === "text" || previewType === "json") && (
            <>
              {loading && (
                <div className="flex items-center justify-center py-16">
                  <Loader2 className="h-8 w-8 animate-spin text-cyan-400" />
                </div>
              )}
              {error && !loading && <ErrorMessage message={error} />}
              {text !== null && !loading && (
                <pre
                  className={`whitespace-pre-wrap break-words rounded-lg bg-gray-950 p-4 font-mono text-sm text-gray-300 ${
                    previewType === "json" ? "text-emerald-300" : ""
                  }`}
                >
                  {text}
                </pre>
              )}
            </>
          )}
        </div>
      </div>
    </div>
  );
}

function ErrorMessage({ message }: { message: string }) {
  return (
    <div className="flex flex-col items-center gap-2 py-12 text-center">
      <AlertCircle className="h-10 w-10 text-red-400" />
      <p className="text-sm text-red-400">{message}</p>
    </div>
  );
}
