import {
  useCallback,
  useEffect,
  useRef,
  useState,
  type PointerEvent,
} from "react";
import { ChevronDown } from "lucide-react";
import { createRoot } from "react-dom/client";
import { useLocation, useNavigate } from "react-router-dom";
import {
  LayoutGrid,
  Search,
  SlidersHorizontal,
  Menu,
  X,
} from "lucide-react";
import Swal from "sweetalert2";
import {
  WhatsappShareButton, WhatsappIcon,
  TelegramShareButton, TelegramIcon,
  TwitterShareButton, XIcon,
  FacebookShareButton, FacebookIcon,
  EmailShareButton, EmailIcon,
} from "react-share";
import { ProductGroupCard, IndividualProductCard } from "./ProductCards";
import { useRoomVisualizer } from "./roomVisualizerHooks";
import { useCatalogProducts } from "./useCatalogProducts";
import { RoomPreviewPanel } from "./RoomPreviewPanel";
import useAppStore from "../../store/useAppStore";
import { useSegmentCanvas } from "../../hooks/useSegmentCanvas";
import { useApplyTexture } from "../../hooks/useApplyTexture";
import { API_BASE } from "../../api/client";

type RoomVisualizerState = {
  previewImage?: string;
  filename?: string;
  maskCount?: number;
};

// ── Hook para detectar mobile (< 1024px) ─────────────────────────────────────
function useIsMobile() {
  const [isMobile, setIsMobile] = useState(() => window.innerWidth < 1024);
  useEffect(() => {
    const handler = () => setIsMobile(window.innerWidth < 1024);
    window.addEventListener("resize", handler);
    return () => window.removeEventListener("resize", handler);
  }, []);
  return isMobile;
}

