import { useState, useEffect, useMemo } from "react";
import { AnimatePresence, m } from 'framer-motion';
import { MessageSquare, X, Check, Image as ImageIcon, Type, StickyNote, Download, Trash2, List } from "lucide-react";
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
import { finder } from "@medv/finder";

function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

export interface Annotation {
  id: string;
  x: number;
  y: number;
  selector: string;
  type: "text" | "image" | "note";
  originalContent: string;
  newContent: string;
  url: string;
  elementRect: Record<string, number> | null;
  scrollX: number;
  scrollY: number;
  viewportWidth: number;
  viewportHeight: number;
  userAgent: string;
  timestamp: string;
}

export interface AnnotatorProps {
  assets?: string[]; // Array of image URLs for the media browser
  onSubmit?: (annotations: Annotation[]) => Promise<void>;
}

export function Annotator({ assets = [], onSubmit }: AnnotatorProps) {
  const [isActive, setIsActive] = useState(false);
  const [hoveredElement, setHoveredElement] = useState<HTMLElement | null>(null);
  const [selectedElement, setSelectedElement] = useState<HTMLElement | null>(null);
  const [annotations, setAnnotations] = useState<Annotation[]>(() => {
    if (typeof window !== "undefined") {
      const saved = localStorage.getItem("mintel-annotations");
      if (saved) {
        try {
          return JSON.parse(saved);
        } catch (e) {
          console.error("Failed to parse saved annotations", e);
        }
      }
    }
    return [];
  });

  useEffect(() => {
    if (typeof window !== "undefined") {
      localStorage.setItem("mintel-annotations", JSON.stringify(annotations));
    }
  }, [annotations]);
  
  // Modal state
  const [currentType, setCurrentType] = useState<"text" | "image" | "note">("text");
  const [currentText, setCurrentText] = useState("");
  const [selectedAsset, setSelectedAsset] = useState<string | null>(null);
  const [showList, setShowList] = useState(false);
  const [searchTerm, setSearchTerm] = useState("");
  const [isSubmitting, setIsSubmitting] = useState(false);

  // Disable overlays if needed (e.g. inside iframes)
  const isExcluded = useMemo(() => {
    if (typeof window === "undefined") return false;
    return window.self !== window.top;
  }, []);

  const getSelector = (el: HTMLElement): string => {
    try {
      return finder(el, {
        root: document.body,
        className: (name) =>
          !name.startsWith("annotator-") &&
          !name.includes("[") &&
          !name.includes("/") &&
          !name.match(/^[a-z]-[0-9]/),
        idName: (name) => !name.startsWith("__next") && !name.includes(":"),
      });
    } catch {
      return "unknown";
    }
  };

  useEffect(() => {
    if (!isActive) {
      setHoveredElement(null);
      return;
    }

    const handleMouseMove = (e: MouseEvent) => {
      if (selectedElement) return;
      const target = e.target as HTMLElement;
      if (target.closest(".annotator-ui-ignore")) {
        setHoveredElement(null);
        return;
      }
      setHoveredElement(target);
    };

    const handleClick = (e: MouseEvent) => {
      if (selectedElement) return;
      const target = e.target as HTMLElement;
      if (target.closest(".annotator-ui-ignore")) return;

      e.preventDefault();
      e.stopPropagation();

      setSelectedElement(target);
      setHoveredElement(null);
      
      // Auto-detect type
      if (target.tagName.toLowerCase() === "img") {
        setCurrentType("image");
      } else {
        setCurrentType("text");
        setCurrentText(target.innerText || "");
      }
    };

    window.addEventListener("mousemove", handleMouseMove);
    window.addEventListener("click", handleClick, true);

    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
      window.removeEventListener("click", handleClick, true);
    };
  }, [isActive, selectedElement]);

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === "Escape") {
        if (selectedElement) {
          setSelectedElement(null);
        } else if (isActive) {
          setIsActive(false);
        }
      }
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [isActive, selectedElement]);

  const saveAnnotation = () => {
    if (!selectedElement) return;

    const rect = selectedElement.getBoundingClientRect();
    const newContent = currentType === "image" ? selectedAsset || "" : currentText;
    
    if (!newContent) return;

    const annotation: Annotation = {
      id: Math.random().toString(36).substring(2, 9),
      x: rect.left + rect.width / 2 + window.scrollX,
      y: rect.top + rect.height / 2 + window.scrollY,
      selector: getSelector(selectedElement),
      type: currentType,
      originalContent: currentType === "image" ? (selectedElement as HTMLImageElement).src || "" : selectedElement.innerText,
      newContent,
      url: window.location.href,
      elementRect: rect ? {
        x: rect.x, y: rect.y, width: rect.width, height: rect.height,
        top: rect.top, right: rect.right, bottom: rect.bottom, left: rect.left
      } : null,
      scrollX: window.scrollX,
      scrollY: window.scrollY,
      viewportWidth: window.innerWidth,
      viewportHeight: window.innerHeight,
      userAgent: navigator.userAgent,
      timestamp: new Date().toISOString(),
    };

    setAnnotations([...annotations, annotation]);
    setSelectedElement(null);
    setCurrentText("");
    setSelectedAsset(null);
  };

  const exportJSON = () => {
    const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(annotations, null, 2));
    const downloadAnchorNode = document.createElement("a");
    downloadAnchorNode.setAttribute("href", dataStr);
    downloadAnchorNode.setAttribute("download", "corrections.json");
    document.body.appendChild(downloadAnchorNode);
    downloadAnchorNode.click();
    downloadAnchorNode.remove();
  };

  const handleSubmit = async () => {
    if (!onSubmit || annotations.length === 0) return;
    setIsSubmitting(true);
    try {
      await onSubmit(annotations);
      setAnnotations([]);
      setShowList(false);
    } catch (error) {
      console.error("Submission failed", error);
      alert("Fehler beim Senden der Korrekturen. Bitte JSON Export nutzen.");
    } finally {
      setIsSubmitting(false);
    }
  };

  const deleteAnnotation = (id: string) => {
    setAnnotations(annotations.filter((a) => a.id !== id));
  };

  const [updateTick, setUpdateTick] = useState(0);

  useEffect(() => {
    if (!isActive && !selectedElement) return;
    
    let rafId: number;
    const handleScroll = () => {
      cancelAnimationFrame(rafId);
      rafId = requestAnimationFrame(() => setUpdateTick(t => t + 1));
    };
    
    // Use capture phase to catch scrolls on any nested container
    window.addEventListener("scroll", handleScroll, true);
    window.addEventListener("resize", handleScroll);
    
    return () => {
      window.removeEventListener("scroll", handleScroll, true);
      window.removeEventListener("resize", handleScroll);
      cancelAnimationFrame(rafId);
    };
  }, [isActive, selectedElement]);

  const hoveredRect = useMemo(() => hoveredElement?.getBoundingClientRect(), [hoveredElement, updateTick]);
  const selectedRect = useMemo(() => selectedElement?.getBoundingClientRect(), [selectedElement, updateTick]);

  if (isExcluded) return null;

  return (
    <div className="annotator-ui-ignore">
      {/* 1. Global Toolbar */}
      <div className="fixed bottom-36 md:bottom-24 right-4 z-[10000] flex flex-col items-end gap-2">
        <div className="bg-black/80 backdrop-blur-xl border border-white/10 p-1.5 rounded-2xl shadow-2xl flex flex-col items-center gap-1">
          <button
            onClick={() => setIsActive(!isActive)}
            className={cn(
              "p-2.5 rounded-xl transition-all",
              isActive
                ? "bg-blue-500 text-white shadow-lg shadow-blue-500/20"
                : "text-white/70 hover:text-white hover:bg-white/10"
            )}
            title={isActive ? "Modus beenden" : "Korrekturen erfassen"}
          >
            {isActive ? <X size={20} /> : <MessageSquare size={20} />}
          </button>

          <div className="w-6 h-px bg-white/10 my-1" />

          <button
            onClick={() => setShowList(!showList)}
            className="p-2.5 text-white/70 hover:text-white hover:bg-white/10 rounded-xl relative"
            title="Liste anzeigen"
          >
            <List size={20} />
            {annotations.length > 0 && (
              <span className="absolute -top-1 -right-1 w-4 h-4 bg-blue-500 text-[9px] flex items-center justify-center rounded-full text-white font-bold border border-[#1a1a1a]">
                {annotations.length}
              </span>
            )}
          </button>

          {annotations.length > 0 && (
            <>
              <div className="w-6 h-px bg-white/10 my-1" />
              <button
                onClick={exportJSON}
                className="p-2.5 rounded-xl text-white/70 hover:text-white hover:bg-white/10 transition-all"
                title="JSON Export"
              >
                <Download size={20} />
              </button>
            </>
          )}
        </div>
      </div>

      {/* 2. Highlights */}
      <AnimatePresence>
        {isActive && (
          <div className="fixed inset-0 pointer-events-none z-[9998]">
            {hoveredRect && (
              <m.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                exit={{ opacity: 0 }}
                className="absolute border-2 border-blue-400 bg-blue-400/10 rounded-sm transition-all duration-200"
                style={{
                  top: hoveredRect.top,
                  left: hoveredRect.left,
                  width: hoveredRect.width,
                  height: hoveredRect.height,
                }}
              />
            )}

            {selectedRect && (
              <m.div
                initial={{ scale: 0.9, opacity: 0 }}
                animate={{ scale: 1, opacity: 1 }}
                className="absolute border-2 border-yellow-400 bg-yellow-400/20 rounded-sm"
                style={{
                  top: selectedRect.top,
                  left: selectedRect.left,
                  width: selectedRect.width,
                  height: selectedRect.height,
                }}
              />
            )}
          </div>
        )}
      </AnimatePresence>

      {/* 3. Action Modal */}
      <AnimatePresence>
        {selectedElement && (
          <div className="fixed inset-0 flex items-center justify-center z-[10000] bg-black/40 backdrop-blur-sm">
            <m.div
              initial={{ opacity: 0, y: 20, scale: 0.95 }}
              animate={{ opacity: 1, y: 0, scale: 1 }}
              exit={{ opacity: 0, y: 20, scale: 0.95 }}
              className="bg-[#1c1c1e] border border-white/10 rounded-3xl p-4 sm:p-6 w-[95vw] md:w-[800px] shadow-2xl flex flex-col max-h-[85vh]"
            >
              <div className="flex items-center justify-between mb-6">
                <h3 className="text-white font-bold text-lg">Änderung erfassen</h3>
                <button
                  onClick={() => setSelectedElement(null)}
                  className="text-white/40 hover:text-white"
                >
                  <X size={20} />
                </button>
              </div>

              <div className="flex gap-2 mb-6 shrink-0">
                <button
                  onClick={() => setCurrentType("text")}
                  className={cn(
                    "flex-1 py-3 px-4 rounded-xl text-sm font-medium transition-all flex items-center justify-center gap-2",
                    currentType === "text"
                      ? "bg-white text-black shadow-lg"
                      : "bg-white/5 text-white/40 hover:bg-white/10"
                  )}
                >
                  <Type size={16} /> Text
                </button>
                <button
                  onClick={() => setCurrentType("image")}
                  className={cn(
                    "flex-1 py-3 px-4 rounded-xl text-sm font-medium transition-all flex items-center justify-center gap-2",
                    currentType === "image"
                      ? "bg-white text-black shadow-lg"
                      : "bg-white/5 text-white/40 hover:bg-white/10"
                  )}
                >
                  <ImageIcon size={16} /> Bild
                </button>
                <button
                  onClick={() => setCurrentType("note")}
                  className={cn(
                    "flex-1 py-3 px-4 rounded-xl text-sm font-medium transition-all flex items-center justify-center gap-2",
                    currentType === "note"
                      ? "bg-white text-black shadow-lg"
                      : "bg-white/5 text-white/40 hover:bg-white/10"
                  )}
                >
                  <StickyNote size={16} /> Notiz
                </button>
              </div>

              <div className="flex-1 overflow-y-auto min-h-[200px] mb-6 hide-scrollbar" style={{ scrollbarWidth: 'none', msOverflowStyle: 'none' }}>
                {currentType === "text" && (
                  <div className="space-y-2">
                    <label className="text-xs font-bold uppercase tracking-wider text-white/40">Neuer Text</label>
                    <textarea
                      autoFocus
                      value={currentText}
                      onChange={(e) => setCurrentText(e.target.value)}
                      className="w-full h-32 bg-black/40 border border-white/10 rounded-2xl p-4 text-white placeholder:text-white/20 focus:outline-none focus:border-blue-500/50 transition-colors resize-none"
                    />
                  </div>
                )}

                {currentType === "note" && (
                  <div className="space-y-2">
                    <label className="text-xs font-bold uppercase tracking-wider text-white/40">Anmerkung</label>
                    <textarea
                      autoFocus
                      value={currentText}
                      onChange={(e) => setCurrentText(e.target.value)}
                      placeholder="Was soll hier gemacht werden?"
                      className="w-full h-32 bg-black/40 border border-white/10 rounded-2xl p-4 text-white placeholder:text-white/20 focus:outline-none focus:border-blue-500/50 transition-colors resize-none"
                    />
                  </div>
                )}

                {currentType === "image" && (
                  <div className="space-y-2 h-full">
                    <label className="text-xs font-bold uppercase tracking-wider text-white/40">Neues Bild wählen</label>
                    {assets.length === 0 ? (
                      <div className="text-sm text-white/40 p-4 bg-white/5 rounded-xl border border-white/5 text-center">
                        Keine Assets übergeben. Bitte das prop <code>assets</code> befüllen.
                      </div>
                    ) : (
                      <>
                        <style>{`.hide-scrollbar::-webkit-scrollbar { display: none; }`}</style>
                        <div className="mb-3">
                          <input
                            type="text"
                            placeholder="Suchen nach Dateinamen..."
                            value={searchTerm}
                            onChange={(e) => setSearchTerm(e.target.value)}
                            className="w-full bg-black/40 border border-white/10 rounded-xl px-4 py-3 text-sm text-white placeholder:text-white/40 focus:outline-none focus:border-blue-500/50 transition-colors"
                          />
                        </div>
                        <div 
                          className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-3 h-[400px] overflow-y-auto hide-scrollbar"
                          style={{ scrollbarWidth: 'none', msOverflowStyle: 'none' }}
                        >
                        {assets.filter(asset => asset.toLowerCase().includes(searchTerm.toLowerCase())).map((asset) => {
                          const filename = asset.split('/').pop() || asset;
                          return (
                            <button
                              key={asset}
                              title={asset}
                              onClick={() => setSelectedAsset(asset)}
                              className={cn(
                                "relative flex flex-col items-center bg-black/20 rounded-xl overflow-hidden border-2 transition-all p-2 gap-2 w-full",
                                selectedAsset === asset
                                  ? "border-blue-500 shadow-[0_0_0_4px_rgba(59,130,246,0.3)] bg-blue-500/10"
                                  : "border-transparent hover:border-white/20 hover:bg-white/5"
                              )}
                              style={{ height: '130px' }}
                            >
                              <div className="w-full flex-1 rounded-lg overflow-hidden bg-black/40 flex items-center justify-center relative">
                                {asset.match(/\.(mp4|webm)$/i) ? (
                                  <video src={asset} className="w-full h-full object-cover opacity-80" />
                                ) : (
                                  <img src={asset} loading="lazy" alt={filename} className="w-full h-full object-contain" />
                                )}
                                {selectedAsset === asset && (
                                  <div className="absolute inset-0 flex items-center justify-center bg-blue-500/20 backdrop-blur-[2px]">
                                    <div className="bg-blue-500 text-white rounded-full p-1.5 shadow-lg">
                                      <Check size={18} strokeWidth={3} />
                                    </div>
                                  </div>
                                )}
                              </div>
                              <span className="text-[11px] font-medium text-white/70 truncate w-full text-center shrink-0" title={filename}>
                                {filename}
                              </span>
                            </button>
                          );
                        })}
                      </div>
                      </>
                    )}
                  </div>
                )}
              </div>

              <button
                disabled={(!currentText && currentType !== "image") || (currentType === "image" && !selectedAsset)}
                onClick={saveAnnotation}
                className="w-full bg-blue-500 hover:bg-blue-400 disabled:opacity-50 disabled:cursor-not-allowed text-white font-bold py-4 rounded-2xl flex items-center justify-center gap-2 transition-all shadow-lg shadow-blue-500/20 shrink-0"
              >
                <Check size={20} />
                Speichern
              </button>
            </m.div>
          </div>
        )}
      </AnimatePresence>

      {/* 4. Annotations List Sidebar */}
      <AnimatePresence>
        {showList && (
          <>
            <m.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              onClick={() => setShowList(false)}
              className="fixed inset-0 bg-black/60 backdrop-blur-sm z-[10001]"
            />
            <m.div
              initial={{ x: "100%" }}
              animate={{ x: 0 }}
              exit={{ x: "100%" }}
              transition={{ type: "spring", damping: 25, stiffness: 200 }}
              className="fixed top-0 right-0 h-full w-full sm:w-[400px] bg-[#1c1c1e] border-l border-white/10 z-[10002] shadow-2xl flex flex-col"
            >
              <div className="p-8 border-b border-white/10 flex items-center justify-between">
                <div>
                  <h2 className="text-2xl font-bold text-white mb-1">Korrekturen</h2>
                  <p className="text-white/40 text-sm">{annotations.length} erfasst</p>
                </div>
                <button
                  onClick={() => setShowList(false)}
                  className="p-2 text-white/40 hover:text-white bg-white/5 rounded-xl transition-colors"
                >
                  <X size={20} />
                </button>
              </div>

              <div className="flex-1 overflow-y-auto p-6 space-y-4">
                {annotations.length === 0 ? (
                  <div className="h-full flex flex-col items-center justify-center text-center px-8 opacity-40">
                    <List size={48} className="mb-4" />
                    <p>Noch keine Korrekturen vorhanden.</p>
                  </div>
                ) : (
                  annotations.map((ann) => (
                    <div
                      key={ann.id}
                      className="bg-white/5 border border-white/5 rounded-2xl p-4 flex flex-col gap-3 group relative"
                    >
                      <button 
                        onClick={() => deleteAnnotation(ann.id)}
                        className="absolute top-4 right-4 text-white/20 hover:text-red-400 opacity-0 group-hover:opacity-100 transition-opacity"
                      >
                        <Trash2 size={16} />
                      </button>
                      
                      <div className="flex items-center gap-2">
                        <span className={cn(
                          "px-2 py-1 rounded-md text-[10px] font-bold uppercase tracking-wider flex items-center gap-1",
                          ann.type === "text" ? "bg-blue-500/20 text-blue-400" :
                          ann.type === "image" ? "bg-purple-500/20 text-purple-400" :
                          "bg-orange-500/20 text-orange-400"
                        )}>
                          {ann.type === "text" && <Type size={12} />}
                          {ann.type === "image" && <ImageIcon size={12} />}
                          {ann.type === "note" && <StickyNote size={12} />}
                          {ann.type}
                        </span>
                      </div>
                      
                      {ann.type === "image" ? (
                        <div className="flex items-center gap-2">
                          <img src={ann.newContent} alt="New" className="w-16 h-16 object-cover rounded-lg bg-white/10" />
                          <div className="text-xs text-white/60 flex-1 truncate">{ann.newContent}</div>
                        </div>
                      ) : (
                        <p className="text-white text-sm whitespace-pre-wrap">{ann.newContent}</p>
                      )}
                      
                      <div className="text-[10px] text-white/30 truncate mt-2 font-mono flex items-center gap-2">
                        <span>{ann.selector}</span>
                        {ann.url && <span className="truncate max-w-[100px] text-blue-400" title={ann.url}>{new URL(ann.url).pathname}</span>}
                      </div>
                      <div className="flex flex-wrap items-center gap-2 mt-2 pt-2 border-t border-white/5">
                        {ann.timestamp && (
                          <span className="text-[9px] px-1.5 py-0.5 rounded bg-white/5 text-white/40">
                            {new Date(ann.timestamp).toLocaleString()}
                          </span>
                        )}
                        {ann.viewportWidth && (
                          <span className="text-[9px] px-1.5 py-0.5 rounded bg-white/5 text-white/40">
                            {ann.viewportWidth}x{ann.viewportHeight}
                          </span>
                        )}
                        {ann.scrollX !== undefined && (
                          <span className="text-[9px] px-1.5 py-0.5 rounded bg-white/5 text-white/40">
                            Scroll: {Math.round(ann.scrollX)},{Math.round(ann.scrollY)}
                          </span>
                        )}
                      </div>
                    </div>
                  ))
                )}
              </div>
              
              {annotations.length > 0 && (
                <div className="p-6 border-t border-white/10 flex flex-col gap-3">
                  {onSubmit && (
                    <button
                      onClick={handleSubmit}
                      disabled={isSubmitting}
                      className="w-full bg-blue-500 hover:bg-blue-400 text-white font-bold py-4 rounded-2xl flex items-center justify-center gap-2 transition-all shadow-lg shadow-blue-500/20 disabled:opacity-50 disabled:cursor-not-allowed"
                    >
                      {isSubmitting ? (
                        <div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
                      ) : (
                        <Check size={20} />
                      )}
                      {isSubmitting ? "Wird gesendet..." : "Korrekturen an Entwickler senden"}
                    </button>
                  )}
                  <button
                    onClick={exportJSON}
                    className={cn(
                      "w-full font-bold py-3 rounded-2xl flex items-center justify-center gap-2 transition-all",
                      onSubmit ? "bg-white/5 text-white/70 hover:bg-white/10 hover:text-white" : "bg-blue-500 hover:bg-blue-400 text-white shadow-lg shadow-blue-500/20 py-4"
                    )}
                  >
                    <Download size={onSubmit ? 18 : 20} />
                    JSON {onSubmit && "lokal "}Exportieren
                  </button>
                  <button
                    onClick={() => {
                      if (confirm("Möchtest du wirklich alle erfassten Korrekturen löschen?")) {
                        setAnnotations([]);
                      }
                    }}
                    className="w-full bg-red-500/10 text-red-500 hover:bg-red-500/20 font-bold py-3 rounded-xl flex items-center justify-center gap-2 transition-all mt-2"
                  >
                    <Trash2 size={18} />
                    Alle löschen
                  </button>
                </div>
              )}
            </m.div>
          </>
        )}
      </AnimatePresence>
    </div>
  );
}
