import StyledWrapper from "@insite/client-framework/Common/StyledWrapper";
import siteMessage from "@insite/client-framework/SiteMessage";
import ApplicationState from "@insite/client-framework/Store/ApplicationState";
import { getCurrentAccountState } from "@insite/client-framework/Store/Data/Accounts/AccountsSelector";
import { getBillToState } from "@insite/client-framework/Store/Data/BillTos/BillTosSelectors";
import {
    canPlaceOrder,
    canSubmitForApprovalOrder,
    getCartState,
    getCurrentCartState,
} from "@insite/client-framework/Store/Data/Carts/CartsSelector";
import {
    getCurrentPromotionsDataView,
    getDiscountTotal,
    getOrderPromotions,
    getShippingPromotions,
} from "@insite/client-framework/Store/Data/Promotions/PromotionsSelectors";
import { getPageLinkByPageType, useGetLink } from "@insite/client-framework/Store/Links/LinksSelectors";
import placeOrderForApproval from "@insite/client-framework/Store/Pages/OnePageCheckout/Handlers/PlaceOrderForApproval";
import setIsPlacingOrder from "@insite/client-framework/Store/Pages/OnePageCheckout/Handlers/SetIsPlacingOrder";
import updateCurrentAccount from "@insite/client-framework/Store/Pages/OnePageCheckout/Handlers/UpdateCurrentAccount";
import translate from "@insite/client-framework/Translate";
import { LinkFieldValue } from "@insite/client-framework/Types/FieldDefinition";
import WidgetModule from "@insite/client-framework/Types/WidgetModule";
import WidgetProps from "@insite/client-framework/Types/WidgetProps";
import CartTotalDisplay, { CartTotalDisplayStyles } from "@insite/content-library/Components/CartTotalDisplay";
import Button, { ButtonPresentationProps } from "@insite/mobius/Button";
import Checkbox, { CheckboxPresentationProps } from "@insite/mobius/Checkbox";
import { BaseTheme } from "@insite/mobius/globals/baseTheme";
import GridContainer, { GridContainerProps } from "@insite/mobius/GridContainer";
import GridItem, { GridItemProps } from "@insite/mobius/GridItem";
import LoadingSpinner from "@insite/mobius/LoadingSpinner";
import Typography, { TypographyPresentationProps } from "@insite/mobius/Typography";
import { breakpointMediaQueries } from "@insite/mobius/utilities";
import { HasHistory, withHistory } from "@insite/mobius/utilities/HistoryContext";
import InjectableCss from "@insite/mobius/utilities/InjectableCss";
import React, { useState } from "react";
import { connect, ResolveThunks } from "react-redux";
import { css } from "styled-components";

const enum fields {
    termsAndConditionsLink = "termsAndConditionsLink",
}

interface OwnProps extends WidgetProps {
    fields: {
        [fields.termsAndConditionsLink]: LinkFieldValue;
    };
}

const mapStateToProps = (state: ApplicationState) => {
    const { cartId } = state.pages.onePageCheckout;
    const cartState = cartId ? getCartState(state, cartId) : getCurrentCartState(state);
    const { value: cart, isLoading } = cartState;
    const promotions = getCurrentPromotionsDataView(state).value;
    return {
        cart,
        account: getCurrentAccountState(state).value,
        billTo: getBillToState(state, cart?.billToId).value,
        orderPromotions: promotions ? getOrderPromotions(promotions) : undefined,
        shippingPromotions: promotions ? getShippingPromotions(promotions) : undefined,
        discountTotal: promotions ? getDiscountTotal(promotions) : undefined,
        isLoading,
        isExpanded: state.pages.onePageCheckout.paymentDetailsState === "complete" || canSubmitForApprovalOrder(cart),
        isPlacingOrder: state.pages.onePageCheckout.isPlacingOrder,
        placeOrderErrorMessage: state.pages.onePageCheckout.placeOrderErrorMessage,
        showPlaceOrderButton: canPlaceOrder(cart),
        showSubmitForApprovalOrderButton: canSubmitForApprovalOrder(cart),
        orderApprovalDetailsPageUrl: getPageLinkByPageType(state, "OrderApprovalDetailsPage")?.url,
    };
};

