import { makeStyles } from "@material-ui/core/styles";
import Typography from "@material-ui/core/Typography";
import Form from "@saleor/components/Form";
import Hr from "@saleor/components/Hr";
import Skeleton from "@saleor/components/Skeleton";
import {
  Timeline,
  TimelineAddNote,
  TimelineEvent,
  TimelineEventProps,
  TimelineNote
} from "@saleor/components/Timeline";
import { TitleElement } from "@saleor/components/Timeline/TimelineEventHeader";
import { OrderDetails_order_events } from "@saleor/orders/types/OrderDetails";
import { orderUrl } from "@saleor/orders/urls";
import {
  OrderEventsEmailsEnum,
  OrderEventsEnum
} from "@saleor/types/globalTypes";
import React from "react";
import { defineMessages } from "react-intl";
import { FormattedMessage, IntlShape, useIntl } from "react-intl";

import ExtendedTimelineEvent from "./ExtendedTimelineEvent";
import { getEventSecondaryTitle, isTimelineEventOfType } from "./utils";

export const getEventMessage = (
  event: OrderDetails_order_events,
  intl: IntlShape
) => {
  switch (event.type) {
    case OrderEventsEnum.CANCELED:
      return intl.formatMessage({
        defaultMessage: "Order was cancelled",
        description: "order history message"
      });
    case OrderEventsEnum.ADDED_PRODUCTS:
      return intl.formatMessage({
        defaultMessage: "Products were added to an order",
        description: "order history message"
      });
    case OrderEventsEnum.DRAFT_CREATED:
      return intl.formatMessage({
        defaultMessage: "Draft order was created",
        description: "order history message"
      });
    case OrderEventsEnum.REMOVED_PRODUCTS:
      return intl.formatMessage({
        defaultMessage: "Products were deleted from an order",
        description: "order history message"
      });
    case OrderEventsEnum.EMAIL_SENT:
      switch (event.emailType) {
        case OrderEventsEmailsEnum.DIGITAL_LINKS:
          return intl.formatMessage({
            defaultMessage: "Links to the order's digital goods were sent",
            description: "order history message"
          });
        case OrderEventsEmailsEnum.FULFILLMENT_CONFIRMATION:
          return intl.formatMessage({
            defaultMessage: "Fulfillment confirmation was sent to customer",
            description: "order history message"
          });
        case OrderEventsEmailsEnum.ORDER_CONFIRMATION:
          return intl.formatMessage({
            defaultMessage: "Order confirmation was sent to customer",
            description: "order history message"
          });
        case OrderEventsEmailsEnum.PAYMENT_CONFIRMATION:
          return intl.formatMessage({
            defaultMessage: "Payment confirmation was sent to customer",
            description: "order history message"
          });
        case OrderEventsEmailsEnum.SHIPPING_CONFIRMATION:
          return intl.formatMessage({
            defaultMessage: "Shipping details was sent to customer",
            description: "order history message"
          });
        case OrderEventsEmailsEnum.TRACKING_UPDATED:
          return intl.formatMessage({
            defaultMessage: "Shipping tracking number was sent to customer",
            description: "order history message"
          });
        case OrderEventsEmailsEnum.ORDER_CANCEL:
          return intl.formatMessage({
            defaultMessage: "Order cancel information was sent to customer",
            description: "order history message"
          });
        case OrderEventsEmailsEnum.ORDER_REFUND:
          return intl.formatMessage({
            defaultMessage: "Order refund information was sent to customer",
            description: "order history message"
          });
      }
    case OrderEventsEnum.FULFILLMENT_CANCELED:
      return intl.formatMessage({
        defaultMessage: "Fulfillment was cancelled",
        description: "order history message"
      });
    case OrderEventsEnum.INVOICE_REQUESTED:
      return intl.formatMessage(
        {
          defaultMessage: "Invoice was requested by {requestedBy}",
          description: "order history message"
        },
        {
          requestedBy: event.user ? event.user.email : null
        }
      );
    case OrderEventsEnum.INVOICE_GENERATED:
      return intl.formatMessage(
        {
          defaultMessage:
            "Invoice no. {invoiceNumber} was generated by {generatedBy}",
          description: "order history message"
        },
        {
          generatedBy: event.user ? event.user.email : null,
          invoiceNumber: event.invoiceNumber
        }
      );
    case OrderEventsEnum.INVOICE_UPDATED:
      return intl.formatMessage(
        {
          defaultMessage: "Invoice no. {invoiceNumber} was updated",
          description: "order history message"
        },
        {
          invoiceNumber: event.invoiceNumber
        }
      );
    case OrderEventsEnum.INVOICE_SENT:
      return intl.formatMessage(
        {
          defaultMessage: "Invoice was sent to customer by {sentBy}",
          description: "order history message"
        },
        {
          sentBy: event.user ? event.user.email : null
        }
      );
    case OrderEventsEnum.FULFILLMENT_FULFILLED_ITEMS:
      return intl.formatMessage(
        {
          defaultMessage: "Fulfilled {quantity} items",
          description: "order history message"
        },
        {
          quantity: event.quantity
        }
      );
    case OrderEventsEnum.FULFILLMENT_REFUNDED:
      return intl.formatMessage(
        {
          defaultMessage: "Order was refunded by {refundedBy}",
          description: "order history message"
        },
        {
          refundedBy: event.user ? event.user.email : null
        }
      );
    case OrderEventsEnum.FULFILLMENT_RESTOCKED_ITEMS:
      return intl.formatMessage(
        {
          defaultMessage: "Restocked {quantity} items",
          description: "order history message"
        },
        {
          quantity: event.quantity
        }
      );
    case OrderEventsEnum.NOTE_ADDED:
      return intl.formatMessage({
        defaultMessage: "Note was added to the order",
        description: "order history message"
      });
    case OrderEventsEnum.ORDER_FULLY_PAID:
      return intl.formatMessage({
        defaultMessage: "Order was fully paid",
        description: "order history message"
      });
    case OrderEventsEnum.ORDER_MARKED_AS_PAID:
      return intl.formatMessage({
        defaultMessage: "Order was marked as paid",
        description: "order history message"
      });
    case OrderEventsEnum.OTHER:
      return event.message;
    case OrderEventsEnum.OVERSOLD_ITEMS:
      return intl.formatMessage(
        {
          defaultMessage: "Oversold {quantity} items",
          description: "order history message"
        },
        {
          quantity: event.quantity
        }
      );
    case OrderEventsEnum.PAYMENT_CAPTURED:
      return intl.formatMessage({
        defaultMessage: "Payment was captured",
        description: "order history message"
      });
    case OrderEventsEnum.PAYMENT_FAILED:
      return intl.formatMessage({
        defaultMessage: "Payment failed",
        description: "order history message"
      });
    case OrderEventsEnum.PAYMENT_REFUNDED:
      return intl.formatMessage({
        defaultMessage: "Payment was refunded",
        description: "order history message"
      });
    case OrderEventsEnum.PAYMENT_VOIDED:
      return intl.formatMessage({
        defaultMessage: "Payment was voided",
        description: "order history message"
      });
    case OrderEventsEnum.PLACED:
      return intl.formatMessage({
        defaultMessage: "Order was placed",
        description: "order history message"
      });
    case OrderEventsEnum.PLACED_FROM_DRAFT:
      return intl.formatMessage({
        defaultMessage: "Order was created from draft",
        description: "order history message"
      });
    case OrderEventsEnum.TRACKING_UPDATED:
      return intl.formatMessage({
        defaultMessage: "Updated fulfillment group's tracking number",
        description: "order history message"
      });
    case OrderEventsEnum.UPDATED_ADDRESS:
      return intl.formatMessage({
        defaultMessage: "Order address was updated",
        description: "order history message"
      });
    case OrderEventsEnum.PAYMENT_AUTHORIZED:
      return intl.formatMessage({
        defaultMessage: "Payment was authorized",
        description: "order history message"
      });
    case OrderEventsEnum.CONFIRMED:
      return intl.formatMessage({
        defaultMessage: "Order was confirmed",
        description: "order history message"
      });
    case OrderEventsEnum.EXTERNAL_SERVICE_NOTIFICATION:
      return event.message;
  }
};

