import PropTypes from "prop-types";
import { useState, useEffect, useRef } from "react";
import { Alert } from "antd";
import { useMediaQuery } from "react-responsive";
import { useNavigate, useLocation } from "react-router-dom";
import { Element, scroller } from "react-scroll";
import axios from "axios";
import Page from "./components/Page";
import Images from "./components/ImageSidebar";
import { ImageProvider, useImageContext } from "./contexts/ImageContext";
import LoadingModal from "./components/LoadingModal";
import { ActionProvider } from "./contexts/ActionContext";
import SubPage from "./components/SubPage";
import PropertyPage from "./components/PropertyPage";
import { MenuProvider } from "./contexts/MenuContext";
import { ThemeProvider } from "./contexts/ThemeContext";
import {
  SettingsProvider,
  useSettingsContext,
} from "./contexts/SettingsContext";
const apiUrl = import.meta.env.VITE_API_URL;

// Component that handles image loading after API data is fetched
const AppContent = ({ pages, properties, images }) => {
  const { loadImages } = useImageContext();
  const [loadedOnce, setLoadedOnce] = useState(false);
  const [currentPage, setCurrentPage] = useState({ pageType: "landingPage" });
  const [currentTheme, setCurrentTheme] = useState();
  const [currentProperty, setCurrentProperty] = useState(null);
  const [currentPageIdx, setCurrentPageIdx] = useState(0);
  const [contentVisible, setContentVisible] = useState(true);
  const [subPageVisible, setSubPageVisible] = useState(false);
  const locationRef = useRef();
  const previousPageRef = useRef(null);
  const currentPageRef = useRef(currentPage);
  const landingPages = pages.filter((page) => page.pageType == "landingPage");

  const navigate = useNavigate();
  const location = useLocation();
  const settings = useSettingsContext();
  const isMobile = useMediaQuery({ maxWidth: 800 });

  // Load images when they become available
  useEffect(() => {
    if (!loadedOnce && images && images.length > 0) {
      loadImages(images);
      setLoadedOnce(true);
    }
  }, [images, loadImages, loadedOnce]);

  const setPageTitle = (name) => {
    document.title = name ? `${name} - The Hideout` : "The Hideout";
  };

  // Handle direct URL navigation
  // eslint-disable-next-line react-hooks/exhaustive-deps
  useEffect(() => {
    locationRef.current = location.pathname;
    if (Object.keys(settings).length == 0) {
      return;
    }
    // Check if the URL matches /properties/:slug
    if (location.pathname.startsWith("/properties/")) {
      const propertySlug = location.pathname.split("/properties/")[1];
      if (propertySlug != "") {
        const property = properties.find((p) => p.slug === propertySlug);
        if (property) {
          // Set previousPage when navigating to a property
          if (currentPageRef.current.pageType !== "subPage") {
            previousPageRef.current = { ...currentPageRef.current };
          }

          setCurrentProperty(property);
          setContentVisible(true);
          if (currentProperty != null || currentPage.pageType == "subPage") {
            setSubPageVisible(false);
            setTimeout(() => {
              setSubPageVisible(true);
            }, 500);
          } else {
            setSubPageVisible(true);
          }
          setPageTitle(property.name);
        } else {
          navigate(settings.redirects["404"]);
          setCurrentProperty(null); // property not found
        }
        return; // exit early since we're on a property page
      }
    }
    setCurrentProperty(null);
    if (pages.length > 0 && location.pathname !== "/") {
      const slug = location.pathname.slice(1); // Remove leading slash
      const page = pages.find((p) => p.slug === slug);

      if (page) {
        // Set previousPage when navigating to a subpage
        if (
          page.pageType === "subPage" &&
          currentPageRef.current.pageType !== "subPage"
        ) {
          previousPageRef.current = { ...currentPageRef.current };
        }

        setCurrentPage(page);
        setCurrentPageIdx(pages.indexOf(page));
        setPageTitle(page.name);

        if (page.pageType === "landingPage") {
          // Ensure DOM has rendered before attempting to scroll
          setSubPageVisible(false);
          requestAnimationFrame(() => {
            scroller.scrollTo(slug, {
              duration: 0,
              delay: 0,
              smooth: "easeInOutQuart",
              containerId: "app-container",
            });
          });
        } else {
          setContentVisible(false);
          if (currentPage.pageType == page.pageType) {
            setSubPageVisible(false);
            setTimeout(() => {
              setSubPageVisible(true);
            }, 500);
          } else {
            setSubPageVisible(true);
          }

          setTimeout(() => {
            setContentVisible(true);
          }, 600);
        }
      } else {
        navigate(settings.redirects["404"]);
      }
    } else if (
      pages.length > 0 &&
      location.pathname === "/" &&
      settings?.redirects?.index != null
    ) {
      console.log("settings.redirects", settings.redirects);
      const indexPage = pages.find((p) => p.slug === settings.redirects.index);
      // Default to index page
      setCurrentPage(indexPage);
      setCurrentPageIdx(0);
      setPageTitle(indexPage.name);
      navigate(`/${indexPage.slug}`, { replace: true });
    }
  }, [
    location.pathname,
    pages,
    settings?.redirects?.index,
    navigate,
    settings,
    properties,
    currentPage.pageType,
    currentProperty,
  ]);

  // Set up scroll spy to update URL when scrolling
  useEffect(() => {
    if (currentPage.pageType == "subPage") {
      return;
    }
    if (pages.length > 0) {
      let scrollTimeout;

      const handleScrollSpy = () => {
        const container = document.getElementById("app-container");
        if (!container) return;

        const scrollTop = container.scrollTop;
        const containerHeight = container.clientHeight;
        const viewportCenter = scrollTop + containerHeight / 2;

        // Find which page is currently in the center of the viewport
        let currentPageIndex = 0;
        let minDistance = Infinity;

        pages.forEach((page, index) => {
          const element = document.querySelector(`[data-name="${page.slug}"]`);
          if (element) {
            const elementTop = element.offsetTop;
            //const elementBottom = elementTop + element.offsetHeight;
            const elementCenter = elementTop + element.offsetHeight / 2;

            const distance = Math.abs(viewportCenter - elementCenter);
            if (distance < minDistance) {
              minDistance = distance;
              currentPageIndex = index;
              if (minDistance != 0) {
                setContentVisible(false);
              }
              if (minDistance == 0) {
                setContentVisible(true);
              }
            }
          }
        });

        // Debounce both current page state and URL updates to reduce frequency
        clearTimeout(scrollTimeout);
        scrollTimeout = setTimeout(() => {
          if (pages[currentPageIndex] && pages[currentPageIndex].slug) {
            // Update current page state for Images component
            if (currentPageIdx !== currentPageIndex) {
              setCurrentPage(pages[currentPageIndex]);
              setCurrentPageIdx(currentPageIndex);
              setPageTitle(pages[currentPageIndex].name);

              const newPath = `/${pages[currentPageIndex].slug}`;
              if (locationRef.current !== newPath) {
                navigate(newPath, { replace: true });
              }
            }
          }
        }, 100); // Debounce for 100ms
      };

      const container = document.getElementById("app-container");
      if (container) {
        container.addEventListener("scroll", handleScrollSpy, {
          passive: true,
        });
        return () => {
          container.removeEventListener("scroll", handleScrollSpy);
          clearTimeout(scrollTimeout);
        };
      }
    }
  }, [pages, navigate, currentPageIdx, currentPage.pageType]);

  // Update currentPageRef whenever currentPage changes
  useEffect(() => {
    currentPageRef.current = currentPage;
  }, [currentPage]);

  // Set body background color to match current page's theme
  useEffect(() => {
    const theme = settings.themes.find(
      (theme) => theme.name === currentPage?.theme
    );
    setCurrentTheme(theme);
  }, [currentPage, settings.themes]);

  // Handle subpage close with smart navigation
  const handleSubPageClose = () => {
    // Check if there's a previous page stored in ref
    if (previousPageRef.current && previousPageRef.current.slug) {
      // Navigate to the previous page's slug
      navigate(`/${previousPageRef.current.slug}`);
    } else {
      // No previous page, redirect to home
      navigate("/");
    }
  };

  return (
    <ThemeProvider currentTheme={currentTheme}>
      <MenuProvider pages={pages} currentPageSlug={currentPage?.slug}>
        <div
          className={
            !isMobile
              ? "th-app-container"
              : "th-app-container th-app-container-mobile"
          }
          id="app-container"
        >
          {landingPages.map((pageData, index) => (
            <Element
              key={index}
              name={pageData.slug}
              className={
                !isMobile
                  ? "th-page-wrapper"
                  : "th-page-wrapper th-page-wrapper-mobile"
              }
              data-name={pageData.slug}
            >
              <Page
                pageData={pageData}
                visible={
                  contentVisible && pageData.notionId == currentPage.notionId
                }
                theme={settings.themes.find(
                  (theme) => theme.name === pageData.theme
                )}
                themes={settings.themes}
                isSubPage={false}
                id={index}
              />
            </Element>
          ))}
        </div>
        <SubPage
          visible={currentPage.pageType == "subPage" && subPageVisible == true}
        >
          <Page
            pageData={currentPage}
            visible={contentVisible}
            theme={settings.themes.find(
              (theme) => theme.name === currentPage.theme
            )}
            themes={settings.themes}
            isSubPage={true}
            id={currentPageIdx}
            showClose={true}
            showMenu={false}
            onClose={handleSubPageClose}
          />
        </SubPage>
        <SubPage visible={currentProperty != null && subPageVisible == true}>
          <PropertyPage
            propertyData={currentProperty}
            visible={contentVisible}
            onClose={() => {
              navigate("/" + settings.redirects.properties);
            }}
          />
        </SubPage>
        {isMobile && <div className="th-mobile-overlay" />}

        {!isMobile && (
          <Images
            imageCollections={[...pages, ...properties]}
            currentSlug={currentProperty?.slug || currentPage?.slug}
          />
        )}
      </MenuProvider>
    </ThemeProvider>
  );
};

