// Set webpack public path at runtime for chunk loading
// This MUST be the very first thing before any imports
if (window.arraySubs !== undefined && window.arraySubs.publicPath) {
  __webpack_public_path__ = window.arraySubs.publicPath;
}
import React, {
  lazy,
  Suspense,
  useCallback,
  useEffect,
  useRef,
  useState,
} from "react";
import ReactDOM from "react-dom/client";
import {
  HashRouter as Router,
  Routes,
  Route,
  Navigate,
  useLocation,
} from "react-router-dom";
import { __ } from "@wordpress/i18n";
import "@scss/main/index.scss";
import "@libs/form-builder/scss/form-builder.scss";
import "@libs/toast/toast.scss";
import useAdminMenuSync from "@/hooks/useAdminMenuSync";
import { getRouteVisiblity } from "@libs/menu-visibility";

// Lazy load pages

// Settings pages
const GeneralSettings = lazy(() =>
  import("./pages/Settings/GeneralSettings.jsx"),
);
const RetentionFlowPage = lazy(() => import("./pages/RetentionFlow/index.jsx"));
const PlanSwitchingSettings = lazy(() =>
  import("./pages/Settings/PlanSwitchingSettings.jsx"),
);
const RefundsSettings = lazy(() =>
  import("./pages/Settings/RefundsSettings.jsx"),
);
const FeatureManagerSettings = lazy(() =>
  import("./pages/Settings/FeatureManagerSettings.jsx"),
);
const StoreCreditSettings = lazy(() =>
  import("./pages/StoreCredit/StoreCreditSettings.jsx"),
);
const SkipPauseSettings = lazy(() =>
  import("./pages/Settings/SkipPauseSettings.jsx"),
);
const ToolkitSettings = lazy(() =>
  import("./pages/Settings/ToolkitSettings.jsx"),
);
const ProfileFieldsSettings = lazy(() =>
  import("./pages/Settings/ProfileFieldsSettings.jsx"),
);
const MyAccountEditor = lazy(() =>
  import("./pages/ProfileBuilder/MyAccountEditor.jsx"),
);
const GatewayHealthDashboard = lazy(() =>
  import("./pages/Settings/GatewayHealthDashboard.jsx"),
);

// Store Credit pages
const StoreCreditManagement = lazy(() =>
  import("./pages/StoreCredit/StoreCreditManagement.jsx"),
);
const CreditHistory = lazy(() =>
  import("./pages/StoreCredit/CreditHistory.jsx"),
);

// Members Access pages
const MembersAccessPage = lazy(() => import("./pages/MembersAccess/index.jsx"));
const RoleMappingRulesTab = lazy(() =>
  import("./pages/MembersAccess/RoleMappingRulesTab.jsx"),
);
const UrlRulesTab = lazy(() => import("./pages/MembersAccess/UrlRulesTab.jsx"));
const CptRulesTab = lazy(() => import("./pages/MembersAccess/CptRulesTab.jsx"));
const DiscountRulesTab = lazy(() =>
  import("./pages/MembersAccess/DiscountRulesTab.jsx"),
);
const EcommerceRulesTab = lazy(() =>
  import("./pages/MembersAccess/EcommerceRulesTab.jsx"),
);
const DownloadsRulesTab = lazy(() =>
  import("./pages/MembersAccess/DownloadsRulesTab.jsx"),
);
const LoginLimitRulesTab = lazy(() =>
  import("./pages/MembersAccess/LoginLimitRulesTab.jsx"),
);
const ManageMembers = lazy(() =>
  import("./pages/MembersAccess/ManageMembers.jsx"),
);
const Shortcodes = lazy(() => import("./pages/Shortcodes.jsx"));
const ActivityAudits = lazy(() => import("./pages/Audits/ActivityAudits.jsx"));
const ScheduledJobLogs = lazy(() =>
  import("./pages/Audits/ScheduledJobLogs.jsx"),
);

// Checkout Builder
const CheckoutBuilder = lazy(() => import("./pages/CheckoutBuilder/index.jsx"));
const CheckoutBuilderSettings = lazy(() =>
  import("./pages/CheckoutBuilder/Settings.jsx"),
);