const mapDispatchToProps = {
    setIsPlacingOrder,
    placeOrderForApproval,
    updateCurrentAccount,
};

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

export interface OnePageCheckoutReviewAndPlaceOrderStyles {
    container?: GridContainerProps;
    centeringWrapper?: InjectableCss;
    titleGridItem?: GridItemProps;
    titleText?: TypographyPresentationProps;
    cartTotalGridItem?: GridItemProps;
    cartTotal?: CartTotalDisplayStyles;
    checkboxesGridItem?: GridItemProps;
    signUpForNewslettersCheckbox?: CheckboxPresentationProps;
    placeOrderGridItem?: GridItemProps;
    placeOrderButton?: ButtonPresentationProps;
    agreementText?: TypographyPresentationProps;
    placeOrderErrorMessageGridItem?: GridItemProps;
    placeOrderErrorMessageText?: TypographyPresentationProps;
    submitForApprovalButton?: ButtonPresentationProps;
}

export const reviewAndPlaceOrderStyles: OnePageCheckoutReviewAndPlaceOrderStyles = {
    container: { gap: 20 },
    centeringWrapper: {
        css: css`
            display: flex;
            justify-content: center;
            align-items: center;
            height: 450px;
        `,
    },
    titleGridItem: {
        width: 10,
        css: css`
            align-items: center;
        `,
    },
    titleText: {
        variant: "h5",
        css: css`
            margin-bottom: 0;
        `,
    },
    cartTotalGridItem: { width: 12 },
    cartTotal: {
        container: {
            gap: 10,
            css: css`
                padding: 0;
                background-color: transparent;
            `,
        },
    },
    checkboxesGridItem: { width: 12 },
    placeOrderGridItem: {
        width: 12,
        css: css`
            flex-direction: column;
        `,
    },
    placeOrderButton: {
        variant: "primary",
        css: css`
            ${({ theme }: { theme: BaseTheme }) =>
                breakpointMediaQueries(
                    theme,
                    [
                        null,
                        css`
                            width: 100%;
                        `,
                    ],
                    "max",
                )}
        `,
    },
    agreementText: {
        size: 13,
        css: css`
            margin-top: 8px;
        `,
    },
    placeOrderErrorMessageGridItem: { width: 12 },
    placeOrderErrorMessageText: {
        color: "danger",
        css: css`
            margin-top: 5px;
            margin-bottom: 15px;
        `,
    },
    submitForApprovalButton: {
        variant: "primary",
        css: css`
            ${({ theme }: { theme: BaseTheme }) =>
                breakpointMediaQueries(
                    theme,
                    [
                        null,
                        css`
                            width: 100%;
                        `,
                    ],
                    "max",
                )}
        `,
    },
};

const styles = reviewAndPlaceOrderStyles;

