import { useEffect, useMemo, useRef } from "react";

import storeConfig from "discovery.config";

import { useRouter } from "next/router";

import { useLocalization } from "../../shared/localization/LocalizationContext";
import { isDevelopment } from "../../shared/utils/environment";

const B2B_AGENT_URL = isDevelopment()
  ? "http://localhost:3001/app/order-entry-agent"
  : "https://order-entry-agent.vercel.app/app/order-entry-agent";

interface OrderEntryLayoutProps {
  vtexIdclientAutCookie: string;
  vtexIdclientAutCookie_client: string;
  account: string;
  locale?: string;
  customerId?: string;
  userId?: string;
  session?: string;
  segment?: string;
}

const containerStyle: React.CSSProperties = {
  display: "flex",
  flexDirection: "column",
  width: "100%",
  height: "100vh",
  overflow: "hidden",
};

const iframeStyle: React.CSSProperties = {
  flex: 1,
  width: "100%",
  height: "100%",
  border: "none",
};

export const OrderEntryLayout = ({
  vtexIdclientAutCookie,
  vtexIdclientAutCookie_client,
  account,
  locale,
  segment,
  session,
  customerId,
  userId,
}: OrderEntryLayoutProps) => {
  const { t } = useLocalization();
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const router = useRouter();

  const agentOrigin = useMemo(() => new URL(B2B_AGENT_URL).origin, []);

  useEffect(() => {
    function postAuthToIframe() {
      const targetWindow = iframeRef.current?.contentWindow;
      const quoteId = router.query.quoteId ?? "";

      if (!targetWindow) return;

      // We send only the token (not the full Cookie header) to reduce exposure.
      targetWindow.postMessage(
        {
          type: "AUTH_TOKEN_UPDATE",
          vtexIdclientAutCookie,
          vtexIdclientAutCookie_client,
          segment,
          session,
          account,
          locale,
          customerId,
          userId,
          quoteId,
        },
        agentOrigin
      );
    }

    function primeOrderFormCookie(orderFormId: string) {
      const secureSubdomain = storeConfig?.secureSubdomain;
      if (!secureSubdomain) return Promise.resolve(false);

      const url = new URL(
        `/api/checkout/pub/orderForm/${encodeURIComponent(
          orderFormId
        )}?refreshOutdatedData=true`,
        secureSubdomain
      );

      return fetch(url.toString(), {
        method: "GET",
        credentials: "include",
        cache: "no-store",
      }).then((res) => res.ok);
    }

    function onMessage(event: MessageEvent) {
      // Only accept messages coming from the iframe's origin.
      if (event.origin !== agentOrigin) return;

      // Ensure the message is from the iframe window we embedded.
      if (event.source !== iframeRef.current?.contentWindow) return;

      // Handshake: child tells it is ready; parent responds by sending auth.
      if (event.data?.type === "B2B_AGENT_READY") {
        postAuthToIframe();
      }

      if (event.data?.type === "B2B_GO_TO_CHECKOUT") {
        const orderFormId = event.data?.orderFormId;
        const secureSubdomain = storeConfig?.secureSubdomain;
        if (
          !secureSubdomain ||
          typeof orderFormId !== "string" ||
          !orderFormId
        ) {
          return;
        }
        primeOrderFormCookie(orderFormId)
          .then((ok) => {
            if (!ok) return;
            window.location.assign(`${secureSubdomain}/checkout/payment`);
          })
          .catch((error) => {
            console.warn(
              "Failed to prime orderForm cookie before checkout",
              error
            );
          });
      }
    }

    window.addEventListener("message", onMessage);

    // Fallback: try once after iframe load in case READY was missed.
    const iframe = iframeRef.current;
    let loadFallbackId: ReturnType<typeof setTimeout>;
    const onLoad = () => {
      // Small delay to allow the iframe app to attach its message listener.
      loadFallbackId = setTimeout(() => {
        postAuthToIframe();
      }, 150);
    };

    if (iframe) iframe.addEventListener("load", onLoad);

    // If token changes while iframe is already up, proactively resend.
    // This is safe because we still constrain by agentOrigin.
    let resendId: ReturnType<typeof setTimeout>;
    if (iframeRef.current?.contentWindow && vtexIdclientAutCookie) {
      // Delay to avoid racing the initial mount.
      resendId = setTimeout(() => {
        postAuthToIframe();
      }, 1);
    }

    return () => {
      window.removeEventListener("message", onMessage);
      if (iframe) iframe.removeEventListener("load", onLoad);
      clearTimeout(loadFallbackId);
      clearTimeout(resendId);
    };
  }, [
    vtexIdclientAutCookie,
    vtexIdclientAutCookie_client,
    segment,
    session,
    account,
    locale,
    customerId,
    userId,
    agentOrigin,
  ]);

  return (
    <section style={containerStyle} data-fs-bp-b2b-agent>
      <iframe
        ref={iframeRef}
        style={iframeStyle}
        data-fs-bp-b2b-agent-iframe
        src={B2B_AGENT_URL}
        title={t("orderEntry.titles.orderEntryAgent")}
        allow="clipboard-read; clipboard-write"
        sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals"
      />
    </section>
  );
};