const Help = lazy(() => import("./pages/Help.jsx"));
const EasySetup = lazy(() => import("./pages/EasySetup/index.jsx"));
const Reports = lazy(() => import("./pages/Reports.jsx"));

// Subscription pages
const SubscriptionsList = lazy(() => import("./pages/SubscriptionsList.jsx"));
const SubscriptionForm = lazy(() => import("./pages/SubscriptionForm.jsx"));
const SubscriptionEdit = lazy(() => import("./pages/SubscriptionEdit.jsx"));
const SubscriptionDetail = lazy(() => import("./pages/SubscriptionDetail.jsx"));
const SubscriptionFeatureLog = lazy(() =>
  import("./pages/SubscriptionFeatureLog.jsx"),
);

const hasLoadedFeature = (fragment) => {
  const classes = window.arraySubs?.liveBootClasses || [];
  return classes.some((cls) => cls.includes(fragment));
};

const isMultiLoginPreventionEnabled = () => {
  return Boolean(window.arraySubs?.settings?.toolkit?.multi_login_prevention);
};

const ACTION_CONTAINER_SELECTOR = ".arraysubs-bottom-fixed-actions";
const ACTION_LEFT_CSS_VAR = "--arraysubs-actions-left";
const ACTION_RIGHT_CSS_VAR = "--arraysubs-actions-right";

const clearActionOffsets = () => {
  document.documentElement.style.removeProperty(ACTION_LEFT_CSS_VAR);
  document.documentElement.style.removeProperty(ACTION_RIGHT_CSS_VAR);
};

const updateActionOffsets = () => {
  const actionContainer = document.querySelector(ACTION_CONTAINER_SELECTOR);

  if (!actionContainer) {
    clearActionOffsets();
    return null;
  }

  const { left, right } = actionContainer.getBoundingClientRect();
  const leftPos = Math.max(left, 0);
  const rightPos = Math.max(window.innerWidth - right, 0);

  document.documentElement.style.setProperty(
    ACTION_LEFT_CSS_VAR,
    `${leftPos}px`,
  );
  document.documentElement.style.setProperty(
    ACTION_RIGHT_CSS_VAR,
    `${rightPos}px`,
  );

  return actionContainer;
};

const MainAppLoadingState = ({ isTransitioning = true }) => {
  return (
    <div
      className={`arraysubs-route-overlay${
        isTransitioning ? " is-active" : ""
      }`}
      aria-hidden={!isTransitioning}
    >
      <span className="spinner is-active" />
    </div>
  );
};

const useRouteTransition = () => {
  const location = useLocation();
  const [isTransitioning, setIsTransitioning] = useState(false);
  const prevPathRef = useRef(location.pathname);
  const mountTimeRef = useRef(Date.now());
  const timersRef = useRef({});

  const clearTimers = useCallback(() => {
    Object.values(timersRef.current).forEach((id) => clearTimeout(id));
    timersRef.current = {};
  }, []);

  useEffect(() => {
    // Skip during initial mount period to avoid overlay on first load.
    if (Date.now() - mountTimeRef.current < 1000) {
      prevPathRef.current = location.pathname;
      return undefined;
    }

    if (prevPathRef.current === location.pathname) {
      return undefined;
    }
    prevPathRef.current = location.pathname;

    clearTimers();
    setIsTransitioning(true);

    const hasLoadingIndicators = () => {
      const page = document.querySelector(".arraysubs-admin-page");
      if (!page) {
        return false;
      }
      const indicators = page.querySelectorAll(
        ".spinner.is-active, .arraysubs-skeleton, .arraysubs-loading",
      );

      return Array.from(indicators).some(
        (el) => !el.closest(".arraysubs-route-overlay"),
      );
    };

    const dismiss = () => {
      setIsTransitioning(false);
      clearTimers();
    };

    // Wait for the new component to mount and set up its loading state.
    timersRef.current.initial = setTimeout(() => {
      const poll = () => {
        if (!hasLoadingIndicators()) {
          dismiss();
          return;
        }
        timersRef.current.poll = setTimeout(poll, 150);
      };
      poll();
    }, 350);

    // Safety fallback: always dismiss after 10 seconds.
    timersRef.current.safety = setTimeout(dismiss, 10000);

    return clearTimers;
  }, [location.pathname, clearTimers]);

  return isTransitioning;
};