AppContent.propTypes = {
  images: PropTypes.shape({
    length: PropTypes.number,
  }),
  pages: PropTypes.array.isRequired,
  properties: PropTypes.array.isRequired,
  themes: PropTypes.shape({
    find: PropTypes.func,
  }),
};

const App = () => {
  const [pages, setPages] = useState([]);
  const [properties, setProperties] = useState([]);
  const [images, setImages] = useState([]);
  const [settings, setSettings] = useState({
    themes: [],
    redirects: {},
    branding: [],
  });
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  const actions = {};

  useEffect(() => {
    const fetchPages = async () => {
      try {
        setLoading(true);
        const response = await axios.get(`${apiUrl}/content`);
        setPages(response.data.pages || response.data); // Handle both array and object with pages property
        setProperties(response.data.properties || response.data);
        setImages(response.data.images || response.data);
        setSettings(response.data.settings || response.data);
      } catch (err) {
        setError(
          err.response?.data?.message || err.message || "Failed to fetch pages"
        );
        console.error("Error fetching pages:", err);
      } finally {
        setLoading(false);
      }
    };

    fetchPages();
  }, []);

  if (error) {
    return (
      <div className="th-error-container">
        <Alert
          message="Error Loading Pages"
          description={error}
          type="error"
          showIcon
        />
      </div>
    );
  }

  return (
    <SettingsProvider settings={settings}>
      <ActionProvider onAction={actions}>
        <ImageProvider>
          <AppContent pages={pages} images={images} properties={properties} />
          <LoadingModal visible={loading} />
        </ImageProvider>
      </ActionProvider>
    </SettingsProvider>
  );
};

export default App;
