import { useCallback, useEffect, useState } from "react";
import {
  Routes,
  Route,
  Navigate,
  Outlet,
  useLocation,
  useNavigate,
} from "react-router-dom";
import { useAuth } from "@/auth";
import { useDispatch, useSelector } from "react-redux";
import { actions, selectors } from "@/store";
import routes, {
  hasNavigation,
  getRouteBy,
  hasNoFooter,
  hasNoHeader,
  hasNavbarFooter,
} from "@/routes";
import BirthdayPage from "../BirthdayPage";
import BirthtimePage from "../BirthtimePage";
import CreateProfilePage from "../CreateProfilePage";
import EmailEnterPage from "../EmailEnterPage";
import SubscriptionPage from "../SubscriptionPage";
import PaymentPage from "../PaymentPage";
import WallpaperPage from "../WallpaperPage";
import StaticPage from "../StaticPage";
import NotFoundPage from "../NotFoundPage";
import Header from "../Header";
import Navbar from "../Navbar";
import Footer from "../Footer";
import "./styles.css";
import DidYouKnowPage from "../DidYouKnowPage";
import FreePeriodInfoPage from "../FreePeriodInfoPage";
import AttentionPage from "../AttentionPage";
import FeedbackPage from "../FeedbackPage";
import CompatibilityPage from "../Compatibility";
import BreathPage from "../BreathPage";
import PriceListPage from "../PriceListPage";
import CompatResultPage from "../CompatResultPage";
import HomePage from "../HomePage";
import UserCallbacksPage from "../UserCallbacksPage";
import NavbarFooter, { INavbarHomeItems } from "../NavbarFooter";
import { EPathsFromHome } from "@/store/siteConfig";
import parseAPNG, { APNG } from "apng-js";
import { useApi, useApiCall } from "@/api";
import { Asset } from "@/api/resources/Assets";

function App(): JSX.Element {
  const [isSpecialOfferOpen, setIsSpecialOfferOpen] = useState<boolean>(false);
  const [leoApng, setLeoApng] = useState<Error | APNG>(Error);
  const navigate = useNavigate();
  const api = useApi();

  const closeSpecialOfferAttention = () => {
    setIsSpecialOfferOpen(false);
    navigate(routes.client.emailEnter());
  };

  const assetsData = useCallback(async () => {
    const { assets } = await api.getAssets({
      category: String("au"),
    });
    return assets;
  }, [api]);

  const { data } = useApiCall<Asset[]>(assetsData);

  useEffect(() => {
    async function getApng() {
      if (!data) return;
      const response = await fetch(
        data.find((item) => item.key === "au.apng.leo")?.url || ""
      );
      const arrayBuffer = await response.arrayBuffer();
      setLeoApng(parseAPNG(arrayBuffer));
    }
    getApng();
  }, [data]);

  return (
    <Routes>
      <Route element={<Layout setIsSpecialOfferOpen={setIsSpecialOfferOpen} />}>
        <Route path={routes.client.root()} element={<MainPage />} />
        <Route path={routes.client.birthday()} element={<BirthdayPage />} />
        <Route path={routes.client.didYouKnow()} element={<DidYouKnowPage />} />
        <Route
          path={routes.client.freePeriodInfo()}
          element={<FreePeriodInfoPage />}
        />
        <Route
          path={routes.client.attention()}
          element={
            <AttentionPage
              isOpenModal={isSpecialOfferOpen}
              onCloseSpecialOffer={closeSpecialOfferAttention}
            />
          }
        />
        <Route path={routes.client.feedback()} element={<FeedbackPage />} />
        <Route path={routes.client.birthtime()} element={<BirthtimePage />} />
        <Route path={routes.client.createProfile()} element={<SkipStep />} />
        <Route path={routes.client.emailEnter()} element={<EmailEnterPage />} />
        <Route path={routes.client.static()} element={<StaticPage />} />
        <Route
          path={routes.client.compatibility()}
          element={<CompatibilityPage />}
        />
        <Route
          path={routes.client.compatibilityResult()}
          element={<CompatResultPage />}
        />
        <Route
          path={routes.client.breath()}
          element={<BreathPage leoApng={leoApng} />}
        />
        <Route path={routes.client.priceList()} element={<PriceListPage />} />
        <Route path={routes.client.home()} element={<HomePage />} />
        <Route
          path={routes.client.breathResult()}
          element={<UserCallbacksPage />}
        />
        <Route
          path={routes.client.subscription()}
          element={<SubscriptionPage />}
        />
        <Route path={routes.client.paymentMethod()} element={<PaymentPage />} />
        <Route
          path={routes.client.wallpaper()}
          element={<ProtectWallpaperPage />}
        />
        <Route element={<PrivateOutlet />}></Route>
        <Route path="*" element={<NotFoundPage />} />
      </Route>
    </Routes>
  );
}

