import React, { StrictMode, useState, useEffect, useMemo } from 'react';
import * as ReactDOM from 'react-dom';
import { createRoot } from 'react-dom/client';
import { Provider, useSelector } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import './index.css';
import App from './App.js';
import { worker } from './mocks/browser.js';

const EXTENSION_ID = 'canvas-conductor-extension';

function Portal() {
  const [portalRoot, setPortalRoot] = useState<HTMLElement | null>(null);
  // Get the currently active extension from the Canvas React app's Redux store.
  const storeExtension = useSelector(
    (state: {
      extensions?: {
        activeExtension?: { id: string };
      };
    }) => state?.extensions?.activeExtension,
  );
  const activeExtension = useMemo(
    () => (import.meta.env.DEV ? { id: EXTENSION_ID } : storeExtension),
    [storeExtension],
  );

  useEffect(() => {
    if (activeExtension?.id) {
      // Wait for a tick here to ensure the div in the extension modal has been rendered so we can portal
      // our extension into it.
      requestAnimationFrame(() => {
        const targetDiv = document.querySelector<HTMLElement>(
          `#extensionPortalContainer.canvas-extension-${activeExtension.id}`,
        );
        if (targetDiv) {
          setPortalRoot(targetDiv);
        }
      });
    }
  }, [activeExtension]);

  // We don't want to render anything if the Extension is not active in the Canvas app.
  if (activeExtension?.id !== EXTENSION_ID || !portalRoot) {
    return null;
  }

  return ReactDOM.createPortal(
    <StrictMode>
      <App />
    </StrictMode>,
    portalRoot,
  );
}

// The Canvas store is available in Drupal settings, making it possible to add it
// to this App via a <Provider>, giving us access to its data and actions.
const store =
  window?.drupalSettings?.canvas?.store ??
  configureStore({
    reducer: (state = {}) => state,
  });

async function enableMocking() {
  if (import.meta.env.DEV) {
    // `worker.start()` returns a Promise that resolves
    // once the Service Worker is up and ready to intercept requests.
    return worker.start();
  }
  return;
}

const container = document.createElement('div');
container.id = EXTENSION_ID;

document.body.append(container);
const root = createRoot(container);

enableMocking().then(() => {
  root.render(
    <Provider store={store}>
      <Portal />
    </Provider>,
  );
});
