import siteMessage from "@insite/client-framework/SiteMessage";
import ApplicationState from "@insite/client-framework/Store/ApplicationState";
import setAddToListModalIsOpen from "@insite/client-framework/Store/Components/AddToListModal/Handlers/SetAddToListModalIsOpen";
import { getSettingsCollection } from "@insite/client-framework/Store/Context/ContextSelectors";
import {
    canAddAllToList,
    canCheckoutWithCart,
    canSaveOrder,
    canSubmitForQuote,
    getCurrentCartState,
    hasOnlyQuoteRequiredProducts,
    hasQuoteRequiredProducts,
    isCartCheckoutDisabled,
    isCartEmpty,
    isPunchOutOrder,
} from "@insite/client-framework/Store/Data/Carts/CartsSelector";
import addToWishList from "@insite/client-framework/Store/Data/WishLists/Handlers/AddToWishList";
import { getPageLinkByPageType } from "@insite/client-framework/Store/Links/LinksSelectors";
import doPunchOutCheckout from "@insite/client-framework/Store/Pages/Cart/Handlers/DoPunchOutCheckout";
import saveOrder from "@insite/client-framework/Store/Pages/Cart/Handlers/SaveOrder";
import preloadCheckoutShippingData from "@insite/client-framework/Store/Pages/CheckoutShipping/Handlers/PreloadCheckoutShippingData";
import signInAsGuest from "@insite/client-framework/Store/Pages/SignIn/Handlers/SignInAsGuest";
import translate from "@insite/client-framework/Translate";
import WidgetModule from "@insite/client-framework/Types/WidgetModule";
import WidgetProps from "@insite/client-framework/Types/WidgetProps";
import TwoButtonModal from "@insite/content-library/Components/TwoButtonModal";
import Button, { ButtonPresentationProps } from "@insite/mobius/Button";
import Clickable, { ClickablePresentationProps } from "@insite/mobius/Clickable";
import { BaseTheme } from "@insite/mobius/globals/baseTheme";
import Hidden, { HiddenProps } from "@insite/mobius/Hidden";
import OverflowMenu, { OverflowMenuPresentationProps } from "@insite/mobius/OverflowMenu";
import ToasterContext from "@insite/mobius/Toast/ToasterContext";
import breakpointMediaQueries from "@insite/mobius/utilities/breakpointMediaQueries";
import { HasHistory, withHistory } from "@insite/mobius/utilities/HistoryContext";
import React, { useContext, useState } from "react";
import { connect, ResolveThunks } from "react-redux";
import { css } from "styled-components";

const enum fields {
    fullWidthButton = "fullWidthButton",
    checkoutVariant = "checkoutVariant",
    requestForQuoteVariant = "requestForQuoteVariant",
    saveOrderVariant = "saveOrderVariant",
    addAllToListVariant = "addAllToListVariant",
}

const enum variants {
    primary = "primary",
    secondary = "secondary",
    overflow = "overflow",
    unenabled = "unenabled",
}

interface OwnProps extends WidgetProps {
    fields: {
        [fields.fullWidthButton]: boolean;
        [fields.checkoutVariant]: variants;
        [fields.requestForQuoteVariant]: variants;
        [fields.saveOrderVariant]: variants;
        [fields.addAllToListVariant]: variants;
    };
}