interface LayoutProps {
  setIsSpecialOfferOpen: React.Dispatch<React.SetStateAction<boolean>>;
}

function Layout({ setIsSpecialOfferOpen }: LayoutProps): JSX.Element {
  const location = useLocation();
  const navigate = useNavigate();
  const dispatch = useDispatch();
  const showNavbar = hasNavigation(location.pathname);
  const showFooter = hasNoFooter(location.pathname);
  const showHeader = hasNoHeader(location.pathname);
  const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false);
  const changeIsSpecialOfferOpen = () => setIsSpecialOfferOpen(true);
  const homeConfig = useSelector(selectors.selectHome);
  const showNavbarFooter = homeConfig.isShowNavbar;

  const handleCompatibility = () => {
    dispatch(
      actions.siteConfig.update({
        home: {
          pathFromHome: EPathsFromHome.navbar,
          isShowNavbar: showNavbarFooter,
        },
      })
    );
    navigate(routes.client.compatibility());
  };
  const handleBreath = () => {
    dispatch(
      actions.siteConfig.update({
        home: {
          pathFromHome: EPathsFromHome.navbar,
          isShowNavbar: showNavbarFooter,
        },
      })
    );
    navigate(routes.client.breath());
  };

  const navbarItems: INavbarHomeItems[] = [
    {
      title: "Breathing",
      path: routes.client.breath(),
      paths: [routes.client.breath(), routes.client.breathResult()],
      image: "Breath.svg",
      onClick: handleBreath,
    },
    {
      title: "Aura",
      path: routes.client.home(),
      paths: [routes.client.home()],
      image: "Aura.svg",
      active: true,
      onClick: () => null,
    },
    {
      title: "Compatibility",
      path: routes.client.compatibility(),
      paths: [
        routes.client.compatibility(),
        routes.client.compatibilityResult(),
      ],
      image: "Compatibility.svg",
      onClick: handleCompatibility,
    },
    {
      title: "My Moon",
      path: routes.client.wallpaper(),
      paths: [routes.client.wallpaper()],
      image: "moon.svg",
      onClick: () => null,
    },
  ];

  return (
    <div className="container">
      {showHeader ? (
        <Header
          openMenu={() => setIsMenuOpen(true)}
          clickCross={changeIsSpecialOfferOpen}
        />
      ) : null}
      <main className="content">
        <Outlet />
      </main>
      {showFooter ? <Footer color={showNavbar ? "black" : "white"} /> : null}
      {showNavbar ? (
        <Navbar isOpen={isMenuOpen} closeMenu={() => setIsMenuOpen(false)} />
      ) : null}
      {showNavbarFooter && hasNavbarFooter(location.pathname) ? (
        <NavbarFooter items={navbarItems} />
      ) : null}
    </div>
  );
}

function PrivateOutlet(): JSX.Element {
  const { user } = useAuth();
  return user ? (
    <Outlet />
  ) : (
    <Navigate to={routes.client.root()} replace={true} />
  );
}

function SkipStep(): JSX.Element {
  const { user } = useAuth();
  return user ? (
    <Navigate to={routes.client.emailEnter()} replace={true} />
  ) : (
    <CreateProfilePage />
  );
}

function MainPage(): JSX.Element {
  const status = useSelector(selectors.selectStatus);
  return <Navigate to={getRouteBy(status)} replace={true} />;
}

function ProtectWallpaperPage(): JSX.Element {
  const status = useSelector(selectors.selectStatus);
  return <WallpaperPage />;
  return status === "subscribed" ? (
    <WallpaperPage />
  ) : (
    <Navigate to={getRouteBy(status)} replace={true} />
  );
}

export default App;
