import { useEffect, useRef, useState } from "react";
import OpenSeadragon from "openseadragon";
import { ToolsSidebar } from "./ToolsSidebar";
import { TopToolbar } from "./TopToolbar";
import { AnnotationCanvas, type Annotation } from "./AnnotationCanvas";
import { ArrowLeft } from "lucide-react";
import { useNavigate } from "react-router-dom";
import "./viewer.css";

interface PathoraViewerProps {
  imageUrl?: string;
  slideName?: string;
}

export type Tool = "none" | "select" | "rectangle" | "polygon" | "ellipse" | "brush";
type UploadedSlide = {
  id: string;
  name: string;
  uploadedAt: string;
  levelCount: number;
  levelDimensions: number[][];
};

export function PathoraViewer({ 
  imageUrl = "", 
  slideName = "Pathora Viewer" 
}: PathoraViewerProps) {
  console.log("PathoraViewer component rendering with:", { imageUrl, slideName });
  
  const viewerRef = useRef<HTMLDivElement>(null);
  const osdViewerRef = useRef<OpenSeadragon.Viewer | null>(null);
  const navigate = useNavigate();
  const [selectedTool, setSelectedTool] = useState<Tool>("none");
  const [zoomLevel, setZoomLevel] = useState<number>(1);
  const [showAnnotations, setShowAnnotations] = useState(true);
  const [showHeatmap, setShowHeatmap] = useState(false);
  const [annotations, setAnnotations] = useState<Annotation[]>([]);
  const [selectedAnnotationId, setSelectedAnnotationId] = useState<string | null>(null);
  const [activeLabel, setActiveLabel] = useState("Tumor");
  const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);
  const [uploadedSlides, setUploadedSlides] = useState<UploadedSlide[]>([]);
  const [showOriginal, setShowOriginal] = useState(true);
  const [showHematoxylin, setShowHematoxylin] = useState(false);
  const [showEosin, setShowEosin] = useState(false);
  const [isLoading, setIsLoading] = useState(true);
  const [loadError, setLoadError] = useState<string | null>(null);
  const [tileServerUrl, setTileServerUrl] = useState("http://localhost:8001");
  const [slideId, setSlideId] = useState("slide-1");
  const [tileSize, setTileSize] = useState(256);
  const [tileMode, setTileMode] = useState<"none" | "image" | "tiles">("none");
  const [slideFile, setSlideFile] = useState<File | null>(null);
  const [autoSlideId, setAutoSlideId] = useState(true);
  const [tileMeta, setTileMeta] = useState<{
    width: number;
    height: number;
    level_count: number;
    level_dimensions: number[][];
    level_downsamples: number[];
    mpp_x?: number | null;
    mpp_y?: number | null;
  } | null>(null);
  const [tileLoadError, setTileLoadError] = useState<string | null>(null);
  const [isTileLoading, setIsTileLoading] = useState(false);
  const channelItemsRef = useRef<{
    original?: OpenSeadragon.TiledImage;
    hematoxylin?: OpenSeadragon.TiledImage;
    eosin?: OpenSeadragon.TiledImage;
  }>({});

  const normalizeBaseUrl = (value: string) => {
    return value.replace(/\/$/, "");
  };

  const autoSlideIdLabel = autoSlideId ? "Auto ID enabled" : "Manual ID";

  const generateSlideId = () => {
    const now = new Date();
    const stamp = now
      .toISOString()
      .replace(/[-:]/g, "")
      .replace("T", "-")
      .slice(0, 15);
    const rand = Math.random().toString(36).slice(2, 6);
    return `slide-${stamp}-${rand}`;
  };

  const buildTileSource = (meta: {
    width: number;
    height: number;
    level_count: number;
    level_downsamples: number[];
  }, channel: "original" | "hematoxylin" | "eosin" = "original") => {
    const baseUrl = normalizeBaseUrl(tileServerUrl);
    const maxLevel = Math.max(0, meta.level_count - 1);

    const tileSource = new OpenSeadragon.TileSource({
      width: meta.width,
      height: meta.height,
      tileSize,
      minLevel: 0,
      maxLevel,
    });

    tileSource.getLevelScale = (level: number) => {
      const slideLevel = Math.max(0, meta.level_count - 1 - level);
      const downsample = meta.level_downsamples[slideLevel] || 1;
      return 1 / downsample;
    };

    tileSource.getTileUrl = (level: number, x: number, y: number) => {
      const slideLevel = Math.max(0, meta.level_count - 1 - level);
      return `${baseUrl}/tiles/${slideId}/${slideLevel}/${x}/${y}.jpg?tile_size=${tileSize}&channel=${channel}`;
    };

    return tileSource;
  };

  const addUploadedSlide = (
    id: string,
    name: string,
    levelCount: number,
    levelDimensions: number[][]
  ) => {
    const uploadedAt = new Date().toLocaleString();
    setUploadedSlides((prev) => {
      const filtered = prev.filter((slide) => slide.id !== id);
      return [{ id, name, uploadedAt, levelCount, levelDimensions }, ...filtered].slice(0, 20);
    });
  };

  const handleLoadSlide = async () => {
    if (!slideId.trim()) {
      setTileLoadError("Slide id is required.");
      return;
    }

    if (!slideFile) {
      setTileLoadError("Please choose a WSI file to upload.");
      return;
    }

    const baseUrl = normalizeBaseUrl(tileServerUrl);
    setIsTileLoading(true);
    setTileLoadError(null);

    try {
      const formData = new FormData();
      formData.append("file", slideFile);

      const uploadRes = await fetch(`${baseUrl}/slides/${slideId}/upload`, {
        method: "POST",
        body: formData,
      });

      if (!uploadRes.ok) {
        const text = await uploadRes.text();
        throw new Error(text || "Failed to upload slide");
      }

      const metaRes = await fetch(`${baseUrl}/slides/${slideId}/metadata`);
      if (!metaRes.ok) {
        const text = await metaRes.text();
        throw new Error(text || "Failed to read metadata");
      }

      const meta = await metaRes.json();
      setTileMeta(meta);
      setTileMode("tiles");
      addUploadedSlide(
        slideId,
        slideFile?.name || "Untitled slide",
        meta.level_count || 1,
        meta.level_dimensions || []
      );
    } catch (error: any) {
      setTileLoadError(error?.message || "Failed to upload slide");
    } finally {
      setIsTileLoading(false);
    }
  };

  const handleSelectUploadedSlide = async (id: string) => {
    const baseUrl = normalizeBaseUrl(tileServerUrl);
    setSlideId(id);
    setTileLoadError(null);
    setIsTileLoading(true);

    const fetchMeta = async () => {
      const metaRes = await fetch(`${baseUrl}/slides/${id}/metadata`);
      if (!metaRes.ok) {
        const text = await metaRes.text();
        const error = new Error(text || "Failed to read metadata") as Error & {
          status?: number;
        };
        error.status = metaRes.status;
        throw error;
      }
      return metaRes.json();
    };

    try {
      let meta: any;
      try {
        meta = await fetchMeta();
      } catch (error: any) {
        if (error?.status === 404) {
          const reloadRes = await fetch(`${baseUrl}/slides/${id}/reload`, { method: "POST" });
          if (!reloadRes.ok) {
            const text = await reloadRes.text();
            throw new Error(text || "Failed to reload slide");
          }
          meta = await fetchMeta();
        } else {
          throw error;
        }
      }

      setTileMeta(meta);
      setTileMode("tiles");
    } catch (error: any) {
      setTileLoadError(error?.message || "Failed to load slide");
    } finally {
      setIsTileLoading(false);
    }
  };

  // Initialize OpenSeadragon viewer
  useEffect(() => {
    if (!viewerRef.current || osdViewerRef.current) return;

    console.log("Initializing OpenSeadragon with image:", imageUrl);
    console.log("Viewer ref:", viewerRef.current);

    try {
      const viewer = OpenSeadragon({
        element: viewerRef.current,
        prefixUrl: "https://cdnjs.cloudflare.com/ajax/libs/openseadragon/4.1.0/images/",
        crossOriginPolicy: "Anonymous",
        showNavigator: true,
        navigatorPosition: "BOTTOM_RIGHT",
        navigatorSizeRatio: 0.15,
        showNavigationControl: false,
        minZoomImageRatio: 0.5,
        maxZoomPixelRatio: 3,
        visibilityRatio: 0.5,
        constrainDuringPan: true,
        animationTime: 0.5,
        gestureSettingsMouse: {
          clickToZoom: false,
          dblClickToZoom: true,
        },
      });

      console.log("OpenSeadragon viewer created:", viewer);

      // Add error handler
      viewer.addHandler("open-failed", (event: any) => {
        console.error("Failed to open image:", event);
        setLoadError("Failed to load image. Please check the image path.");
        setIsLoading(false);
      });

      // Add success handler
      viewer.addHandler("open", () => {
        console.log("Image loaded successfully");
        setIsLoading(false);
        setLoadError(null);
      });

      // Update zoom level on zoom
      viewer.addHandler("zoom", () => {
        const zoom = viewer.viewport.getZoom();
        setZoomLevel(zoom);
      });

      osdViewerRef.current = viewer;

      return () => {
        if (osdViewerRef.current) {
          osdViewerRef.current.destroy();
          osdViewerRef.current = null;
        }
      };
    } catch (error) {
      console.error("Error initializing OpenSeadragon:", error);
    }
  }, [imageUrl]);

  useEffect(() => {
    if (!osdViewerRef.current) return;

    const viewer = osdViewerRef.current;

    if (tileMode === "tiles" && tileMeta) {
      setIsLoading(true);
      setLoadError(null);
      viewer.open(buildTileSource(tileMeta, "original"));
      return;
    }

    if (tileMode === "image" && imageUrl) {
      setIsLoading(true);
      setLoadError(null);
      viewer.open({
        type: "image",
        url: imageUrl,
      });
      return;
    }

    if (tileMode === "none") {
      setIsLoading(false);
      setLoadError(null);
      viewer.close();
    }
  }, [imageUrl, tileMeta, tileMode, tileServerUrl, tileSize, slideId]);

  useEffect(() => {
    if (!osdViewerRef.current || !tileMeta || tileMode !== "tiles") return;
    const viewer = osdViewerRef.current;

    const originalItem = viewer.world.getItemAt(0);
    if (originalItem) {
      channelItemsRef.current.original = originalItem;
      originalItem.setOpacity(showOriginal ? 1 : 0);
    }

    const ensureChannel = (
      key: "hematoxylin" | "eosin",
      enabled: boolean,
      channel: "hematoxylin" | "eosin"
    ) => {
      const existing = channelItemsRef.current[key];
      if (existing) {
        existing.setOpacity(enabled ? 1 : 0);
        return;
      }
      if (!enabled) return;

      viewer.addTiledImage({
        tileSource: buildTileSource(tileMeta, channel),
        opacity: 1,
        success: (event: any) => {
          channelItemsRef.current[key] = event.item as OpenSeadragon.TiledImage;
        },
      });
    };

    ensureChannel("hematoxylin", showHematoxylin, "hematoxylin");
    ensureChannel("eosin", showEosin, "eosin");
  }, [tileMeta, tileMode, showOriginal, showHematoxylin, showEosin, tileServerUrl, tileSize, slideId]);

  const handleAnnotationComplete = (annotation: Annotation) => {
    console.log("Annotation completed:", annotation);
    setAnnotations((prev) => [...prev, annotation]);
    // Auto-select the newly created annotation
    setSelectedAnnotationId(annotation.id);
  };

  const handleAnnotationSelected = (annotationId: string | null) => {
    setSelectedAnnotationId(annotationId);
  };

  const handleUndo = () => {
    if (annotations.length > 0) {
      const newAnnotations = annotations.slice(0, -1);
      setAnnotations(newAnnotations);
      setSelectedAnnotationId(null);
    }
  };

  const handleDelete = () => {
    if (selectedAnnotationId) {
      const newAnnotations = annotations.filter(
        (ann) => ann.id !== selectedAnnotationId
      );
      setAnnotations(newAnnotations);
      setSelectedAnnotationId(null);
    }
  };

  const handleZoomIn = () => {
    if (osdViewerRef.current) {
      const currentZoom = osdViewerRef.current.viewport.getZoom();
      osdViewerRef.current.viewport.zoomTo(currentZoom * 1.2);
    }
  };

  const handleZoomOut = () => {
    if (osdViewerRef.current) {
      const currentZoom = osdViewerRef.current.viewport.getZoom();
      osdViewerRef.current.viewport.zoomTo(currentZoom / 1.2);
    }
  };

  const zoomPresets = [1, 5, 10, 20, 40];
  const micronsPerPixel = tileMeta?.mpp_x ?? tileMeta?.mpp_y ?? null;
  const imageMeta = {
    stain: "H&E",
    width: tileMeta?.width ?? null,
    height: tileMeta?.height ?? null,
    levelCount: tileMeta?.level_count ?? null,
    mpp: micronsPerPixel,
    slideId,
  };
  const isTileLoaded = tileMode === "tiles" && !!tileMeta;

  const handleZoomPreset = (level: number) => {
    if (osdViewerRef.current) {
      osdViewerRef.current.viewport.zoomTo(level);
    }
  };

  return (
    <div className="flex flex-col h-screen bg-gray-100">
      {/* Header with back button */}
      <header className="h-16 bg-gradient-to-r from-teal-700 to-teal-600 text-white flex items-center px-6 shadow-md">
        <button
          onClick={() => navigate("/")}
          className="flex items-center space-x-2 hover:bg-teal-800/50 px-3 py-2 rounded-lg transition-colors"
        >
          <ArrowLeft className="w-5 h-5" />
          <span className="font-medium">Back to Analysis</span>
        </button>
        <div className="flex-1 text-center">
          <h1 className="text-2xl font-bold">Pathora Viewer</h1>
          <p className="text-xs text-teal-100">Advanced Whole Slide Imaging Platform</p>
        </div>
        <div className="w-40"></div> {/* Spacer for centering */}
      </header>

      <div className="flex flex-1 overflow-hidden">
        {/* Tools Sidebar */}
        <ToolsSidebar
          selectedTool={selectedTool}
          onToolChange={setSelectedTool}
          annotations={annotations}
          selectedAnnotationId={selectedAnnotationId}
          onSelectAnnotation={handleAnnotationSelected}
          uploadedSlides={uploadedSlides}
          tileServerUrl={tileServerUrl}
          onTileServerUrlChange={setTileServerUrl}
          onSlideFileChange={(file) => {
            setSlideFile(file);
            if (file && autoSlideId) {
              setSlideId(generateSlideId());
            }
          }}
          slideFileName={slideFile?.name ?? null}
          onUploadSlide={handleLoadSlide}
          isTileLoading={isTileLoading}
          tileLoadError={tileLoadError}
          onSelectUploadedSlide={handleSelectUploadedSlide}
          activeLabel={activeLabel}
          onLabelChange={setActiveLabel}
          imageMeta={imageMeta}
          channelVisibility={{
            original: showOriginal,
            hematoxylin: showHematoxylin,
            eosin: showEosin,
          }}
          onChannelToggle={(channel, value) => {
            if (channel === "original") setShowOriginal(value);
            if (channel === "hematoxylin") setShowHematoxylin(value);
            if (channel === "eosin") setShowEosin(value);
          }}
          isTileLoaded={isTileLoaded}
          isCollapsed={isSidebarCollapsed}
          onToggleCollapsed={() => setIsSidebarCollapsed((prev) => !prev)}
        />

        {/* Main Viewer Area */}
        <div className="flex-1 flex flex-col">{/* Top Toolbar */}
          <TopToolbar
            slideName={slideName}
            zoomLevel={zoomLevel}
            zoomPresets={zoomPresets}
            onZoomPreset={handleZoomPreset}
            micronsPerPixel={micronsPerPixel}
            showAnnotations={showAnnotations}
            showHeatmap={showHeatmap}
            onUndo={handleUndo}
            onDelete={handleDelete}
            onZoomIn={handleZoomIn}
            onZoomOut={handleZoomOut}
            onToggleAnnotations={() => setShowAnnotations(!showAnnotations)}
            onToggleHeatmap={() => setShowHeatmap(!showHeatmap)}
            canUndo={annotations.length > 0}
            canDelete={selectedAnnotationId !== null}
          />

          <div className="flex-1 flex overflow-hidden">
            {/* Viewer Container */}
            <div className="flex-1 relative">
              <div
                ref={viewerRef}
                className="absolute inset-0 bg-black"
                style={{ width: "100%", height: "100%" }}
              />

              {/* Loading State */}
              {isLoading && (
                <div className="absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-75 z-50">
                  <div className="text-center">
                    <div className="inline-block animate-spin rounded-full h-16 w-16 border-t-4 border-b-4 border-teal-500 mb-4"></div>
                    <p className="text-white text-lg font-semibold">Loading slide viewer...</p>
                    <p className="text-gray-300 text-sm mt-2">Initializing OpenSeadragon</p>
                  </div>
                </div>
              )}

              {/* Error State */}
              {loadError && (
                <div className="absolute inset-0 flex items-center justify-center bg-gray-900 bg-opacity-75 z-50">
                  <div className="bg-white rounded-lg p-6 max-w-md text-center">
                    <div className="text-red-500 text-5xl mb-4">⚠️</div>
                    <h3 className="text-xl font-bold text-gray-800 mb-2">Failed to Load Image</h3>
                    <p className="text-gray-600 mb-4">{loadError}</p>
                    <button
                      onClick={() => window.location.reload()}
                      className="px-4 py-2 bg-teal-600 text-white rounded-lg hover:bg-teal-700 transition-colors"
                    >
                      Retry
                    </button>
                  </div>
                </div>
              )}

              {/* Annotation Canvas */}
              <AnnotationCanvas
                viewer={osdViewerRef.current}
                tool={selectedTool}
                onAnnotationComplete={handleAnnotationComplete}
                activeLabel={activeLabel}
                onAnnotationSelected={handleAnnotationSelected}
                annotations={annotations}
                selectedAnnotationId={selectedAnnotationId}
                showAnnotations={showAnnotations}
              />
            

            {/* Annotations count */}
            {showAnnotations && annotations.length > 0 && (
              <div className="absolute bottom-4 left-4 bg-white px-3 py-2 rounded shadow-md text-sm z-40">
                <span className="font-semibold">Annotations:</span> {annotations.length}
              </div>
            )}

            {/* Heatmap overlay placeholder */}
            {showHeatmap && (
              <div className="absolute inset-0 pointer-events-none bg-gradient-to-br from-red-500/20 via-yellow-500/20 to-green-500/20" />
            )}

              {tileMode === "none" && !isLoading && !loadError && (
                <div className="absolute inset-0 flex items-center justify-center bg-gray-900/60 z-40">
                  <div className="rounded-lg px-5 py-4 text-center">
                    <div className="text-sm font-semibold text-white">Upload a WSI to start</div>
                    <div className="text-xs text-white/80 mt-1">
                      Use the uploader in the left Uploads tab to load a slide.
                    </div>
                  </div>
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
