import React from "react";
import ReactDOM from "react-dom/client";
import RetentionAnalyticsPage from "./pages/RetentionAnalytics/RetentionAnalyticsPage";
import "./scss/retention-analytics.scss";

const CONTAINER_ID = "arraysubs-retention-analytics-root";
const HIDDEN_ATTR = "data-arraysubs-retention-hidden";
const BODY_CLASS = "arraysubs-retention-analytics-page-body";

let reactRoot = null;

/**
 * Get the configured retention analytics path.
 */
function getRetentionPath() {
  return (
    window.arraySubsRetention?.pagePath || "/analytics/arraysubs-retention"
  );
}

/**
 * Read the current WC admin path from the URL.
 */
function getCurrentPath() {
  try {
    return new URL(window.location.href).searchParams.get("path") || "";
  } catch {
    return "";
  }
}

/**
 * Whether the current URL matches the retention analytics route.
 */
function isRetentionRoute() {
  return getCurrentPath() === getRetentionPath();
}

/**
 * Mount the retention analytics React app inside #root alongside WC's layout.
 */
function mount() {
  if (document.getElementById(CONTAINER_ID)) {
    return;
  }

  const wcLayout = document.querySelector("#root > .woocommerce-layout");

  if (!wcLayout) {
    waitForLayout(mount);
    return;
  }

  wcLayout.setAttribute(HIDDEN_ATTR, "");

  const container = document.createElement("div");
  container.id = CONTAINER_ID;
  wcLayout.parentElement.appendChild(container);

  reactRoot = ReactDOM.createRoot(container);
  reactRoot.render(
    <React.StrictMode>
      <RetentionAnalyticsPage />
    </React.StrictMode>,
  );
}

/**
 * Unmount the retention analytics React app and restore WC's layout.
 */
function unmount() {
  if (reactRoot) {
    reactRoot.unmount();
    reactRoot = null;
  }

  const container = document.getElementById(CONTAINER_ID);
  if (container) {
    container.remove();
  }

  const hidden = document.querySelector(`[${HIDDEN_ATTR}]`);
  if (hidden) {
    hidden.style.display = "";
    hidden.removeAttribute(HIDDEN_ATTR);
  }
}

/**
 * Wait for WC to render its layout inside #root, then call the callback.
 */
function waitForLayout(callback) {
  const root = document.getElementById("root");

  if (!root) {
    return;
  }

  const observer = new MutationObserver(() => {
    if (document.querySelector("#root > .woocommerce-layout")) {
      observer.disconnect();
      callback();
    }
  });

  observer.observe(root, { childList: true, subtree: true });

  setTimeout(() => observer.disconnect(), 8000);
}

/**
 * Check the current route and mount or unmount accordingly.
 */
function handleRouteChange() {
  console.log("Checking route for retention analytics...", isRetentionRoute());

  if (isRetentionRoute()) {
    document.body.classList.add(BODY_CLASS);
    mount();
  } else {
    document.body.classList.remove(BODY_CLASS);
    unmount();
  }
}

/**
 * Patch history.pushState / replaceState to emit route change events.
 */
function patchHistory() {
  if (window.__arraysubsRetentionSpaPatched) {
    return;
  }

  window.__arraysubsRetentionSpaPatched = true;

  const emit = () =>
    window.dispatchEvent(new Event("arraysubs:retention-routechange"));

  ["pushState", "replaceState"].forEach((method) => {
    const original = window.history[method];

    if (typeof original !== "function") {
      return;
    }

    window.history[method] = function patchedMethod(...args) {
      const result = original.apply(this, args);
      emit();
      return result;
    };
  });

  window.addEventListener("popstate", emit);
}

// Bootstrap.
patchHistory();
window.addEventListener("arraysubs:retention-routechange", handleRouteChange);

if (document.readyState === "loading") {
  document.addEventListener("DOMContentLoaded", handleRouteChange);
} else {
  handleRouteChange();
}