const OnePageCheckoutReviewAndPlaceOrder = ({
    fields,
    cart,
    account,
    billTo,
    orderPromotions,
    shippingPromotions,
    discountTotal,
    isLoading,
    isExpanded,
    isPlacingOrder,
    placeOrderErrorMessage,
    showPlaceOrderButton,
    showSubmitForApprovalOrderButton,
    orderApprovalDetailsPageUrl,
    history,
    setIsPlacingOrder,
    placeOrderForApproval,
    updateCurrentAccount,
}: Props) => {
    const [signUpForNewsletters, setSignUpForNewslettersCheckbox] = useState(false);
    const { url: termsAndConditionsUrl } = useGetLink(fields.termsAndConditionsLink);

    if (!cart) {
        return (
            <StyledWrapper {...styles.centeringWrapper}>
                <LoadingSpinner data-test-selector="onePageCheckout_reviewAndPlaceOrder" />
            </StyledWrapper>
        );
    }

    const emailForSubsribe = account?.isGuest ? billTo?.email : account?.email;

    const placeOrderClickHandler = () => {
        if (account && account.isSubscribed === false && signUpForNewsletters && emailForSubsribe) {
            updateCurrentAccount({
                account: { ...account, isSubscribed: true, email: emailForSubsribe },
            });
        }

        setIsPlacingOrder({ isPlacingOrder: true });
    };

    const submitForApprovalOrderClickHandler = () => {
        placeOrderForApproval({
            onSuccess: (cartId: string) => {
                if (orderApprovalDetailsPageUrl) {
                    history.push(`${orderApprovalDetailsPageUrl}?cartId=${cartId}`);
                }
            },
            onComplete(resultProps) {
                if (resultProps.apiResult?.cart.id) {
                    // "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);
                }
            },
        });
    };

    return (
        <GridContainer {...styles.container} data-test-selector="onePageCheckoutReviewAndPlaceOrder_header">
            <GridItem {...styles.titleGridItem}>
                <Typography as="h2" {...styles.titleText}>
                    {translate("Review & Place Order")}
                </Typography>
            </GridItem>
            {isExpanded && (
                <>
                    <GridItem {...styles.cartTotalGridItem}>
                        <CartTotalDisplay
                            cart={cart}
                            orderPromotions={orderPromotions}
                            shippingPromotions={shippingPromotions}
                            discountTotal={discountTotal}
                            extendedStyles={styles.cartTotal}
                        />
                    </GridItem>
                    {account && account.isSubscribed === false && emailForSubsribe && (
                        <GridItem {...styles.checkboxesGridItem}>
                            <Checkbox
                                {...styles.signUpForNewslettersCheckbox}
                                onChange={(_, value) => setSignUpForNewslettersCheckbox(value)}
                                checked={signUpForNewsletters}
                            >
                                {siteMessage("SignIn_Sign_Up_Newsletter")}
                            </Checkbox>
                        </GridItem>
                    )}
                    <GridItem {...styles.placeOrderGridItem}>
                        {showPlaceOrderButton && (
                            <Button
                                {...styles.placeOrderButton}
                                disabled={isLoading || isPlacingOrder}
                                onClick={placeOrderClickHandler}
                                data-test-selector="checkoutReviewAndSubmit_placeOrder"
                            >
                                {translate("Place Order")}
                            </Button>
                        )}
                        {showSubmitForApprovalOrderButton && (
                            <Button
                                {...styles.submitForApprovalButton}
                                disabled={isLoading || isPlacingOrder}
                                onClick={submitForApprovalOrderClickHandler}
                                data-test-selector="checkoutReviewAndSubmit_submitForApproval"
                            >
                                {translate("Submit For Approval")}
                            </Button>
                        )}
                        {showPlaceOrderButton && termsAndConditionsUrl && (
                            <Typography {...styles.agreementText}>
                                {siteMessage("Checkout_Agreement", termsAndConditionsUrl)}
                            </Typography>
                        )}
                    </GridItem>
                    {placeOrderErrorMessage && (
                        <GridItem {...styles.placeOrderErrorMessageGridItem}>
                            <Typography {...styles.placeOrderErrorMessageText}>{placeOrderErrorMessage}</Typography>
                        </GridItem>
                    )}
                </>
            )}
        </GridContainer>
    );
};

const widgetModule: WidgetModule = {
    component: connect(mapStateToProps, mapDispatchToProps)(withHistory(OnePageCheckoutReviewAndPlaceOrder)),
    definition: {
        group: "One Page Checkout",
        allowedContexts: ["OnePageCheckoutPage"],
        displayName: "Review & Place Order",
        fieldDefinitions: [
            {
                name: fields.termsAndConditionsLink,
                fieldType: "Contextual",
                displayName: "Terms And Conditions Link",
                editorTemplate: "LinkField",
                defaultValue: { type: "Page", value: "" },
            },
        ],
    },
};

export default widgetModule;
