import { ComponentRef, createComponent, Type } from "@angular/core";
import { createApplication } from "@angular/platform-browser";
import React, { useEffect, useRef, useState } from "react";

type AnyComponentRef = ComponentRef<unknown>;

export type ReactifyProps = {
  component: Type<unknown>;
  inputs?: Record<string, unknown>;
};

export const Reactify: React.FunctionComponent<ReactifyProps> = (props) => {
  const hostElementRef = useRef<HTMLDivElement>(null);
  const [componentRef, setComponentRef] = useState<AnyComponentRef | null>(
    null
  );

  const renderComponent = async () => {
    const appRef = await createApplication();
    return createComponent(props.component, {
      environmentInjector: appRef.injector,
      hostElement: hostElementRef.current!,
    });
  };

  const changeInputs = () => {
    if (componentRef) {
      for (const [key, value] of Object.entries(props.inputs || {})) {
        componentRef.setInput(key, value);
      }
      componentRef.changeDetectorRef.detectChanges();
    }
  };

  useEffect(() => {
    renderComponent().then(setComponentRef);
  }, [hostElementRef, props.component]);

  useEffect(() => {
    changeInputs();
  }, [componentRef, props.inputs]);

  return <div ref={hostElementRef} />;
};
