import usePromotionCodeForm from "@insite/client-framework/Common/Hooks/usePromotionCodeForm";
import { getStyledWrapper } from "@insite/client-framework/Common/StyledWrapper";
import siteMessage from "@insite/client-framework/SiteMessage";
import ApplicationState from "@insite/client-framework/Store/ApplicationState";
import {
    canApplyPromotionsToCart,
    getCartState,
    getCurrentCartState,
    isCartEmpty,
} from "@insite/client-framework/Store/Data/Carts/CartsSelector";
import { getQueryStrings } from "@insite/client-framework/Store/Data/Pages/PageSelectors";
import {
    getCurrentPromotionsDataView,
    getPromotionsDataView,
} from "@insite/client-framework/Store/Data/Promotions/PromotionsSelectors";
import applyPromotion from "@insite/client-framework/Store/Pages/CheckoutReviewAndSubmit/Handlers/ApplyPromotion";
import removePromotion from "@insite/client-framework/Store/Pages/CheckoutReviewAndSubmit/Handlers/RemovePromotion";
import removePromotions from "@insite/client-framework/Store/Pages/CheckoutReviewAndSubmit/Handlers/RemovePromotions";
import translate from "@insite/client-framework/Translate";
import { PromotionModel } from "@insite/client-framework/Types/ApiModels";
import WidgetModule from "@insite/client-framework/Types/WidgetModule";
import WidgetProps from "@insite/client-framework/Types/WidgetProps";
import Button, { ButtonPresentationProps } from "@insite/mobius/Button";
import GridContainer, { GridContainerProps } from "@insite/mobius/GridContainer";
import GridItem, { GridItemProps } from "@insite/mobius/GridItem";
import Link, { LinkPresentationProps } from "@insite/mobius/Link";
import Tag, { TagPresentationProps } from "@insite/mobius/Tag";
import TextField, { TextFieldPresentationProps } from "@insite/mobius/TextField";
import Typography, { TypographyPresentationProps } from "@insite/mobius/Typography";
import InjectableCss from "@insite/mobius/utilities/InjectableCss";
import React from "react";
import { connect, ResolveThunks } from "react-redux";
import { css } from "styled-components";

const mapStateToProps = (state: ApplicationState) => {
    const { cartId } = getQueryStrings(state);
    const cartState = cartId ? getCartState(state, cartId) : getCurrentCartState(state);
    const cart = cartState.value;
    const promotionsDataView = cartId ? getPromotionsDataView(state, cartId) : getCurrentPromotionsDataView(state);
    const promotions = promotionsDataView.value;
    const {
        isApplyingPromotion,
        promotionErrorMessage,
        promotionSuccessMessage,
        isCheckingOutWithPayPay,
        isPromotionAppliedSuccess,
        isPromotionRemovedSuccess,
        isPromotionsRemovedSuccess,
    } = state.pages.checkoutReviewAndSubmit;
    return {
        promotions,
        isApplyButtonDisabled: cartState.isLoading || isApplyingPromotion || isCartEmpty(cart),
        canApplyPromosToCart: canApplyPromotionsToCart(cart) && !isCheckingOutWithPayPay,
        promotionErrorMessage,
        promotionSuccessMessage,
        isPromotionAppliedSuccess,
        isPromotionRemovedSuccess,
        isPromotionsRemovedSuccess,
    };
};

const mapDispatchToProps = {
    applyPromotion,
    removePromotion,
    removePromotions,
};

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

export interface CheckoutReviewAndSubmitPromotionCodeStyles {
    form?: InjectableCss;
    promotionCodeTextField?: TextFieldPresentationProps;
    applyButton?: ButtonPresentationProps;
    applySuccessText?: TypographyPresentationProps;
    promotionRemovedText?: TypographyPresentationProps;
    gridContainer?: GridContainerProps;
    promotionCodeGridItem?: GridItemProps;
    applyPromotionGridItem?: GridItemProps;
    promotionAppliedGridItem?: GridItemProps;
    promotionRemovedGridItem?: GridItemProps;
    removeCodesGridItem?: GridItemProps;
    removeCodeGridItem?: GridItemProps;
    removeCodesLink?: LinkPresentationProps;
    removeCodeTag?: TagPresentationProps;
}

export const promotionCodeFormStyles: CheckoutReviewAndSubmitPromotionCodeStyles = {
    applyButton: {
        variant: "tertiary",
        css: css`
            width: 100%;
            margin-top: 2.5em;
        `,
    },
    applySuccessText: {
        color: "success",
    },
    gridContainer: { gap: 10 },
    promotionCodeGridItem: {
        width: [12, 12, 12, 8, 8],
    },
    applyPromotionGridItem: {
        width: [12, 12, 12, 4, 4],
        css: css`
            width: 100%;
            display: flex;
        `,
    },
    promotionAppliedGridItem: {
        width: [12, 12, 12, 12, 12],
    },
    promotionRemovedGridItem: {
        width: [12, 12, 12, 12, 12],
    },
    removeCodesGridItem: {
        width: [12, 12, 12, 12, 12],
    },
    removeCodeGridItem: {
        width: [12, 12, 12, 12, 12],
        css: css`
            flex-wrap: wrap;
        `,
    },
    removeCodesLink: {
        color: "primary",
    },
    removeCodeTag: {
        typographyProps: {
            ellipsis: true,
            css: css`
                width: 100%;
                text-align: left;
                margin: 5px 0;
            `,
        },
    },
};

