/**
 * TEAM: frontend_infra
 * @flow strict
 */

/* eslint-disable flexport/no-unused-aphrodite-styles */

import * as React from "react";
import {StyleSheet, css} from "aphrodite";
import Icon, {type IconNames} from "./Icon";
import IconButton from "./button/IconButton";
import latitudeColors, {type Color} from "./colors";

import Text from "./Text";

type CtaButtonAlignment = "under" | "right";

type Intent =
  | "default"
  | "default-light"
  | "warning"
  | "error-hollow"
  | "error";

type Props = {|
  /**
   * defines the visual style which conveys the level of importance / urgency
   * to the user
   */
  +intent?: Intent,
  /** the name of the icon to be displayed on the left of the banner */
  +iconName?: IconNames,
  /** the message that will appear at the center of the banner */
  +message: string | React.Element<typeof Text>,
  /** additional content to display in the banner below the message */
  +additionalContent?: React.Node,
  /**
   * The call to action button that will appear below the banner message.
   * This button should have intent "basic" and kind "blank"
   */
  +ctaButton?: React.Node,

  /**
   * The alignment of the CTA Button. Currently, right and under are supported. If alignment is not specified, the implied default alignment is "under."
   */
  +ctaButtonAlignment?: CtaButtonAlignment,

  /**
   * Called when the close button is pressed. If an onClose
   * isn't provided, the close button will not appear
   */
  +onClose?: () => void,
|};

/**
 * @category Data Display
 * @short Spans the entire width of its parent and displays a informing message
 * @brandStatus V2
 * @status Beta
 *
 * The banner component is used to provide feedback to the user such as when
 * an app update has occurred or when there are errors returned from the server.
 * Banners can also be used to display passive messages such as when times are
 * being displayed in a separate timezone or when the user is impersonating
 * a client.
 */
export default function Banner({
  intent = "default",
  iconName,
  message,
  additionalContent,
  ctaButton,
  ctaButtonAlignment = "under",
  onClose,
}: Props): React.Element<"div"> {
  const messageContent = message === "string" ? <Text>message</Text> : message;

  const iconColor = getIconColor(intent);

  const ctaButtonContent =
    ctaButton != null ? (
      <div
        className={
          ctaButtonAlignment === "under"
            ? css(styles.ctaButtonUnderWrapper)
            : null
        }
      >
        {ctaButton}
      </div>
    ) : null;

  const additionalContentNode =
    additionalContent != null ? (
      <div className={css(styles.additionalContentWrapper)}>
        {additionalContent}
      </div>
    ) : null;

  let closeNode = null;
  if (onClose) {
    closeNode = (
      <div className={css(intent === "error" && styles.closeWrapperError)}>
        <IconButton
          iconName="cancel"
          onClick={onClose}
          kind="blank"
          intent="none"
          type="button"
          size="l"
          height={{type: "customDontUse", height: 20}}
        />
      </div>
    );
  }

  return (
    <div
      className={css(
        styles.container,
        styles.bannerPadding,
        styles[intent],
        additionalContent != null && styles.closeButtonWrapper
      )}
    >
      <div className={css(styles.contentWrapper)}>
        <div
          className={
            ctaButtonAlignment === "right"
              ? css(styles.iconWrapperRightAligned)
              : css(styles.iconWrapper)
          }
        >
          {iconName && <Icon size="s" iconName={iconName} color={iconColor} />}
        </div>
        <div
          className={
            ctaButtonAlignment === "right"
              ? css(styles.content)
              : css(styles.contentRightAligned)
          }
        >
          {messageContent}
          {additionalContentNode}
          {ctaButtonAlignment === "under" ? ctaButtonContent : null}
        </div>
        {ctaButtonAlignment === "right" ? ctaButtonContent : null}
      </div>
      {closeNode}
    </div>
  );
}

const getIconColor = (intent: Intent): Color => {
  if (intent === "error") {
    return "white";
  } else if (intent === "error-hollow") {
    return "red40";
  } else if (intent === "warning") {
    return "orange30";
  }
  return "grey60";
};

const styles = StyleSheet.create({
  container: {
    display: "flex",
    flexDirection: "row",
    borderRadius: "0",
    alignItems: "flex-start",
  },
  closeButtonWrapper: {
    alignItems: "baseline",
  },
  contentWrapper: {
    display: "flex",
    flexDirection: "row",
    flex: 1,
  },
  iconWrapper: {
    marginRight: "20px",
  },
  iconWrapperRightAligned: {
    marginRight: "20px",
    alignSelf: "center",
  },
  closeWrapperError: {
    ":nth-child(1n) > button > span > svg": {
      fill: latitudeColors.white,
      animationDuration: "0",
    },
    ":nth-child(1n) > button > span > svg :hover": {
      fill: latitudeColors.white,
    },
  },
  content: {
    display: "flex",
    flexDirection: "column",
    flex: "1",
    marginRight: "20px",
    lineHeight: "20px",
  },
  contentRightAligned: {
    display: "flex",
    flexDirection: "column",
    flex: "1",
    marginRight: "20px",
    lineHeight: "20px",
    alignSelf: "center",
  },
  additionalContentWrapper: {
    marginTop: "8px",
  },
  ctaButtonUnderWrapper: {
    paddingTop: "8px",
  },
  bannerPadding: {
    padding: "18px",
  },
  default: {
    border: `2px solid ${latitudeColors.grey20}`,
    background: latitudeColors.grey10,
  },
  "default-light": {
    border: `2px solid ${latitudeColors.grey20}`,
    background: latitudeColors.white,
  },
  warning: {
    border: `2px solid ${latitudeColors.grey30}`,
    background: latitudeColors.white,
  },
  "error-hollow": {
    border: `2px solid ${latitudeColors.red40}`,
    background: latitudeColors.white,
  },
  error: {
    background: latitudeColors.red40,
    color: latitudeColors.white,
  },
});
