import { jsx } from "react/jsx-runtime";
import { memo, useLayoutEffect, useRef, useCallback } from "react";
import styled from "styled-components";
import { useDispatch } from "react-redux";
import { buildLogRocketQueryParams } from "@elliemae/pui-logrocket";
import {
  MicroAppManager
} from "../utils/micro-frontend/types.js";
import { getAppBridge } from "../utils/micro-frontend/app-bridge.js";
import { getSSFHost } from "../utils/micro-frontend/ssf-host.js";
import { waitMessage } from "../data/wait-message/actions.js";
import {
  getLogger,
  getMicroFrontEndAppConfig
} from "../utils/micro-frontend/index.js";
const Div = styled.div`
  display: flex;
  width: 100%;
  height: 100%;
  flex-direction: column;
  overflow: hidden;
`;
const useAppRenderer = (props) => {
  const {
    id,
    history,
    homeRoute,
    initialRoute,
    onLoadComplete,
    onUnloadComplete,
    containerId,
    ssfAppOptions = {},
    disableWaitMessage = false
  } = props;
  const dispatch = useDispatch();
  const getConfig = useCallback(
    () => getMicroFrontEndAppConfig({
      id
    }),
    [id]
  );
  useLayoutEffect(() => {
    let isMounted = true;
    let appBridge = null;
    let ssfHost = null;
    let unloadInProgress = Promise.resolve();
    let instanceId = null;
    (async () => {
      await unloadInProgress;
      if (!disableWaitMessage) {
        dispatch(waitMessage.open());
      }
      try {
        const {
          microappManager = MicroAppManager.APPSDK,
          hostUrl,
          title,
          name,
          ssfAppOptions: configSsfAppOptions = {}
        } = getConfig();
        const mergedSsfAppOptions = {
          ...configSsfAppOptions,
          ...ssfAppOptions
        };
        if (microappManager === MicroAppManager.SSF) {
          ssfHost = getSSFHost();
          if (!ssfHost)
            throw new Error(`Failed to load ${id}, SSFHost not initialized`);
          if (isMounted) {
            const { searchParams, ...guestOptions } = mergedSsfAppOptions;
            const guest = ssfHost.loadGuest({
              id,
              url: hostUrl,
              title: title ?? name,
              targetElement: document.getElementById(containerId),
              searchParams,
              onLoad: onLoadComplete,
              options: guestOptions
            });
            instanceId = guest.id;
          }
        } else {
          appBridge = await getAppBridge();
          if (!appBridge)
            throw new Error(`Failed to load ${id}, AppBridge not initialized`);
          if (isMounted) {
            instanceId = await appBridge.openApp({
              id,
              frameOptions: {
                containerId,
                queryParams: buildLogRocketQueryParams()
              },
              history,
              homeRoute,
              initialRoute
            });
            setTimeout(() => {
              try {
                onLoadComplete?.(instanceId);
              } catch (ex) {
              }
            }, 0);
          }
        }
      } catch (ex) {
        getLogger().error({
          message: `Failed to load ${id}`,
          exception: ex
        });
        isMounted = false;
        if (appBridge && instanceId)
          unloadInProgress = appBridge.closeApp(instanceId);
        if (ssfHost && instanceId)
          unloadInProgress = Promise.resolve(ssfHost.unloadGuest(instanceId));
        throw ex;
      } finally {
        if (!disableWaitMessage) {
          dispatch(waitMessage.close());
        }
      }
    })();
    return () => {
      isMounted = false;
      if (ssfHost) {
        unloadInProgress = Promise.resolve(ssfHost.unloadGuest(instanceId));
      } else if (appBridge) {
        unloadInProgress = appBridge.closeApp(instanceId);
      }
      unloadInProgress.then(() => {
        instanceId = null;
        setTimeout(() => {
          try {
            onUnloadComplete?.();
          } catch (ex) {
          }
        }, 0);
      }).catch(() => {
      });
    };
  }, [
    containerId,
    dispatch,
    history,
    homeRoute,
    initialRoute,
    id,
    onLoadComplete,
    onUnloadComplete,
    getConfig,
    ssfAppOptions,
    disableWaitMessage
  ]);
};
const GuestMicroApp = memo(
  (props) => {
    const containerId = useRef(crypto.randomUUID());
    useAppRenderer({ ...props, containerId: containerId.current });
    return /* @__PURE__ */ jsx(Div, { id: containerId.current });
  }
);
export {
  GuestMicroApp
};