const styles = promotionCodeFormStyles;
const StyledForm = getStyledWrapper("form");

const CheckoutReviewAndSubmitPromotionCode = ({
    promotions,
    isApplyButtonDisabled,
    promotionSuccessMessage,
    promotionErrorMessage,
    isPromotionAppliedSuccess,
    isPromotionRemovedSuccess,
    isPromotionsRemovedSuccess,
    canApplyPromosToCart,
    applyPromotion,
    removePromotion,
    removePromotions,
}: Props) => {
    const { promotionCode, setPromotionCode, promotionsWithCode, removingPromotionCode, setRemovingPromotionCode } =
        usePromotionCodeForm(promotions);

    const handlePromotionCodeChange = (event: React.ChangeEvent<HTMLInputElement>) =>
        setPromotionCode(event.currentTarget.value);

    const applyPromotionHandler = () => {
        applyPromotion({ promotionCode });
        setPromotionCode("");
    };

    const removePromotionCodesHandler = () => {
        removePromotions();
    };

    const removePromotionHandler = (promotion: PromotionModel) => {
        removePromotion({ promotionId: promotion.id });
        setRemovingPromotionCode(promotion.promotionCode);
    };

    if (!canApplyPromosToCart) {
        return null;
    }

    return (
        <>
            <StyledForm {...styles.form}>
                <GridContainer {...styles.gridContainer}>
                    <GridItem {...styles.promotionCodeGridItem}>
                        <TextField
                            {...styles.promotionCodeTextField}
                            label={translate("Have a Promotion Code?")}
                            value={promotionCode}
                            onChange={handlePromotionCodeChange}
                            error={promotionErrorMessage}
                            data-test-selector="promotionCodeTextField"
                        />
                    </GridItem>
                    <GridItem {...styles.applyPromotionGridItem}>
                        <Button
                            {...styles.applyButton}
                            onClick={e => {
                                e.preventDefault();
                                applyPromotionHandler();
                            }}
                            disabled={isApplyButtonDisabled || promotionCode.length === 0}
                            data-test-selector="applyPromotionCodeButton"
                        >
                            {translate("Apply")}
                        </Button>
                    </GridItem>
                    {isPromotionAppliedSuccess && (
                        <GridItem {...styles.promotionAppliedGridItem}>
                            <Typography
                                {...styles.applySuccessText}
                                as="div"
                                data-test-selector="promotionCode_addingPromotionCodeSuccessMessage"
                            >
                                {promotionSuccessMessage}
                            </Typography>
                        </GridItem>
                    )}
                    {promotionsWithCode.length > 0 && (
                        <GridItem {...styles.removeCodesGridItem}>
                            <Link
                                {...styles.removeCodesLink}
                                onClick={e => {
                                    e.preventDefault();
                                    removePromotionCodesHandler();
                                }}
                                data-test-selector="promotionCode_removePromotionCodesButton"
                            >
                                {translate("Remove Codes")}
                            </Link>
                        </GridItem>
                    )}
                    {promotionsWithCode.length > 0 && (
                        <GridItem {...styles.removeCodeGridItem}>
                            {promotionsWithCode.map(promotion => (
                                <Tag
                                    {...styles.removeCodeTag}
                                    key={promotion.id}
                                    onDelete={e => {
                                        e.preventDefault();
                                        removePromotionHandler(promotion);
                                    }}
                                    data-test-selector={`promotionCode_promotionTag_${promotion.promotionCode}`}
                                >
                                    {promotion.promotionCode}
                                </Tag>
                            ))}
                        </GridItem>
                    )}
                    {isPromotionsRemovedSuccess && (
                        <GridItem {...styles.promotionRemovedGridItem}>
                            <Typography
                                {...styles.promotionRemovedText}
                                as="div"
                                data-test-selector="promotionCode_allPromotionCodesRemovedMessage"
                            >
                                {siteMessage("Promotion_CodesRemoved")}
                            </Typography>
                        </GridItem>
                    )}
                    {isPromotionRemovedSuccess && (
                        <GridItem {...styles.promotionRemovedGridItem}>
                            <Typography
                                {...styles.promotionRemovedText}
                                as="div"
                                data-test-selector="promotionCode_promotionCodeRemovedMessage"
                            >
                                {siteMessage("Promotion_CodeRemoved", removingPromotionCode)}
                            </Typography>
                        </GridItem>
                    )}
                </GridContainer>
            </StyledForm>
        </>
    );
};

const widgetModule: WidgetModule = {
    component: connect(mapStateToProps, mapDispatchToProps)(CheckoutReviewAndSubmitPromotionCode),
    definition: {
        group: "Common",
        allowedContexts: ["CartPage", "CheckoutShippingPage", "CheckoutReviewAndSubmitPage", "OnePageCheckoutPage"],
        displayName: "Promotion Code Form",
    },
};

export default widgetModule;
