import React, { ReactNode } from 'react';
import ReactDOM from 'react-dom';
import { SdkConfig, initSdk } from '@hiro-ui/sdk';
import HiroGraphOrm from '@hiro-graph/orm';

import { HiroAppRoot } from '../components';
import { Orm } from '../contexts';
import { getMappings } from '../helpers';

const HiroGraphMappings = getMappings();

interface HiroAppParams {
  config?: SdkConfig;
}

const getConfigFromEnv = () => {
  const graphUrl = process.env.REACT_APP_GRAPH_URL;
  const authUrl =
    process.env.REACT_APP_AUTH_URL || `${graphUrl}/api/6/auth/ui/`;
  const redirectUrl =
    process.env.REACT_APP_REDIRECT_URL || `${graphUrl}/api/6/auth/ui-redirect`;
  const clientId = process.env.REACT_APP_CLIENT_ID;

  const config = {
    graphUrl,
    authUrl,
    clientId,
    redirectUrl,
  };

  if (Object.values(config).every(Boolean)) {
    return config;
  }

  return undefined;
};

export class HiroApp {
  config?: SdkConfig;

  constructor({ config }: HiroAppParams = {}) {
    this.config = config;

    if (!config) {
      this.config = getConfigFromEnv();
    }
  }

  setup = async () => {
    const {
      ready,
      config: { token, graphUrl },
    } = await initSdk(this.config);

    let orm: Orm | undefined;

    if (token && graphUrl) {
      orm = new HiroGraphOrm(
        {
          endpoint: graphUrl,
          token,
        },
        HiroGraphMappings,
      ) as Orm;
    }

    return { orm, ready };
  };

  render = async (children: ReactNode, target: HTMLElement | null) => {
    const { orm, ready } = await this.setup();

    ReactDOM.render(
      <HiroAppRoot orm={orm}>{children}</HiroAppRoot>,
      target,
      ready,
    );
  };
}