const mapStateToProps = (state: ApplicationState) => {
    const cartState = getCurrentCartState(state);
    const cart = cartState.value;
    const isCartLoading = cartState.isLoading;
    const { isUpdatingCart } = state.context;
    const {
        cartSettings: { onePageCheckout },
        wishListSettings: { allowMultipleWishLists },
    } = getSettingsCollection(state);
    const { isSavingOrder } = state.pages.cart;

    return {
        cart,
        allowMultipleWishLists,
        isCartEmpty: isCartEmpty(cart),
        canSaveOrder: cartState.value?.canSaveOrder,
        canAddAllToList: canAddAllToList(cart),
        isPunchOutOrder: isPunchOutOrder(cart),
        canCheckoutWithCart: canCheckoutWithCart(cart),
        isCartCheckoutDisabled:
            isCartLoading ||
            !cart ||
            isCartCheckoutDisabled(cart) ||
            isUpdatingCart ||
            state.pages.signIn.isSigningInAsGuest,
        hasOnlyQuoteRequiredProducts: hasOnlyQuoteRequiredProducts(cart),
        canSubmitForQuote: canSubmitForQuote(cart),
        isSubmitForQuoteButtonDisabled: isCartLoading || isUpdatingCart,
        rfqRequestQuotePageUrl: getPageLinkByPageType(state, "RfqRequestQuotePage")?.url,
        hasQuoteRequiredProducts: hasQuoteRequiredProducts(cart),
        checkoutReviewAndSubmitPageUrl: getPageLinkByPageType(state, "CheckoutReviewAndSubmitPage")?.url,
        checkoutShippingPageUrl: getPageLinkByPageType(state, "CheckoutShippingPage")?.url,
        isSignedIn: cartState.value?.isAuthenticated && !cartState.value?.isGuestOrder,
        savedOrdersPageUrl: getPageLinkByPageType(state, "SavedOrderDetailsPage")?.url,
        signInPageUrl: getPageLinkByPageType(state, "SignInPage")?.url,
        cartPageUrl: getPageLinkByPageType(state, "CartPage")?.url,
        onePageCheckout,
        onePageCheckoutPageUrl: getPageLinkByPageType(state, "OnePageCheckoutPage")?.url,
        isSaveOrderDisabled:
            cartState.isLoading ||
            isSavingOrder ||
            isUpdatingCart ||
            cartState.value?.lineCount === 0 ||
            cartState.value?.cartLines?.length === 0,
    };
};

const mapDispatchToProps = {
    setAddToListModalIsOpen,
    addToWishList,
    preloadCheckoutShippingData,
    doPunchOutCheckout,
    saveOrder,
    signInAsGuest,
};

type Props = OwnProps & ReturnType<typeof mapStateToProps> & HasHistory & ResolveThunks<typeof mapDispatchToProps>;

export interface CartActionsStyles {
    narrowHidden?: HiddenProps;
    narrowOverflowMenu?: OverflowMenuPresentationProps;
    saveOrderClickable?: ClickablePresentationProps;
    addAllToListClickable?: ClickablePresentationProps;
    requestAQuoteClickable?: ClickablePresentationProps;
    checkoutClickable?: ClickablePresentationProps;
    wideHidden?: HiddenProps;
    wideOverflowMenu?: OverflowMenuPresentationProps;
    saveOrderButton?: ButtonPresentationProps;
    checkoutButton?: ButtonPresentationProps;
}

export const cartActionsStyles: CartActionsStyles = {
    narrowHidden: {
        above: "sm",
        css: css`
            display: flex;
            justify-content: flex-end;
        `,
    },
    wideHidden: {
        below: "md",
        css: css`
            display: flex;
            justify-content: flex-end;
        `,
    },
    saveOrderButton: {
        buttonType: "outline",
        variant: "secondary",
    },
    wideOverflowMenu: {
        cssOverrides: {
            wrapper: css`
                margin-left: 20px;
            `,
        },
    },
};

const styles = cartActionsStyles;