const MainContent = () => {
  useAdminMenuSync();
  const location = useLocation();
  const isTransitioning = useRouteTransition();
  const hasMultiLoginPrevention = hasLoadedFeature("MultiLoginPrevention");
  const canAccessLoginLimit =
    hasMultiLoginPrevention && isMultiLoginPreventionEnabled();

  useEffect(() => {
    const bodyClass = "arraysubs-pro-only-route";
    const menuItems = window.arraySubs?.menu?.items || [];
    const currentPath = location.pathname;
    const routeVisiblity = getRouteVisiblity(currentPath, menuItems);

    if (routeVisiblity === -1) {
      document.body.classList.add(bodyClass);

      return () => {
        document.body.classList.remove(bodyClass);
        clearActionOffsets();
      };
    }

    document.body.classList.remove(bodyClass);

    const appRoot =
      document.querySelector(".arraysubs-admin-page") || document.body;
    let animationFrameId = 0;
    let observedActionContainer = null;
    let actionResizeObserver = null;
    let layoutResizeObserver = null;

    const disconnectActionResizeObserver = () => {
      if (actionResizeObserver) {
        actionResizeObserver.disconnect();
        actionResizeObserver = null;
      }
    };

    const scheduleActionOffsetsUpdate = () => {
      if (animationFrameId) {
        window.cancelAnimationFrame(animationFrameId);
      }

      animationFrameId = window.requestAnimationFrame(() => {
        animationFrameId = 0;

        const nextActionContainer = updateActionOffsets();

        if (nextActionContainer === observedActionContainer) {
          return;
        }

        disconnectActionResizeObserver();
        observedActionContainer = nextActionContainer;

        if (!window.ResizeObserver || !observedActionContainer) {
          return;
        }

        actionResizeObserver = new ResizeObserver(() => {
          scheduleActionOffsetsUpdate();
        });
        actionResizeObserver.observe(observedActionContainer);
      });
    };

    scheduleActionOffsetsUpdate();

    const mutationObserver = new MutationObserver(() => {
      scheduleActionOffsetsUpdate();
    });

    mutationObserver.observe(appRoot, {
      childList: true,
      subtree: true,
    });

    window.addEventListener("resize", scheduleActionOffsetsUpdate);

    if (window.ResizeObserver) {
      layoutResizeObserver = new ResizeObserver(() => {
        scheduleActionOffsetsUpdate();
      });
      layoutResizeObserver.observe(appRoot);
    }

    return () => {
      document.body.classList.remove(bodyClass);

      if (animationFrameId) {
        window.cancelAnimationFrame(animationFrameId);
      }

      window.removeEventListener("resize", scheduleActionOffsetsUpdate);
      mutationObserver.disconnect();
      disconnectActionResizeObserver();

      if (layoutResizeObserver) {
        layoutResizeObserver.disconnect();
      }

      clearActionOffsets();
    };
  }, [location.pathname]);

  return (
    <div className="arraysubs-admin-page">
      <div
        className={`arraysubs-route-overlay${
          isTransitioning ? " is-active" : ""
        }`}
        aria-hidden={!isTransitioning}
      >
        <span className="spinner is-active" />
      </div>
      <Suspense fallback={<MainAppLoadingState />}>
        <Routes>
          <Route path="/" element={<Navigate to="/subscriptions" replace />} />

          {/* Settings */}
          <Route path="/settings/general" element={<GeneralSettings />} />

          <Route
            path="/settings/plan-switching"
            element={<PlanSwitchingSettings />}
          />
          <Route path="/settings/refunds" element={<RefundsSettings />} />
          <Route
            path="/settings/feature-manager"
            element={<FeatureManagerSettings />}
          />
          <Route
            path="/store-credit/settings"
            element={<StoreCreditSettings />}
          />
          <Route path="/settings/skip-pause" element={<SkipPauseSettings />} />
          <Route path="/settings/toolkit" element={<ToolkitSettings />} />
          {/* Profile Builder */}
          <Route
            path="/profile-builder/profile-form"
            element={<ProfileFieldsSettings />}
          />
          <Route
            path="/profile-builder/my-account"
            element={<MyAccountEditor />}
          />
          <Route
            path="/settings/gateways"
            element={<GatewayHealthDashboard />}
          />

          {/* Store Credit */}
          <Route
            path="/store-credit/:userId?"
            element={<StoreCreditManagement />}
          />
          <Route path="/store-credit/history" element={<CreditHistory />} />

          {/* Manage Members - Standalone page */}
          <Route path="/manage-members/:userId?" element={<ManageMembers />} />

          {/* Members Access - Flat Routes */}
          <Route path="/members-access" element={<MembersAccessPage />}>
            <Route index element={<RoleMappingRulesTab />} />
          </Route>
          <Route
            path="/members-access/discount-rules"
            element={<MembersAccessPage />}
          >
            <Route index element={<DiscountRulesTab />} />
          </Route>
          <Route
            path="/members-access/ecommerce-rules"
            element={<MembersAccessPage />}
          >
            <Route index element={<EcommerceRulesTab />} />
          </Route>
          <Route
            path="/members-access/url-rules"
            element={<MembersAccessPage />}
          >
            <Route index element={<UrlRulesTab />} />
          </Route>
          <Route
            path="/members-access/cpt-rules"
            element={<MembersAccessPage />}
          >
            <Route index element={<CptRulesTab />} />
          </Route>
          <Route
            path="/members-access/downloads-rules"
            element={<MembersAccessPage />}
          >
            <Route index element={<DownloadsRulesTab />} />
          </Route>
          <Route
            path="/members-access/login-limit"
            element={<MembersAccessPage />}
          >
            <Route
              index
              element={
                canAccessLoginLimit ? (
                  <LoginLimitRulesTab />
                ) : (
                  <Navigate to="/members-access" replace />
                )
              }
            />
          </Route>
          {/* Retention Flow */}
          <Route path="/retention-flow" element={<RetentionFlowPage />} />

          <Route path="/shortcodes" element={<Shortcodes />} />
          <Route path="/audits/activity-audits" element={<ActivityAudits />} />
          <Route
            path="/audits/scheduled-job-logs"
            element={<ScheduledJobLogs />}
          />

          {/* Checkout Builder */}
          <Route path="/checkout-builder" element={<CheckoutBuilder />} />
          <Route
            path="/checkout-builder/settings"
            element={<CheckoutBuilderSettings />}
          />

          <Route path="/reports" element={<Reports />} />

          <Route path="/help" element={<Help />} />

          {/* Easy Setup */}
          <Route path="/easy-setup" element={<EasySetup />} />

          {/* Subscriptions */}
          <Route path="/subscriptions" element={<SubscriptionsList />} />
          <Route path="/subscriptions/form" element={<SubscriptionForm />} />
          <Route
            path="/subscriptions/edit/:id"
            element={<SubscriptionEdit />}
          />
          <Route
            path="/subscriptions/detail/:id"
            element={<SubscriptionDetail />}
          />
          <Route
            path="/subscriptions/feature-log"
            element={<SubscriptionFeatureLog />}
          />
        </Routes>
      </Suspense>
    </div>
  );
};

// Find #wpbody, clear it, and create the root element
const wpbody = document.getElementById("wpbody");

if (wpbody) {
  // Remove all children of #wpbody
  while (wpbody.firstChild) {
    wpbody.removeChild(wpbody.firstChild);
  }

  // Create the root element
  const rootElementId =
    window?.arraySubs?.env?.mainRootDomId || "arraysubs-main-root";
  const targetElement = document.createElement("div");
  targetElement.id = rootElementId;
  wpbody.appendChild(targetElement);

  // Create React root
  const root = ReactDOM.createRoot(targetElement);

  root.render(
    <React.StrictMode>
      {window.arraySubs !== undefined ? (
        <Router>
          <div id="wpbody-content">
            <div className="wrap">
              <MainContent />
            </div>
          </div>
        </Router>
      ) : (
        <div id="wpbody-content">
          <div className="wrap">
            <MainAppLoadingState className="arraysubs-admin-loading--boot" />
          </div>
        </div>
      )}
    </React.StrictMode>,
  );
} else {
  console.error(__("Target element #wpbody not found.", "arraysubs"));
}
