import { clsx } from 'clsx';
import { useIntl } from 'react-intl';
import { Breakpoint } from '@transferwise/neptune-tokens';

import { Layout } from '../common';
import { CloseButton } from '../common/closeButton';
import FlowHeader from '../common/flowHeader/FlowHeader';
import Logo from '../logo';
import Stepper, { type Step } from '../stepper/Stepper';
import Container from '../container';

import { useScreenSize } from '../common/hooks/useScreenSize';
import messages from './FlowNavigation.messages';
import AnimatedLabel from './animatedLabel';
import IconButton from '../iconButton';
import { ArrowLeft } from '@transferwise/icons';

const defaultLogo = <Logo />;

export interface FlowNavigationProps {
  /** @default 0 */
  activeStep?: number;
  avatar?: React.ReactNode;
  /** @default <Logo /> */
  logo?: React.ReactNode;
  /** @default false */
  done?: boolean;
  /** Called when the close button is clicked. If not provided the close button won't show */
  onClose?: () => void;
  /** Called when the back button is clicked. If not provided the back button won't show. The back button only shows on small screens */
  onGoBack?: () => void;
  /** Steps to be displayed in stepper. If not provided, the stepper won't show. */
  steps?: readonly Step[];
  /**
   * When true, renders in composable mode using a fluid Container.
   * This allows the FlowNavigation to be used within custom layout containers.
   * @default false
   */
  composable?: boolean;
  /**
   * Controls whether the bottom border is displayed.
   * Only applies to the composable variant. Non-composable variant always uses the done state.
   * @default true
   */
  showBottomBorder?: boolean;
}

const FlowNavigation = ({
  activeStep = 0,
  avatar,
  logo = defaultLogo,
  done = false,
  onClose,
  onGoBack,
  steps,
  composable = false,
  showBottomBorder = true,
}: FlowNavigationProps) => {
  const intl = useIntl();
  const screenSm = useScreenSize(Breakpoint.SMALL);
  const screenLg = useScreenSize(Breakpoint.LARGE);

  const closeButton = onClose != null && <CloseButton size="lg" onClick={onClose} />;

  const newAvatar = done ? null : avatar;
  const displayGoBack = onGoBack != null && activeStep > 0;

  const flowHeaderContent = (
    <FlowHeader
      className={clsx(
        'np-flow-navigation__content',
        !composable && 'p-x-3',
        screenSm == null
          ? 'np-flow-navigation--hidden'
          : {
              'np-flow-navigation--xs-max': !screenSm,
              // Size switches on parent container which may or may not have the same size as the window.
              'np-flow-navigation--sm': screenSm,
              'np-flow-navigation--lg': screenLg,
            },
      )}
      leftContent={
        <>
          {!screenSm && displayGoBack ? (
            <IconButton
              size={40}
              priority="tertiary"
              type="default"
              aria-label={intl.formatMessage(messages.back)}
              onClick={onGoBack}
            >
              <ArrowLeft />
            </IconButton>
          ) : (
            <div className="np-flow-header__left">{logo}</div>
          )}
          {!screenSm && !done && steps && steps.length > 0 && (
            <AnimatedLabel className="m-x-1" steps={steps} activeLabel={activeStep} />
          )}
        </>
      }
      rightContent={
        <div className="np-flow-header__right d-flex align-items-center justify-content-end order-2--lg">
          {newAvatar}
          {newAvatar && closeButton && <span className="m-x-1" />}
          {closeButton}
        </div>
      }
      bottomContent={
        !done && steps && steps.length > 0 ? (
          <Stepper
            activeStep={activeStep}
            steps={steps}
            className={clsx('np-flow-navigation__stepper')}
          />
        ) : null
      }
      layout={!screenLg ? Layout.VERTICAL : Layout.HORIZONTAL}
    />
  );

  if (composable) {
    return (
      <Container
        size="fluid"
        className={clsx('np-flow-navigation np-flow-navigation--composable', {
          'np-flow-navigation--border-bottom': showBottomBorder,
        })}
      >
        {flowHeaderContent}
      </Container>
    );
  }

  return (
    <div
      className={clsx('np-flow-navigation p-y-3', {
        'np-flow-navigation--border-bottom': !done,
      })}
    >
      {flowHeaderContent}
    </div>
  );
};

export default FlowNavigation;
