import React, { useState, useEffect, useRef, useCallback } from "react";
import "./ImageGallery.css";
import moment from "moment";
import { useDispatch, useSelector } from "react-redux";
import { useModal } from "./ModalContext";
import ImagePop from "./ImagePop";
import Avatar from "../../components/common/Avatar";
import DateRangePicker from "../../components/common/DateRangePicker";
import eventBus from "../../services/eventBus";
import Breadcrumb from "../../components/common/Breadcrumb";
import { formatUTCToLocalTime } from "../../utils/dateUtils";
import useImageGallery from "../../hooks/useImageGallery";
import { useProjectName } from "../../hooks/useProjects";
import { setProjectId } from "../../slices/localVariablesSlice";

const SCROLL_THRESHOLD = 5;

const ImageGallery = () => {
  const selectedProjectId = useSelector(
    (store) => store.localVariables.projectId
  );
  const dispatch = useDispatch();
  const { projectNames } = useProjectName();

  // Auto-select a project on mount
  useEffect(() => {
    if (!selectedProjectId && projectNames?.length) {
      dispatch(setProjectId(projectNames[0].id));
    }
  }, [selectedProjectId, projectNames, dispatch]);

  // Filter states
  const [selectedFilters, setSelectedFilters] = useState({
    building: [],
    floor: [],
    activity: [],
    uploadedBy: [],
    workCategory: [],
    workArea: [],
    startDate: "",
    endDate: "",
  });
  const [appliedFilters, setAppliedFilters] = useState({
    buildingIds: null,
    floorIds: null,
    activityIds: null,
    uploadedByIds: null,
    workCategoryIds: null,
    workAreaIds: null,
    startDate: null,
    endDate: null,
  });
  const [collapsedFilters, setCollapsedFilters] = useState({
    dateRange: false,
    building: false,
    floor: false,
    activity: false,
    uploadedBy: false,
    workCategory: false,
    workArea: false,
  });
  const [isFilterPanelOpen, setIsFilterPanelOpen] = useState(false);
  const [hoveredImage, setHoveredImage] = useState(null);

  const imageGroupRefs = useRef({});
  const loaderRef = useRef(null);
  const filterPanelRef = useRef(null);
  const filterButtonRef = useRef(null);
  const { openModal } = useModal();

  const {
    data,
    fetchNextPage,
    hasNextPage,
    isLoading,
    isFetchingNextPage,
    refetch,
  } = useImageGallery(selectedProjectId, appliedFilters);

  const images = data?.pages.flatMap((page) => page.data) || [];

  useEffect(() => {
    const handleClick = (e) => {
      if (
        filterPanelRef.current &&
        !filterPanelRef.current.contains(e.target) &&
        filterButtonRef.current &&
        !filterButtonRef.current.contains(e.target)
      ) {
        setIsFilterPanelOpen(false);
      }
    };
    document.addEventListener("mousedown", handleClick);
    return () => document.removeEventListener("mousedown", handleClick);
  }, []);

  useEffect(() => {
    if (selectedProjectId) refetch();
  }, [selectedProjectId, appliedFilters, refetch]);

  useEffect(() => {
    const handler = (data) => {
      if (data.projectId === selectedProjectId) refetch();
    };
    eventBus.on("image_gallery", handler);
    return () => eventBus.off("image_gallery", handler);
  }, [selectedProjectId, refetch]);

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

  const observer = new IntersectionObserver(
    ([entry]) => {
      if (entry.isIntersecting && hasNextPage && !isFetchingNextPage && !isLoading) {
        fetchNextPage();
      }
    },
    { rootMargin: "200px", threshold: 0.1 }
  );

  observer.observe(loaderRef.current);

  return () => {
    if (loaderRef.current) {
      observer.unobserve(loaderRef.current); 
    }
  };
}, [hasNextPage, isFetchingNextPage, isLoading, fetchNextPage]);


  // Utility: derive filter options
  const getUniqueValues = useCallback(
    (idKey, nameKey) => {
      const m = new Map();
      images.forEach((batch) => {
        const id = idKey === "floorIds" ? batch.floorIds : batch[idKey];
        if (id && batch[nameKey] && !m.has(id)) {
          m.set(id, batch[nameKey]);
        }
      });
      return [...m.entries()].sort((a, b) => a[1].localeCompare(b[1]));
    },
    [images]
  );

  const getUploadedBy = useCallback(() => {
    const m = new Map();
    images.forEach((batch) => {
      batch.documents.forEach((doc) => {
        const name = `${doc.uploadedBy?.firstName || ""} ${
          doc.uploadedBy?.lastName || ""
        }`.trim();
        if (doc.uploadedBy?.id && name && !m.has(doc.uploadedBy.id)) {
          m.set(doc.uploadedBy.id, name);
        }
      });
    });
    return [...m.entries()].sort((a, b) => a[1].localeCompare(b[1]));
  }, [images]);

  const buildings = getUniqueValues("buildingId", "buildingName");
  const floors = getUniqueValues("floorIds", "floorName");
  const activities = getUniqueValues("activityId", "activityName");
  const workAreas = getUniqueValues("workAreaId", "workAreaName");
  const workCategories = getUniqueValues("workCategoryId", "workCategoryName");
  const uploadedByUsers = getUploadedBy();

  const toggleFilter = useCallback((type, id, name) => {
    setSelectedFilters((prev) => {
      const arr = prev[type];
      const exists = arr.some(([x]) => x === id);
      const updated = exists
        ? arr.filter(([x]) => x !== id)
        : [...arr, [id, name]];
      return { ...prev, [type]: updated };
    });
  }, []);

  const setDateRange = useCallback(({ startDate, endDate }) => {
    setSelectedFilters((prev) => ({
      ...prev,
      startDate: startDate || "",
      endDate: endDate || "",
    }));
  }, []);

  const toggleCollapse = useCallback((type) => {
    setCollapsedFilters((prev) => ({ ...prev, [type]: !prev[type] }));
  }, []);

  const handleApplyFilters = useCallback(() => {
    const payload = {
      buildingIds: selectedFilters.building.map(([x]) => x) || null,
      floorIds: selectedFilters.floor.map(([x]) => x) || null,
      activityIds: selectedFilters.activity.map(([x]) => x) || null,
      uploadedByIds: selectedFilters.uploadedBy.map(([x]) => x) || null,
      workCategoryIds: selectedFilters.workCategory.map(([x]) => x) || null,
      workAreaIds: selectedFilters.workArea.map(([x]) => x) || null,
      startDate: selectedFilters.startDate || null,
      endDate: selectedFilters.endDate || null,
    };
    const changed = Object.keys(payload).some((key) => {
      const oldVal = appliedFilters[key],
        newVal = payload[key];
      return Array.isArray(oldVal)
        ? oldVal.length !== newVal.length ||
            oldVal.some((x) => !newVal.includes(x))
        : oldVal !== newVal;
    });
    if (changed) setAppliedFilters(payload);
  }, [selectedFilters, appliedFilters]);

  const handleClear = useCallback(() => {
    setSelectedFilters({
      building: [],
      floor: [],
      activity: [],
      uploadedBy: [],
      workCategory: [],
      workArea: [],
      startDate: "",
      endDate: "",
    });
    setAppliedFilters({
      buildingIds: null,
      floorIds: null,
      activityIds: null,
      uploadedByIds: null,
      workCategoryIds: null,
      workAreaIds: null,
      startDate: null,
      endDate: null,
    });
  }, []);

  const scrollLeft = useCallback(
    (key) =>
      imageGroupRefs.current[key]?.scrollBy({ left: -200, behavior: "smooth" }),
    []
  );
  const scrollRight = useCallback(
    (key) =>
      imageGroupRefs.current[key]?.scrollBy({ left: 200, behavior: "smooth" }),
    []
  );

  const renderCategory = (label, items, type) => (
    <div
      className={`dropdown my-2 ${collapsedFilters[type] ? "collapsed" : ""}`}
    >
      <div
        className="dropdown-header bg-label-primary"
        onClick={() => toggleCollapse(type)}
      >
        <strong>{label}</strong>
        <div className="header-controls">
          {((type === "dateRange" &&
            (selectedFilters.startDate || selectedFilters.endDate)) ||
            (type !== "dateRange" && selectedFilters[type]?.length > 0)) && (
            <button
              className="clear-button"
              onClick={(e) => {
                e.stopPropagation();
                setSelectedFilters((prev) => ({
                  ...prev,
                  [type]: type === "dateRange" ? "" : [],
                  ...(type === "dateRange" && { startDate: "", endDate: "" }),
                }));
              }}
            >
              Clear
            </button>
          )}
          <span className="collapse-icon">
            {collapsedFilters[type] ? "+" : "-"}
          </span>
        </div>
      </div>
      {!collapsedFilters[type] && (
        <div className="dropdown-content">
          {type === "dateRange" ? (
            <DateRangePicker
              onRangeChange={setDateRange}
              endDateMode="today"
              startDate={selectedFilters.startDate}
              endDate={selectedFilters.endDate}
            />
          ) : (
            items.map(([id, name]) => (
              <label key={id}>
                <input
                  type="checkbox"
                  checked={selectedFilters[type].some(([x]) => x === id)}
                  onChange={() => toggleFilter(type, id, name)}
                />
                {name}
              </label>
            ))
          )}
        </div>
      )}
    </div>
  );

  return (
    <div
      className={`gallery-container container-fluid ${
        isFilterPanelOpen ? "filter-panel-open-end" : ""
      }`}
    >
      <Breadcrumb data={[{ label: "Home", link: "/" }, { label: "Gallery" }]} />
      <div className="main-content">
        <button
          className={`filter-button btn-primary ${
            isFilterPanelOpen ? "closed-icon" : ""
          }`}
          onClick={() => setIsFilterPanelOpen((p) => !p)}
          ref={filterButtonRef}
        >
          {isFilterPanelOpen ? (
            <i className="fa-solid fa-times fs-5" />
          ) : (
            <i className="bx bx-slider-alt ms-1" />
          )}
        </button>
        <div className="activity-section">
          {isLoading ? (
            <div className="text-center">
              <p>Loading...</p>
            </div>
          ) : images.length ? (
            images.map((batch) => {
              const doc = batch.documents[0];
              const userName = `${doc.uploadedBy?.firstName || ""} ${
                doc.uploadedBy?.lastName || ""
              }`.trim();
              const date = formatUTCToLocalTime(doc.uploadedAt);
              const hasArrows = batch.documents.length > SCROLL_THRESHOLD;
              return (
                <div key={batch.batchId} className="grouped-section">
                  <div className="group-heading">
                    {/* Uploader Info */}
                    <div className="d-flex align-items-center mb-1">
                      <Avatar
                        size="xs"
                        firstName={doc.uploadedBy?.firstName}
                        lastName={doc.uploadedBy?.lastName}
                        className="me-2"
                      />
                      <div className="d-flex flex-column align-items-start">
                        <strong className="user-name-text">{userName}</strong>
                        <span className="text-muted small">{date}</span>
                      </div>
                    </div>

                    {/* Location Info */}
                    <div className="location-line text-secondary">
                      <div className="d-flex align-items-center flex-wrap gap-1 text-secondary">
                        {" "}
                        <span className="d-flex align-items-center">
                          <span>{batch.buildingName}</span>
                          <i className="bx bx-chevron-right " />
                        </span>
                        <span className="d-flex align-items-center">
                          <span>{batch.floorName}</span>
                          <i className="bx bx-chevron-right m" />
                        </span>
                        <span className="d-flex align-items-center ">
                          <span>{batch.workAreaName || "Unknown"}</span>
                          <i className="bx bx-chevron-right " />
                          <span>{batch.activityName}</span>
                        </span>
                      </div>
                      {batch.workCategoryName && (
                        <span className="badge bg-label-primary ms-2">
                          {batch.workCategoryName}
                        </span>
                      )}
                    </div>
                  </div>

                  <div className="image-group-wrapper">
                    {hasArrows && (
                      <button
                        className="scroll-arrow left-arrow"
                        onClick={() => scrollLeft(batch.batchId)}
                      >
                        ‹
                      </button>
                    )}
                    <div
                      className="image-group-horizontal"
                      ref={(el) => (imageGroupRefs.current[batch.batchId] = el)}
                    >
                      {batch.documents.map((d, i) => {
                        const hoverDate = moment(d.uploadedAt).format(
                          "DD MMMM, YYYY"
                        );
                        const hoverTime = moment(d.uploadedAt).format(
                          "hh:mm A"
                        );
                        return (
                          <div
                            key={d.id}
                            className="image-card"
                            onClick={() =>
                              openModal(
                                <ImagePop batch={batch} initialIndex={i} />
                              )
                            }
                            onMouseEnter={() => setHoveredImage(d)}
                            onMouseLeave={() => setHoveredImage(null)}
                          >
                            <div className="image-wrapper">
                              <img src={d.url} alt={`Image ${i + 1}`} />
                            </div>
                            {hoveredImage === d && (
                              <div className="image-hover-description">
                                <p>
                                  <strong>Date:</strong> {hoverDate}
                                </p>
                                <p>
                                  <strong>Time:</strong> {hoverTime}
                                </p>
                                <p>
                                  <strong>Activity:</strong>{" "}
                                  {batch.activityName}
                                </p>
                              </div>
                            )}
                          </div>
                        );
                      })}
                    </div>
                    {hasArrows && (
                      <button
                        className="scroll-arrow right-arrow"
                        onClick={() => scrollRight(batch.batchId)}
                      >
                        <i className="bx bx-chevron-right"></i>
                      </button>
                    )}
                  </div>
                </div>
              );
            })
          ) : (
            <p className="text-center text-muted mt-5">
              No images match the selected filters.
            </p>
          )}
          <div ref={loaderRef}>
            {isFetchingNextPage && hasNextPage && <p>Loading...</p>}
            {!hasNextPage && !isLoading && images.length > 0 && (
              <p className="text-muted">
                You've reached the end of the images.
              </p>
            )}
          </div>
        </div>
      </div>

      <div
        className={`offcanvas offcanvas-end ${isFilterPanelOpen ? "show" : ""}`}
        ref={filterPanelRef}
      >
        <div className="offcanvas-header">
          <h5>Filters</h5>
          <button
            className="btn-close"
            onClick={() => setIsFilterPanelOpen(false)}
          />
        </div>
        <div className="filter-actions mt-auto mx-2">
          <button className="btn btn-secondary btn-xs" onClick={handleClear}>
            Clear All
          </button>
          <button
            className="btn btn-primary btn-xs"
            onClick={handleApplyFilters}
          >
            Apply Filters
          </button>
        </div>
        <div className="offcanvas-body d-flex flex-column">
          {renderCategory("Date Range", [], "dateRange")}
          {renderCategory("Building", buildings, "building")}
          {renderCategory("Floor", floors, "floor")}
          {renderCategory("Work Area", workAreas, "workArea")}
          {renderCategory("Activity", activities, "activity")}
          {renderCategory("Uploaded By (User)", uploadedByUsers, "uploadedBy")}
          {renderCategory("Work Category", workCategories, "workCategory")}
        </div>
      </div>
    </div>
  );
};

export default ImageGallery;