const CartActions = ({
    cart,
    isCartEmpty,
    canAddAllToList,
    allowMultipleWishLists,
    setAddToListModalIsOpen,
    addToWishList,
    isPunchOutOrder,
    fields,
    canCheckoutWithCart,
    isCartCheckoutDisabled,
    hasOnlyQuoteRequiredProducts,
    canSubmitForQuote,
    isSubmitForQuoteButtonDisabled,
    history,
    rfqRequestQuotePageUrl,
    preloadCheckoutShippingData,
    doPunchOutCheckout,
    hasQuoteRequiredProducts,
    checkoutReviewAndSubmitPageUrl,
    checkoutShippingPageUrl,
    isSignedIn,
    saveOrder,
    savedOrdersPageUrl,
    cartPageUrl,
    signInPageUrl,
    canSaveOrder,
    onePageCheckout,
    onePageCheckoutPageUrl,
    signInAsGuest,
    isSaveOrderDisabled,
}: Props) => {
    if (!cart || isPunchOutOrder) {
        return null;
    }

    const toasterContext = useContext(ToasterContext);
    const overflowItems = [];
    const wideHiddenOverflowMenu = [];
    const [quoteRequiredModalIsOpen, setQuoteRequiredModalIsOpen] = useState(false);

    const addAllToListClickHandler = () => {
        const productInfos =
            cart.cartLines
                ?.filter(o => o.productId && o.qtyOrdered)
                .map(cartLine => ({
                    productId: cartLine.productId!,
                    qtyOrdered: cartLine.qtyOrdered!,
                    unitOfMeasure: cartLine.unitOfMeasure,
                })) || [];
        if (!allowMultipleWishLists) {
            addToWishList({
                productInfos,
                onSuccess: () => {
                    toasterContext.addToast({ body: siteMessage("Lists_ProductAdded"), messageType: "success" });
                },
                onComplete(resultProps) {
                    if (resultProps.result?.wishList) {
                        // "this" is targeting the object being created, not the parent SFC
                        // eslint-disable-next-line react/no-this-in-sfc
                        this.onSuccess?.(resultProps.result.wishList);
                    } else if (resultProps.result?.errorMessage) {
                        toasterContext.addToast({ body: resultProps.result.errorMessage, messageType: "danger" });
                    }
                },
            });
            return;
        }

        setAddToListModalIsOpen({ modalIsOpen: true, productInfos });
    };

    const checkoutClickHandler = () => {
        if (isPunchOutOrder) {
            doPunchOutCheckout();
            return;
        }

        if (!quoteRequiredModalIsOpen && hasQuoteRequiredProducts) {
            setQuoteRequiredModalIsOpen(true);
            return;
        }

        setQuoteRequiredModalIsOpen(false);

        if (onePageCheckout && onePageCheckoutPageUrl) {
            if (!cart.isAuthenticated) {
                signInAsGuest({ returnUrl: onePageCheckoutPageUrl });
            } else {
                history.push(
                    cart.isAwaitingApproval ? `${onePageCheckoutPageUrl}?cartId=${cart.id}` : onePageCheckoutPageUrl,
                );
            }
            return;
        }

        const { canBypassCheckoutAddress } = cart!;
        if (canBypassCheckoutAddress) {
            history.push(checkoutReviewAndSubmitPageUrl!);
            return;
        }

        preloadCheckoutShippingData({
            cartId: cart?.isAwaitingApproval ? cart.id : undefined,
            onSuccess: () => {
                history.push(
                    cart?.isAwaitingApproval
                        ? `${checkoutShippingPageUrl}?cartId=${cart.id}`
                        : checkoutShippingPageUrl!,
                );
            },
        });
    };

    const requestForQuoteClickHandler = () => {
        if (rfqRequestQuotePageUrl) {
            history.push(rfqRequestQuotePageUrl);
        }
    };

    const saveOrderClickHandler = () => {
        if (!isSignedIn) {
            history.push(`${signInPageUrl}?returnUrl=${cartPageUrl}`);
            return;
        }

        saveOrder({
            onSuccess: (orderId: string) => {
                history.push(`${savedOrdersPageUrl}?cartId=${orderId}`);
            },
            onComplete(resultProps) {
                if (resultProps.apiResult?.cart) {
                    // "this" is targeting the object being created, not the parent SFC
                    // eslint-disable-next-line react/no-this-in-sfc
                    this.onSuccess?.(resultProps.apiResult.cart.id);
                }
            },
            onError: (errorMessage: string) => {
                toasterContext.addToast({ body: errorMessage, messageType: "danger" });
            },
        });
    };

    const submitForQuoteLabel = cart?.isSalesperson ? translate("Create a Quote") : translate("Submit for Quote");

    if (canCheckoutWithCart && fields.checkoutVariant === variants.overflow) {
        overflowItems.push(
            <Clickable
                {...styles.checkoutClickable}
                key="checkout"
                onClick={checkoutClickHandler}
                disabled={isCartCheckoutDisabled || hasOnlyQuoteRequiredProducts}
            >
                {cart?.requiresApproval ? translate("Checkout for Approval") : translate("Checkout")}
            </Clickable>,
        );
    }

    if (canSubmitForQuote && fields.requestForQuoteVariant === variants.overflow) {
        overflowItems.push(
            <Clickable {...styles.requestAQuoteClickable} key="requestforquote" onClick={requestForQuoteClickHandler}>
                {submitForQuoteLabel}
            </Clickable>,
        );
    }

    if (canSaveOrder && fields.saveOrderVariant === variants.overflow) {
        overflowItems.push(
            <Clickable
                {...styles.saveOrderClickable}
                key="saveorder"
                onClick={saveOrderClickHandler}
                disabled={isSaveOrderDisabled}
            >
                {translate("Save Order")}
            </Clickable>,
        );
    }

    if (!isCartEmpty && (!fields.addAllToListVariant || fields.addAllToListVariant === variants.overflow)) {
        overflowItems.push(
            <Clickable
                {...styles.addAllToListClickable}
                key="addAll"
                disabled={!canAddAllToList}
                onClick={addAllToListClickHandler}
                data-test-selector="cartActionsAddAllToList"
            >
                {translate("Add All to List")}
            </Clickable>,
        );
    }

    if (overflowItems.length > 0) {
        wideHiddenOverflowMenu.push(
            <OverflowMenu key="overflow" {...styles.wideOverflowMenu} data-test-selector="cartActionsOverflowMenu">
                {overflowItems}
            </OverflowMenu>,
        );
    }

    const buttonCss = css`
        ${({ theme }: { theme: BaseTheme }) =>
            breakpointMediaQueries(theme, [
                css`
                    width: 100%;
                `,
                css`
                    width: 100%;
                `,
                fields.fullWidthButton
                    ? css`
                          width: 100%;
                      `
                    : null,
                fields.fullWidthButton
                    ? css`
                          width: 100%;
                      `
                    : null,
                fields.fullWidthButton
                    ? css`
                          width: 100%;
                      `
                    : null,
            ])}
    `;
    return (
        <>
            <Hidden {...styles.narrowHidden} data-test-selector="cartActionsNarrow">
                <OverflowMenu position="end" {...styles.narrowOverflowMenu}>
                    {canCheckoutWithCart &&
                        (fields.checkoutVariant === variants.primary ||
                            fields.checkoutVariant === variants.secondary) && (
                            <Button
                                {...styles.checkoutButton}
                                onClick={checkoutClickHandler}
                                disabled={isCartCheckoutDisabled || hasOnlyQuoteRequiredProducts}
                                variant={fields.checkoutVariant}
                                className="button"
                                css={buttonCss}
                            >
                                {cart?.requiresApproval ? translate("Checkout for Approval") : translate("Checkout")}
                            </Button>
                        )}
                    {canSubmitForQuote &&
                        (fields.requestForQuoteVariant === variants.primary ||
                            fields.requestForQuoteVariant === variants.secondary) && (
                            <Button
                                {...styles.requestAQuoteClickable}
                                disabled={isSubmitForQuoteButtonDisabled}
                                onClick={requestForQuoteClickHandler}
                                variant={fields.requestForQuoteVariant}
                                className="button"
                                css={buttonCss}
                            >
                                {submitForQuoteLabel}
                            </Button>
                        )}
                    {canSaveOrder &&
                        (!fields.saveOrderVariant ||
                            fields.saveOrderVariant === variants.primary ||
                            fields.saveOrderVariant === variants.secondary) && (
                            <Button
                                {...styles.saveOrderClickable}
                                onClick={saveOrderClickHandler}
                                variant={fields.saveOrderVariant}
                                disabled={isSaveOrderDisabled}
                                className="button"
                                css={buttonCss}
                            >
                                {translate("Save Order")}
                            </Button>
                        )}
                    {!isCartEmpty &&
                        (fields.addAllToListVariant === variants.primary ||
                            fields.addAllToListVariant === variants.secondary) && (
                            <Button
                                {...styles.addAllToListClickable}
                                onClick={addAllToListClickHandler}
                                variant={fields.addAllToListVariant}
                                className="button"
                                css={buttonCss}
                            >
                                {translate("Add All to List")}
                            </Button>
                        )}
                    {overflowItems}
                </OverflowMenu>
            </Hidden>
            <Hidden {...styles.wideHidden} data-test-selector="cartActionsWide">
                {canCheckoutWithCart &&
                    (fields.checkoutVariant === variants.primary || fields.checkoutVariant === variants.secondary) && (
                        <Button
                            {...styles.checkoutButton}
                            onClick={checkoutClickHandler}
                            disabled={isCartCheckoutDisabled || hasOnlyQuoteRequiredProducts}
                            variant={fields.checkoutVariant}
                            className="button"
                            css={buttonCss}
                        >
                            {cart?.requiresApproval ? translate("Checkout for Approval") : translate("Checkout")}
                        </Button>
                    )}
                {canSubmitForQuote &&
                    (fields.requestForQuoteVariant === variants.primary ||
                        fields.requestForQuoteVariant === variants.secondary) && (
                        <Button
                            {...styles.requestAQuoteClickable}
                            disabled={isSubmitForQuoteButtonDisabled}
                            onClick={requestForQuoteClickHandler}
                            variant={fields.requestForQuoteVariant}
                            className="button"
                            css={buttonCss}
                        >
                            {submitForQuoteLabel}
                        </Button>
                    )}
                {canSaveOrder &&
                    (!fields.saveOrderVariant ||
                        fields.saveOrderVariant === variants.primary ||
                        fields.saveOrderVariant === variants.secondary) && (
                        <Button
                            {...styles.saveOrderClickable}
                            onClick={saveOrderClickHandler}
                            variant={fields.saveOrderVariant}
                            disabled={isSaveOrderDisabled}
                            className="button"
                            data-test-selector="cart_saveOrder"
                            css={buttonCss}
                        >
                            {translate("Save Order")}
                        </Button>
                    )}
                {!isCartEmpty &&
                    (fields.addAllToListVariant === variants.primary ||
                        fields.addAllToListVariant === variants.secondary) && (
                        <Button
                            {...styles.addAllToListClickable}
                            onClick={addAllToListClickHandler}
                            variant={fields.addAllToListVariant}
                            className="button"
                            css={buttonCss}
                        >
                            {translate("Add All to List")}
                        </Button>
                    )}
                {wideHiddenOverflowMenu}
            </Hidden>
            <TwoButtonModal
                headlineText=""
                modalIsOpen={quoteRequiredModalIsOpen}
                messageText={siteMessage("OrderApproval_RequiresQuoteMessage")}
                cancelButtonText={translate("Cancel")}
                submitButtonText={translate("Continue")}
                onCancel={() => setQuoteRequiredModalIsOpen(false)}
                onSubmit={checkoutClickHandler}
                submitTestSelector="QuoteInCartMessageSubmit"
                dataTestSelector="twoButtonModal_RequiresQuote"
            ></TwoButtonModal>
        </>
    );
};

