import {
  ConfigStatusResponseCode,
  IdentityProvider,
  TokenResponse,
  TokenResponseCode,
} from '@axinom/mosaic-id-utils';
import { SvgElement } from '@axinom/mosaic-ui';
import React, { ReactElement, useEffect, useState } from 'react';
import { IdServiceConfiguration } from '../../IdentityServiceClient/IdentityServiceClient';
import { AccountInactiveError } from '../AccountInactiveError/AccountInactiveError';
import { CompletePasswordReset } from '../CompletePasswordReset/CompletePasswordReset';
import { ConfirmSignUp } from '../CompleteUserSignUp/ConfirmSignUp';
import { ConfigurationInvalidError } from '../ConfigurationInvalidError/ConfigurationInvalidError';
import { EnvironmentInactiveError } from '../EnvironmentInactiveError/EnvironmentInactiveError';
import { useIdentityService } from '../IdentityServiceProvider/IdentityServiceProvider';
import { Login } from '../Login/Login';
import { TenantInactiveError } from '../TenantInactiveError/TenantInactiveError';
import { BrandingOptions } from '../common/BrandingOptions';
import classes from './EnsureAuthentication.module.scss';
import { EnvironmentInformationBox } from './EnvironmentInformationBox/EnvironmentInformationBox';

export interface EnsureAuthenticationProps {
  brandingOptions?: BrandingOptions;
}

const Loading: React.FC = () => (
  <div className={classes.loading}>
    <div className={classes.loadingWrapper}>
      <SvgElement viewBox="0 0 125 125" aria-label="Loading">
        <g className={classes.overlay}>
          <path
            fill="#00467d"
            d="M31.3,18.5c-12.6,6.6-19,9.9-22.5,15.7-3.5,5.8-3.5,12.9-3.5,27.2v1.5c0,14.3,0,21.4,3.5,27.2,3.5,5.8,9.8,9.1,22.5,15.7l9.1,4.8c11,5.7,16.5,8.6,22.4,8.6s11.4-2.9,22.4-8.6l9.1-4.8c12.6-6.6,19-9.9,22.5-15.7,3.5-5.8,3.5-12.9,3.5-27.2v-1.5c0-14.3,0-21.4-3.5-27.2-3.5-5.8-9.8-9.1-22.5-15.7l-9.1-4.8c-11-5.7-16.5-8.6-22.4-8.6s-11.4,2.9-22.4,8.6l-9.1,4.8Z"
          />
          <path
            fill="#FFFFFF"
            d="M62.8,5.1c5.9,0,11.4,2.9,22.4,8.6l9.1,4.8c12.6,6.6,19,9.9,22.5,15.7,3.5,5.8,3.5,12.9,3.5,27.2v1.5c0,14.3,0,21.4-3.5,27.2-3.5,5.8-9.8,9.1-22.5,15.7l-9.1,4.8c-11,5.7-16.5,8.6-22.4,8.6s-11.4-2.9-22.4-8.6l-9.1-4.8c-12.6-6.6-19-9.9-22.5-15.7-3.5-5.8-3.5-12.9-3.5-27.2v-1.5c0-14.3,0-21.4,3.5-27.2,3.5-5.8,9.8-9.1,22.5-15.7l9.1-4.8c11-5.7,16.5-8.6,22.4-8.6M62.8,2.1c-6.7,0-12.4,3-23.8,9l-9.1,4.8c-13.1,6.9-19.7,10.3-23.6,16.8-3.9,6.5-3.9,13.9-3.9,28.7v1.5c0,14.8,0,22.2,3.9,28.7,3.9,6.5,10.5,9.9,23.6,16.8l9.1,4.8c11.4,6,17.1,9,23.8,9s12.4-3,23.8-9l9.1-4.8c13.1-6.9,19.7-10.3,23.6-16.8,3.9-6.5,3.9-13.9,3.9-28.7v-1.5c0-14.8,0-22.2-3.9-28.7-3.9-6.5-10.5-9.9-23.6-16.8l-9.1-4.8c-11.4-6-17.1-9-23.8-9h0Z"
          />
          <path
            fill="#28aae1"
            d="M28.5,41.3c.7-3.7,4.2-6.1,7.9-5.4,3.7.7,6.1,4.2,5.4,7.9l-6.8,36.7c-.7,3.7-4.2,6.1-7.9,5.4-3.7-.7-6.1-4.2-5.4-7.9l6.8-36.7Z"
          />
          <path
            fill="#ffc81e"
            d="M31.1,37.1c3-2.3,7.2-1.7,9.5,1.3l27.8,36.7c2.3,3,1.7,7.2-1.3,9.5-3,2.3-7.2,1.7-9.5-1.3l-27.8-36.7c-2.3-3-1.7-7.2,1.3-9.5Z"
          />
          <path
            fill="#28aae1"
            d="M89,35.8c3.7-.7,7.2,1.8,7.9,5.4l6.8,36.7c.7,3.7-1.8,7.2-5.4,7.9-3.7.7-7.2-1.8-7.9-5.4l-6.8-36.7c-.7-3.7,1.8-7.2,5.4-7.9Z"
          />
          <path
            fill="#f06e55"
            d="M84.7,38.5c2.2-3,6.5-3.6,9.5-1.4,3,2.2,3.6,6.5,1.4,9.5l-27.2,36.7c-2.2,3-6.5,3.6-9.5,1.4-3-2.2-3.6-6.5-1.4-9.5l27.2-36.7Z"
          />
        </g>
      </SvgElement>
      <span className={classes.loadingMessage}>
        Authenticating
        <br />
        Please wait
      </span>
    </div>
  </div>
);