export const replacementCreatedMessages = defineMessages({
  description: {
    defaultMessage: "was created for replaced products",
    description: "replacement created order history message description"
  },
  draftNumber: {
    defaultMessage: "Draft #{orderNumber} ",
    description: "replacement created order history message draft number"
  }
});

export interface FormData {
  message: string;
}

const useStyles = makeStyles(
  theme => ({
    eventSubtitle: {
      marginTop: theme.spacing(1)
    },
    header: {
      fontWeight: 500,
      marginBottom: theme.spacing(1)
    },
    linesTableCell: {
      paddingRight: theme.spacing(3)
    },
    root: { marginTop: theme.spacing(4) },
    user: {
      marginBottom: theme.spacing(1)
    }
  }),
  { name: "OrderHistory" }
);

interface OrderHistoryProps {
  history: OrderDetails_order_events[];
  orderCurrency: string;
  onNoteAdd: (data: FormData) => void;
}

const OrderHistory: React.FC<OrderHistoryProps> = props => {
  const { history, orderCurrency, onNoteAdd } = props;
  const classes = useStyles(props);

  const intl = useIntl();

  const getTimelineEventTitleProps = (
    event: OrderDetails_order_events
  ): Partial<TimelineEventProps> => {
    const { type, message } = event;

    const title = isTimelineEventOfType("rawMessage", type)
      ? message
      : getEventMessage(event, intl);

    if (isTimelineEventOfType("secondaryTitle", type)) {
      return {
        secondaryTitle: intl.formatMessage(...getEventSecondaryTitle(event)),
        title
      };
    }

    return { title };
  };

  const getTitleElements = (
    event: OrderDetails_order_events
  ): TitleElement[] => {
    const { type, relatedOrder } = event;

    switch (type) {
      case OrderEventsEnum.ORDER_REPLACEMENT_CREATED: {
        return [
          {
            link: orderUrl(relatedOrder?.id),
            text: intl.formatMessage(replacementCreatedMessages.draftNumber, {
              orderNumber: relatedOrder?.number
            })
          },
          { text: intl.formatMessage(replacementCreatedMessages.description) }
        ];
      }
    }
  };

  return (
    <div className={classes.root}>
      <Typography className={classes.header} color="textSecondary">
        <FormattedMessage defaultMessage="Order History" />
      </Typography>
      <Hr />
      {history ? (
        <Timeline>
          <Form initial={{ message: "" }} onSubmit={onNoteAdd} resetOnSubmit>
            {({ change, data, reset, submit }) => (
              <TimelineAddNote
                message={data.message}
                reset={reset}
                onChange={change}
                onSubmit={submit}
              />
            )}
          </Form>
          {history
            .slice()
            .reverse()
            .map(event => {
              const { id, user, date, message, type } = event;

              if (isTimelineEventOfType("note", type)) {
                return (
                  <TimelineNote
                    date={date}
                    user={user}
                    message={message}
                    key={id}
                  />
                );
              }
              if (isTimelineEventOfType("extendable", type)) {
                return (
                  <ExtendedTimelineEvent
                    event={event}
                    orderCurrency={orderCurrency}
                  />
                );
              }

              if (isTimelineEventOfType("linked", type)) {
                return (
                  <TimelineEvent
                    titleElements={getTitleElements(event)}
                    key={id}
                    date={date}
                  />
                );
              }

              return (
                <TimelineEvent
                  {...getTimelineEventTitleProps(event)}
                  key={id}
                  date={date}
                />
              );
            })}
        </Timeline>
      ) : (
        <Skeleton />
      )}
    </div>
  );
};
OrderHistory.displayName = "OrderHistory";
export default OrderHistory;