export default function RoomVisualizer() {
  const location = useLocation();
  const navigate = useNavigate();
  const state = location.state as RoomVisualizerState | null;
  const isMobile = useIsMobile();

  const storedPreviewImage = useAppStore((store) => store.previewImage);
  const segmentFilename = useAppStore((store) => store.segmentFilename);
  const accumulatedFilename = useAppStore((store) => store.accumulatedFilename);
  const setAccumulatedFilename = useAppStore((store) => store.setAccumulatedFilename);
  const setSegmentResult = useAppStore((store) => store.setSegmentResult);
  const setPreviewImage = useAppStore((store) => store.setPreviewImage);

  // Restaurar segmentFilename y previewImage cuando se abre una sesión del historial
  useEffect(() => {
    if (state?.filename && state.filename !== segmentFilename) {
      setSegmentResult(state.filename, state.maskCount ?? 0);
      setAccumulatedFilename(null); // limpiar ediciones de sesión anterior
    }
    if (state?.previewImage) {
      setPreviewImage(state.previewImage);
    }
  // Solo al montar — state no cambia tras la navegación
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const [currentPreviewImage, setCurrentPreviewImage] = useState<string | null>(() => {
    if (accumulatedFilename) return `${API_BASE}/seg/image/${accumulatedFilename}`;
    return state?.previewImage ?? storedPreviewImage ?? null;
  });

  const [zoom, setZoom] = useState(1);
  const [offset, setOffset] = useState({ x: 0, y: 0 });
  const [dragStart, setDragStart] = useState<{ x: number; y: number } | null>(null);
  const [imageSize, setImageSize] = useState({ width: 0, height: 0 });
  const wrapperRef = useRef<HTMLDivElement>(null);

  const { products, categories, loading, error } = useCatalogProducts();

  // null = sin interacción (primera categoría abierta por defecto)
  // Set vacío = usuario cerró todo deliberadamente
  const [openCategoryIds, setOpenCategoryIds] = useState<Set<string> | null>(null);

  const isCategoryOpen = useCallback(
    (id: string) => {
      if (openCategoryIds === null) {
        return categories.length > 0 && id === categories[0].id;
      }
      return openCategoryIds.has(id);
    },
    [openCategoryIds, categories],
  );

  const toggleCategory = useCallback((id: string) => {
    setOpenCategoryIds((prev) => {
      const base =
        prev === null
          ? categories.length > 0
            ? new Set([categories[0].id])
            : new Set<string>()
          : new Set(prev);
      if (base.has(id)) base.delete(id);
      else base.add(id);
      return base;
    });
  }, [categories]);

  const {
    viewMode, showGrid, showList,
    openProductId, handleSelectProduct, selectedProduct,
    isSearchOpen, setIsSearchOpen,
    searchQuery, setSearchQuery, closeSearch,
    filteredProducts, chunkArray,
  } = useRoomVisualizer(products);

  useEffect(() => { showList(); }, [showList]);


  const {
    canvasRef,
    hoveredMask,
    selectedMasks,
    segmentMeta,
    handleCanvasMouseMove,
    handleCanvasMouseLeave,
    handleCanvasClick,
    clearSelection,
  } = useSegmentCanvas(segmentFilename);

  const { applyTexture, isApplying, resetResult } = useApplyTexture();

  const applyTextureWith = useCallback(
    async (texturePath: string) => {
      if (!segmentFilename || selectedMasks.size === 0) return;
      const baseFilename = accumulatedFilename ?? segmentFilename;
      try {
        const data = await applyTexture(baseFilename, [...selectedMasks], texturePath, segmentFilename);
        if (data?.output_url) {
          setCurrentPreviewImage(`${API_BASE}${data.output_url}?t=${Date.now()}`);
          setAccumulatedFilename(data.output_filename);
          clearSelection();
        }
      } catch {
        // error ya guardado en el hook
      }
    },
    [applyTexture, segmentFilename, selectedMasks, clearSelection, accumulatedFilename, setAccumulatedFilename],
  );

  const handleApplyTexture = useCallback(async () => {
    if (selectedProduct) await applyTextureWith(selectedProduct.ref);
  }, [applyTextureWith, selectedProduct]);

  const handleProductSelect = useCallback(
    async (id: string | number | null) => {
      handleSelectProduct(id);
      if (!id || selectedMasks.size === 0 || !segmentFilename) return;
      const product = products.find((p) => p.id === id);
      if (product) await applyTextureWith(product.ref);
    },
    [handleSelectProduct, selectedMasks, segmentFilename, products, applyTextureWith],
  );

  const handleReset = useCallback(() => {
    const original = state?.previewImage ?? storedPreviewImage ?? null;
    setCurrentPreviewImage(original);
    setAccumulatedFilename(null);
    clearSelection();
    resetResult();
  }, [state, storedPreviewImage, setAccumulatedFilename, clearSelection, resetResult]);

  const handleDownload = useCallback(async () => {
    if (!currentPreviewImage) return;
    const response = await fetch(currentPreviewImage);
    const blob = await response.blob();
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `hyper-reality-${Date.now()}.jpg`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }, [currentPreviewImage]);

  const handleShare = useCallback(async (): Promise<void> => {
    let shareUrl = window.location.href;
    const outputFilename = accumulatedFilename;
    if (outputFilename) {
      try {
        const res = await fetch(`${API_BASE}/api/share`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ output_filename: outputFilename, segment_filename: segmentFilename }),
        });
        if (res.ok) {
          const data = (await res.json()) as { share_id: string };
          shareUrl = `${window.location.origin}/app/share/${data.share_id}`;
        }
      } catch {
        // fallback to current URL
      }
    }

    const title = "My design with Hyper Reality Visualizer";
    let reactRoot: ReturnType<typeof createRoot> | null = null;

    await Swal.fire({
      title: "Compartir diseño",
      html: `
        <div style="text-align:left">
          <p style="font-size:13px;color:#666;margin-bottom:8px">Enlace de tu diseño:</p>
          <div style="display:flex;gap:8px;align-items:center;margin-bottom:20px">
            <input id="swal-share-url" readonly value="${shareUrl}"
              style="flex:1;padding:8px 12px;border:1px solid #ddd;border-radius:8px;font-size:12px;background:#f9f9f9;outline:none;color:#333;" />
            <button id="swal-copy-btn"
              style="padding:8px 16px;background:#0047AB;color:white;border:none;border-radius:8px;cursor:pointer;font-size:13px;white-space:nowrap;font-weight:600;">
              Copiar
            </button>
          </div>
          <p style="font-size:13px;color:#666;margin-bottom:12px">Compartir en:</p>
          <div id="swal-share-buttons" style="display:flex;gap:12px;flex-wrap:wrap;"></div>
        </div>
      `,
      showConfirmButton: false,
      showCloseButton: true,
      width: 500,
      didOpen: () => {
        const copyBtn = document.getElementById("swal-copy-btn");
        copyBtn?.addEventListener("click", async () => {
          await navigator.clipboard.writeText(shareUrl).catch(() => {});
          if (copyBtn) { copyBtn.textContent = "¡Copiado!"; copyBtn.style.background = "#16a34a"; }
          setTimeout(() => {
            if (copyBtn) { copyBtn.textContent = "Copiar"; copyBtn.style.background = "#0047AB"; }
          }, 2000);
        });
        const container = document.getElementById("swal-share-buttons");
        if (container) {
          reactRoot = createRoot(container);
          reactRoot.render(
            <>
              <WhatsappShareButton url={shareUrl} title={title}><WhatsappIcon size={48} round /></WhatsappShareButton>
              <TelegramShareButton url={shareUrl} title={title}><TelegramIcon size={48} round /></TelegramShareButton>
              <TwitterShareButton url={shareUrl} title={title}><XIcon size={48} round /></TwitterShareButton>
              <FacebookShareButton url={shareUrl}><FacebookIcon size={48} round /></FacebookShareButton>
              <EmailShareButton url={shareUrl} subject={title} body="Mira mi diseño de habitación:"><EmailIcon size={48} round /></EmailShareButton>
            </>,
          );
        }
      },
      willClose: () => { reactRoot?.unmount(); },
    });
  }, [segmentFilename, accumulatedFilename]);

  const clampOffset = useCallback(
    (x: number, y: number, zoomValue: number) => {
      const wrapper = wrapperRef.current;
      if (!wrapper || imageSize.width === 0 || imageSize.height === 0) return { x, y };
      const containerRect = wrapper.getBoundingClientRect();
      const scaledWidth = imageSize.width * zoomValue;
      const scaledHeight = imageSize.height * zoomValue;
      const maxX = Math.max(0, (scaledWidth - containerRect.width) / 2);
      const maxY = Math.max(0, (scaledHeight - containerRect.height) / 2);
      return {
        x: Math.max(-maxX, Math.min(maxX, x)),
        y: Math.max(-maxY, Math.min(maxY, y)),
      };
    },
    [imageSize],
  );

  const updateImageSize = useCallback(
    (img: HTMLImageElement) => {
      const wrapper = wrapperRef.current;
      if (!wrapper) return;
      const containerRect = wrapper.getBoundingClientRect();
      const naturalRatio = img.naturalWidth / img.naturalHeight;
      const containerRatio = containerRect.width / containerRect.height;
      const width = naturalRatio > containerRatio ? containerRect.width : containerRect.height * naturalRatio;
      const height = naturalRatio > containerRatio ? containerRect.width / naturalRatio : containerRect.height;
      setImageSize({ width, height });
      setOffset((current) => clampOffset(current.x, current.y, zoom));
    },
    [clampOffset, zoom],
  );

  const handleWheel = useCallback(
    (event: WheelEvent) => {
      event.preventDefault();
      setZoom((currentZoom) => {
        const next = Math.min(3, Math.max(1, currentZoom - event.deltaY * 0.0015));
        setOffset((current) => clampOffset(current.x, current.y, next));
        return next;
      });
    },
    [clampOffset],
  );

  useEffect(() => {
    const el = wrapperRef.current;
    if (!el) return;
    el.addEventListener("wheel", handleWheel, { passive: false });
    return () => el.removeEventListener("wheel", handleWheel);
  }, [handleWheel]);

  const handlePointerDown = useCallback((event: PointerEvent<HTMLDivElement>) => {
    setDragStart({ x: event.clientX, y: event.clientY });
  }, []);

  const handlePointerMove = useCallback(
    (event: PointerEvent<HTMLDivElement>) => {
      if (!dragStart || zoom <= 1) return;
      const dx = event.clientX - dragStart.x;
      const dy = event.clientY - dragStart.y;
      setOffset((current) => clampOffset(current.x + dx, current.y + dy, zoom));
      setDragStart({ x: event.clientX, y: event.clientY });
    },
    [clampOffset, dragStart, zoom],
  );

  const handlePointerUp = useCallback(() => setDragStart(null), []);

  // Props compartidos entre mobile y desktop para RoomPreviewPanel
  const previewPanelProps = {
    previewImage: currentPreviewImage,
    offset,
    zoom,
    imageSize,
    wrapperRef,
    canvasRef,
    selectedProduct,
    selectedMasks,
    hoveredMask,
    segmentMeta,
    isApplying,
    onBack: () => navigate("/app"),
    onPointerDown: handlePointerDown,
    onPointerMove: handlePointerMove,
    onPointerUp: handlePointerUp,
    updateImageSize,
    onCanvasMouseMove: handleCanvasMouseMove,
    onCanvasMouseLeave: handleCanvasMouseLeave,
    onCanvasClick: handleCanvasClick,
    onApplyTexture: handleApplyTexture,
    onReset: handleReset,
    onDownload: handleDownload,
    onShare: handleShare,
  };

  // ── Mobile strip: thumbnails + búsqueda ──────────────────────────────────
  const MobileProductStrip = (
    <div style={{ background: "#fff", borderTop: "1px solid #e5e7eb", flexShrink: 0 }}>
      {isSearchOpen && (
        <div style={{ padding: "8px 12px 4px" }}>
          <div style={{ position: "relative" }}>
            <Search style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", width: 16, height: 16, color: "#9ca3af" }} />
            <input
              autoFocus
              type="text"
              placeholder="Buscar productos..."
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              style={{
                width: "100%",
                paddingLeft: 34,
                paddingRight: 32,
                paddingTop: 8,
                paddingBottom: 8,
                borderRadius: 8,
                border: "2px solid #0047AB",
                outline: "none",
                fontSize: 14,
                color: "#333",
                boxSizing: "border-box",
              }}
            />
            <button
              onClick={closeSearch}
              style={{ position: "absolute", right: 8, top: "50%", transform: "translateY(-50%)", background: "none", border: "none", cursor: "pointer", padding: 4 }}
            >
              <X style={{ width: 14, height: 14, color: "#9ca3af" }} />
            </button>
          </div>
        </div>
      )}

      {/* Thumbnails con scroll horizontal */}
      <div style={{ display: "flex", overflowX: "auto", gap: 8, padding: "8px 12px", scrollbarWidth: "none" }}>
        {loading ? (
          <div style={{ display: "flex", alignItems: "center", justifyContent: "center", width: "100%", height: 64, fontSize: 12, color: "#9ca3af" }}>
            Cargando...
          </div>
        ) : (
          filteredProducts.map((product) => (
            <button
              key={product.id}
              onClick={() => handleProductSelect(product.id)}
              style={{
                flexShrink: 0,
                width: 64,
                height: 64,
                borderRadius: 12,
                overflow: "hidden",
                border: openProductId === product.id ? "2.5px solid #0047AB" : "2px solid #e5e7eb",
                boxShadow: openProductId === product.id ? "0 0 0 2px #dbe7ff" : "none",
                cursor: "pointer",
                padding: 0,
                background: "none",
                transition: "border-color 0.15s",
              }}
            >
              <img
                src={product.image}
                alt={product.name}
                style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }}
              />
            </button>
          ))
        )}
      </div>

      {/* Info del producto + íconos */}
      <div style={{ display: "flex", alignItems: "center", padding: "0 12px 10px", gap: 8, minHeight: 36 }}>
        {selectedProduct ? (
          <div style={{ flex: 1, minWidth: 0 }}>
            <p style={{ fontSize: 10, color: "#707070", textTransform: "uppercase", letterSpacing: "0.05em", margin: 0, lineHeight: 1 }}>
              {selectedProduct.brand}
            </p>
            <p style={{ fontSize: 12, fontWeight: 600, color: "#333", margin: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
              {selectedProduct.name}
            </p>
          </div>
        ) : (
          <div style={{ flex: 1 }} />
        )}
        <div style={{ display: "flex", gap: 4, flexShrink: 0 }}>
          <button
            onClick={() => setIsSearchOpen(!isSearchOpen)}
            style={{ padding: 6, borderRadius: 8, border: "none", background: "none", cursor: "pointer" }}
          >
            <Search style={{ width: 16, height: 16, color: "#0047AB" }} />
          </button>
          <button
            style={{ padding: 6, borderRadius: 8, border: "none", background: "none", cursor: "pointer" }}
          >
            <SlidersHorizontal style={{ width: 16, height: 16, color: "#0047AB" }} />
          </button>
        </div>
      </div>
    </div>
  );

  // ── Desktop sidebar ───────────────────────────────────────────────────────
  const DesktopSidebar = (
    <div style={{ width: "25%", height: "100%", display: "flex", flexDirection: "column", borderRight: "1px solid rgba(0,71,171,0.1)", background: "#fff", flexShrink: 0 }}>
      <div style={{ padding: "24px 24px 0" }}>
        <div style={{ height: 1, background: "#e5e7eb", width: "100%" }} />

        {/* Barra de herramientas */}
        <div style={{ display: "flex", alignItems: "center", gap: 8, height: 46 }}>
          {!isSearchOpen && (
            <button
              onClick={() => setIsSearchOpen(true)}
              className="p-3 rounded-lg border border-[#0047AB] bg-[#0047AB] text-white hover:bg-[#003a94] transition-all duration-300 flex items-center justify-center shadow-sm"
            >
              <Search className="w-5 h-5" />
            </button>
          )}
          <button className="flex-1 flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg border border-[#0047AB] bg-white text-[#0047AB] hover:bg-[#eaf1ff] transition-all duration-300 shadow-sm">
            <SlidersHorizontal className="w-4 h-4 text-[#0047AB]" />
            <span className="font-medium text-sm">Filtros</span>
          </button>
          <div className="flex border border-gray-300 rounded-lg overflow-hidden shadow-sm">
            <button
              onClick={showList}
              className={`p-2.5 flex items-center justify-center transition-colors ${viewMode === "list" ? "bg-[#0047AB] text-white" : "bg-white text-[#0047AB] hover:bg-[#eaf1ff] border-r border-[#dbe7ff]"}`}
            >
              <Menu className="w-5 h-5" />
            </button>
            <button
              onClick={showGrid}
              className={`p-2.5 flex items-center justify-center transition-colors ${viewMode === "grid" ? "bg-[#0047AB] text-white" : "bg-white text-[#0047AB] hover:bg-[#eaf1ff]"}`}
            >
              <LayoutGrid className="w-5 h-5" />
            </button>
          </div>
        </div>

        {isSearchOpen && (
          <div className="animate-in slide-in-from-top-2 fade-in duration-300">
            <div className="relative">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
              <input
                autoFocus
                type="text"
                placeholder="¿Qué estás buscando?..."
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
                className="w-full pl-11 pr-10 py-3 rounded-lg border-2 border-[#0047AB] bg-white focus:outline-none transition-all text-sm text-[#333333]"
              />
              <button
                onClick={closeSearch}
                className="absolute right-3 top-1/2 -translate-y-1/2 p-1 text-gray-400 hover:text-gray-600 bg-white rounded-full shadow-sm"
              >
                <X className="w-4 h-4" />
              </button>
            </div>
          </div>
        )}
      </div>

      {/* Lista de productos con acordeón por categoría */}
      <div className="flex-1 overflow-y-auto py-2">
        {loading ? (
          <div className="flex items-center justify-center h-32 text-sm text-gray-400">Cargando productos...</div>
        ) : error ? (
          <div className="flex items-center justify-center h-32 text-sm text-red-400">{error}</div>
        ) : searchQuery ? (
          /* Búsqueda activa → lista plana de resultados */
          <div className={viewMode === "grid" ? "px-4" : "px-2"}>
            {filteredProducts.length === 0 ? (
              <div className="flex items-center justify-center h-24 text-sm text-gray-400">Sin resultados</div>
            ) : viewMode === "grid" ? (
              <div className="flex flex-col gap-4">
                {chunkArray(filteredProducts, 3).map((group, i) => (
                  <ProductGroupCard key={i} group={group} openProductId={openProductId} onSelectProduct={handleProductSelect} />
                ))}
              </div>
            ) : (
              <div className="grid grid-cols-1 gap-3">
                {filteredProducts.map((product) => (
                  <IndividualProductCard key={product.id} product={product} isSelected={openProductId === product.id} onToggle={() => handleProductSelect(product.id)} />
                ))}
              </div>
            )}
          </div>
        ) : (
          /* Sin búsqueda → acordeón por categoría */
          <div className="flex flex-col">
            {categories.map((cat) => {
              const isOpen = isCategoryOpen(cat.id);
              return (
                <div key={cat.id} className="border-b border-gray-100 last:border-0">
                  <button
                    onClick={() => toggleCategory(cat.id)}
                    className="w-full flex items-center justify-between px-4 py-3 hover:bg-[#f4f8ff] transition-colors text-left"
                  >
                    <div className="flex items-center gap-2 min-w-0">
                      <span className="font-semibold text-sm text-[#333] truncate">{cat.nombre}</span>
                      <span className="text-xs text-[#0047AB] bg-[#eaf1ff] px-1.5 py-0.5 rounded-full flex-shrink-0">
                        {cat.products.length}
                      </span>
                    </div>
                    <ChevronDown
                      className={`w-4 h-4 text-[#0047AB] flex-shrink-0 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`}
                    />
                  </button>

                  {isOpen && (
                    <div className={viewMode === "grid" ? "px-4 pb-4" : "px-2 pb-2"}>
                      {viewMode === "grid" ? (
                        <div className="flex flex-col gap-4">
                          {chunkArray(cat.products, 3).map((group, i) => (
                            <ProductGroupCard key={i} group={group} openProductId={openProductId} onSelectProduct={handleProductSelect} />
                          ))}
                        </div>
                      ) : (
                        <div className="grid grid-cols-1 gap-3">
                          {cat.products.map((product) => (
                            <IndividualProductCard key={product.id} product={product} isSelected={openProductId === product.id} onToggle={() => handleProductSelect(product.id)} />
                          ))}
                        </div>
                      )}
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        )}
      </div>
    </div>
  );

  return (
    <div style={{ height: "100svh", width: "100%", background: "#fff", fontFamily: "sans-serif", color: "#000", display: "flex", flexDirection: "column" }}>
      {isMobile ? (
        // ── Layout Mobile: imagen arriba, strip de thumbnails abajo ──────────
        <div style={{ flex: 1, display: "flex", flexDirection: "column", minHeight: 0 }}>
          <div style={{ flex: 1, minHeight: 0, overflow: "hidden" }}>
            <RoomPreviewPanel {...previewPanelProps} />
          </div>
          {MobileProductStrip}
        </div>
      ) : (
        // ── Layout Desktop: sidebar izquierda + imagen derecha ───────────────
        <div style={{ flex: 1, display: "flex", flexDirection: "row", minHeight: 0 }}>
          {DesktopSidebar}
          <div style={{ flex: 1, minWidth: 0, overflow: "hidden" }}>
            <RoomPreviewPanel {...previewPanelProps} />
          </div>
        </div>
      )}
    </div>
  );
}