/**
 * Ensures that the user is authenticated with a valid account.
 * If not, the login form or an error is shown.
 *
 * The content passed as children will be rendered only if authentication is successful.
 * @props brandingOptions: Includes companyLogo: image, background: colorCode|image to customize the login view
 */
export const EnsureAuthentication: React.FC<EnsureAuthenticationProps> = ({
  children,
  brandingOptions,
}) => {
  const { getToken, getConfiguration, addTokenChangedHandler } =
    useIdentityService();

  const [loading, setLoading] = useState(true);

  const [configuration, setConfiguration] =
    useState<IdServiceConfiguration | null>();

  const [tokenResponse, setTokenResponse] = useState<TokenResponse | null>(
    null,
  );

  const [isProbableApiMismatch, setIsProbableApiMismatch] = useState(false);

  useEffect(() => {
    const initialize = async (): Promise<void> => {
      addTokenChangedHandler((token) => {
        // React on token changes (e.g. logout)
        setTokenResponse(token);
      });
      try {
        const idServiceConfig = await getConfiguration();
        setConfiguration(idServiceConfig);
        if (idServiceConfig.status === 'SUCCESS') {
          setTokenResponse(await getToken());
        }
      } catch (error) {
        // eslint-disable-next-line no-console
        console.error(error);
        setIsProbableApiMismatch(true);
      } finally {
        setLoading(false);
      }
    };

    initialize();
  }, [addTokenChangedHandler, getConfiguration, getToken]);

  let content: ReactElement;
  let showEnvironmentInfo = window.location.hostname === 'localhost';
  const isResetPasswordFlow =
    window.location.pathname.startsWith('/reset-password');
  const isConfirmSignUp =
    window.location.pathname.startsWith('/confirm-signup');

  if (loading) {
    showEnvironmentInfo = false;
    content = <Loading />;
  } else if (
    configuration?.status === ConfigStatusResponseCode.TENANT_NOT_ACTIVE
  ) {
    content = <TenantInactiveError />;
  } else if (
    configuration?.status === ConfigStatusResponseCode.ENVIRONMENT_NOT_ACTIVE
  ) {
    content = <EnvironmentInactiveError />;
  } else if (
    configuration?.status !== ConfigStatusResponseCode.SUCCESS ||
    (configuration?.status === ConfigStatusResponseCode.SUCCESS &&
      !configuration?.providers.find((i) => i.enabled))
  ) {
    content = (
      <ConfigurationInvalidError
        isProbableApiMismatch={isProbableApiMismatch}
      />
    );
  } else if (isResetPasswordFlow) {
    content = <CompletePasswordReset brandingOptions={brandingOptions} />;
  } else if (isConfirmSignUp) {
    content = <ConfirmSignUp brandingOptions={brandingOptions} />;
  } else if (tokenResponse?.code === TokenResponseCode.ACCOUNT_NOT_ACTIVE) {
    content = <AccountInactiveError brandingOptions={brandingOptions} />;
  } else if (!tokenResponse?.user) {
    content = (
      <Login
        providers={configuration.providers.filter((provider) => {
          // TODO: We filter out the Axinom provider when running on localhost until we have a proper solution for it (TASK ID: 45803)
          if (
            provider.idpId === IdentityProvider.AXINOM &&
            window.location.hostname === 'localhost'
          ) {
            return false;
          } else {
            return true;
          }
        })}
        brandingOptions={brandingOptions}
      />
    );
  } else {
    showEnvironmentInfo = false;
    content = <>{children}</>;
  }
  return (
    <>
      {content}
      {showEnvironmentInfo && <EnvironmentInformationBox {...configuration} />}
    </>
  );
};