const widgetModule: WidgetModule = {
    component: connect(mapStateToProps, mapDispatchToProps)(withHistory(CartActions)),
    definition: {
        group: "Cart",
        allowedContexts: ["CartPage"],
        fieldDefinitions: [
            {
                name: fields.fullWidthButton,
                displayName: "Full Width Buttons",
                editorTemplate: "CheckboxField",
                defaultValue: false,
                fieldType: "General",
                isRequired: false,
                variant: "toggle",
                sortOrder: 0,
            },
            {
                name: fields.checkoutVariant,
                displayName: "Checkout",
                editorTemplate: "DropDownField",
                options: [
                    { displayName: "Primary Action", value: variants.primary },
                    { displayName: "Secondary Action", value: variants.secondary },
                    { displayName: "Overflow Action", value: variants.overflow },
                    { displayName: "Not Enabled", value: variants.unenabled },
                ],
                defaultValue: variants.unenabled,
                fieldType: "General",
            },
            {
                name: fields.requestForQuoteVariant,
                displayName: "Submit for Quote",
                editorTemplate: "DropDownField",
                options: [
                    { displayName: "Primary Action", value: variants.primary },
                    { displayName: "Secondary Action", value: variants.secondary },
                    { displayName: "Overflow Action", value: variants.overflow },
                    { displayName: "Not Enabled", value: variants.unenabled },
                ],
                defaultValue: variants.unenabled,
                fieldType: "General",
            },
            {
                name: fields.saveOrderVariant,
                displayName: "Save Order",
                editorTemplate: "DropDownField",
                options: [
                    { displayName: "Primary Action", value: variants.primary },
                    { displayName: "Secondary Action", value: variants.secondary },
                    { displayName: "Overflow Action", value: variants.overflow },
                    { displayName: "Not Enabled", value: variants.unenabled },
                ],
                defaultValue: variants.secondary,
                fieldType: "General",
            },
            {
                name: fields.addAllToListVariant,
                displayName: "Add All to List",
                editorTemplate: "DropDownField",
                options: [
                    { displayName: "Primary Action", value: variants.primary },
                    { displayName: "Secondary Action", value: variants.secondary },
                    { displayName: "Overflow Action", value: variants.overflow },
                    { displayName: "Not Enabled", value: variants.unenabled },
                ],
                defaultValue: variants.overflow,
                fieldType: "General",
            },
        ],
    },
};

export default widgetModule;
