import useOverlayBadge from "@insite/client-framework/Common/Hooks/useOverlayBadge";
import useWidgetBadges from "@insite/client-framework/Common/Hooks/useWidgetBadges";
import mergeToNew from "@insite/client-framework/Common/mergeToNew";
import StyledWrapper from "@insite/client-framework/Common/StyledWrapper";
import wrapInContainerStyles from "@insite/client-framework/Common/wrapInContainerStyles";
import { ProductContext } from "@insite/client-framework/Components/ProductContext";
import ApplicationState from "@insite/client-framework/Store/ApplicationState";
import updateProductInfo from "@insite/client-framework/Store/Components/ProductInfoList/Handlers/UpdateProductInfo";
import { getProductInfoFromList } from "@insite/client-framework/Store/Components/ProductInfoList/ProductInfoListSelectors";
import sendProductRecommendationTracking from "@insite/client-framework/Store/Components/ProductRecommendations/Handlers/SendProductRecommendationTracking";
import translate from "@insite/client-framework/Translate";
import { ProductModel } from "@insite/client-framework/Types/ApiModels";
import ProductAddToCartButton from "@insite/content-library/Components/ProductAddToCartButton";
import ProductAddToListLink, {
    ProductAddToListLinkStyles,
} from "@insite/content-library/Components/ProductAddToListLink";
import ProductBrand, { ProductBrandStyles } from "@insite/content-library/Components/ProductBrand";
import ProductDescription, { ProductDescriptionStyles } from "@insite/content-library/Components/ProductDescription";
import ProductImage, { ProductImageStyles } from "@insite/content-library/Components/ProductImage";
import ProductImageBadges from "@insite/content-library/Components/ProductImageBadges";
import ProductPartNumbers, { ProductPartNumbersStyles } from "@insite/content-library/Components/ProductPartNumbers";
import ProductPrice from "@insite/content-library/Components/ProductPrice";
import ProductQuantityBreakPricing, {
    ProductQuantityBreakPricingStyles,
} from "@insite/content-library/Components/ProductQuantityBreakPricing";
import ProductQuantityOrdered from "@insite/content-library/Components/ProductQuantityOrdered";
import ProductTextBadges from "@insite/content-library/Components/ProductTextBadges";
import ProductUnitOfMeasureSelect from "@insite/content-library/Components/ProductUnitOfMeasureSelect";
import Badge from "@insite/mobius/Badge";
import { ButtonPresentationProps } from "@insite/mobius/Button";
import GridContainer, { GridContainerProps } from "@insite/mobius/GridContainer";
import GridItem, { GridItemProps } from "@insite/mobius/GridItem";
import { SelectPresentationProps } from "@insite/mobius/Select";
import { TextFieldProps } from "@insite/mobius/TextField";
import { TypographyPresentationProps } from "@insite/mobius/Typography";
import InjectableCss from "@insite/mobius/utilities/InjectableCss";
import VisuallyHidden from "@insite/mobius/VisuallyHidden";
import React, { useState } from "react";
import { connect, ResolveThunks } from "react-redux";
import { css } from "styled-components";

const mapStateToProps = (state: ApplicationState, ownProps: OwnProps) => ({
    productInfo: getProductInfoFromList(state, ownProps.carouselId, ownProps.product.id),
});

const mapDispatchToProps = {
    updateProductInfo,
    sendProductRecommendationTracking,
};

interface OwnProps {
    carouselId: string;
    product: ProductModel;
    recommendationId?: number;
    showImage: boolean;
    showBrand: boolean;
    showTitle: boolean;
    showPartNumbers: boolean;
    showPrice: boolean;
    showAddToCart: boolean;
    showAddToList: boolean;
    showImageBadges?: boolean;
    maximumNumberOfImageBadges?: number;
    showTextBadges?: boolean;
    maximumNumberOfTextBadges?: number;
    extendedStyles?: ProductCarouselProductStyles;
}

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

export interface ProductCarouselProductStyles {
    productImageStyles?: ProductImageStyles;
    productBrandWrapper?: InjectableCss;
    productBrandStyles?: ProductBrandStyles;
    productDescriptionStyles?: ProductDescriptionStyles;
    productPartNumbersStyles?: ProductPartNumbersStyles;
    productPriceWrapper?: InjectableCss;
    productUnitOfMeasureSelectStyles?: SelectPresentationProps;
    productQuantityBreakPricingStyles?: ProductQuantityBreakPricingStyles;
    addToCartContainer?: GridContainerProps;
    qtyGridItem?: GridItemProps;
    productQuantityOrderedStyles?: TextFieldProps;
    addToCartButtonGridItem?: GridItemProps;
    productAddToCartButtonStyles?: ButtonPresentationProps;
    productAddToListLinkStyles?: ProductAddToListLinkStyles;
    badgeAreaWrapper?: InjectableCss;
    badgeTextWrapper?: InjectableCss;
    badgeImageWrapper?: InjectableCss;
    badgeText?: TypographyPresentationProps;
    badgeImageProps?: JSX.IntrinsicElements["img"];
}

export const productCarouselProductStyles: ProductCarouselProductStyles = {
    productBrandWrapper: {
        css: css`
            margin: 6px 0;
            min-height: 22px;
        `,
    },
    productDescriptionStyles: {
        productDetailLink: {
            css: css`
                margin-bottom: 6px;
            `,
        },
    },
    productPartNumbersStyles: {
        container: {
            css: css`
                flex-grow: 0;
                margin-bottom: 6px;
            `,
        },
        erpNumberLabelText: { size: 13 },
        erpNumberValueText: { size: 13 },
    },
    productPriceWrapper: {
        css: css`
            flex-grow: 1;
            margin-bottom: 6px;
        `,
    },
    productUnitOfMeasureSelectStyles: {
        cssOverrides: {
            formField: css`
                margin-top: 6px;
            `,
        },
    },
    addToCartContainer: {
        gap: 10,
        css: css`
            flex-grow: 0;
            margin-bottom: 6px;
        `,
    },
    qtyGridItem: { width: 3 },
    productQuantityOrderedStyles: {
        cssOverrides: {
            formField: css`
                margin-top: 0;
            `,
        },
    },
    addToCartButtonGridItem: { width: 9 },
    productAddToCartButtonStyles: {
        css: css`
            width: 100%;
        `,
    },
    productAddToListLinkStyles: {
        link: {
            typographyProps: { size: 13 },
            css: css`
                margin-bottom: 12px;
            `,
        },
    },
    badgeAreaWrapper: {
        css: css`
            position: relative;
        `,
    },
    badgeTextWrapper: {
        css: css`
            position: absolute;
            width: 50%;
            white-space: nowrap;
            overflow: hidden;
        `,
    },
    badgeImageWrapper: {
        css: css`
            position: absolute;
            width: 25%;
            height: 25%;
        `,
    },
    badgeText: {
        weight: "bold",
        css: css`
            width: 100%;
            margin: auto;
            ${wrapInContainerStyles}
        `,
    },
};

const ProductCarouselProduct = ({
    carouselId,
    product,
    showImage,
    showBrand,
    showTitle,
    showPartNumbers,
    showPrice,
    showAddToCart,
    showAddToList,
    showImageBadges,
    maximumNumberOfImageBadges,
    showTextBadges,
    maximumNumberOfTextBadges,
    updateProductInfo,
    extendedStyles,
    productInfo,
    recommendationId,
    sendProductRecommendationTracking,
}: Props) => {
    const [styles] = useState(() => mergeToNew(productCarouselProductStyles, extendedStyles));

    const updateQuantity = (qtyOrdered: number) => {
        updateProductInfo({ id: carouselId, productId: product.id, qtyOrdered });
    };

    const updateUnitOfMeasure = (unitOfMeasure: string) => {
        updateProductInfo({ id: carouselId, productId: product.id, unitOfMeasure });
    };

    if (!product || !productInfo) {
        return null;
    }

    const productContext = {
        product,
        productInfo,
        onUnitOfMeasureChanged: updateUnitOfMeasure,
        onQtyOrderedChanged: updateQuantity,
    };

    const trackProductRecommendation = (isNewPageWasOpen: boolean) => {
        if (recommendationId) {
            sendProductRecommendationTracking({ recommendationId, isNewPageWasOpen });
        }
    };

    const { showOverlayBadge, overlayBadge, overlayBadgeWrapperStyles } = useOverlayBadge({
        productContext,
        showTextBadge: showTextBadges,
        showImageBadge: showImageBadges,
        styles,
    });

    const { imageBadges, textBadges } = useWidgetBadges({ productContext, showTextBadges, showImageBadges });

    return (
        <>
            <ProductContext.Provider value={productContext}>
                {showImage && !showOverlayBadge && (
                    <ProductImage
                        product={productContext}
                        onClick={() => trackProductRecommendation(true)}
                        extendedStyles={styles.productImageStyles}
                    />
                )}
                {showImage && showOverlayBadge && overlayBadge && (
                    <StyledWrapper {...styles.badgeAreaWrapper} data-test-selector="productCarouselBadge">
                        <ProductImage extendedStyles={styles.productImageStyles} product={productContext} />
                        <StyledWrapper {...overlayBadgeWrapperStyles}>
                            <Badge
                                type={overlayBadge.badgeType}
                                value={
                                    overlayBadge.badgeType === "Image"
                                        ? overlayBadge.largeImageBadgePath
                                        : overlayBadge.displayText
                                }
                                badgeTextColor={overlayBadge.textColorHexCode}
                                badgeBackgroundColor={overlayBadge.badgeColorHexCode}
                                badgeTextRounding={overlayBadge.badgeStyle === "Round" ? 20 : 0}
                                imageAltText={overlayBadge.imageAltText ? overlayBadge.imageAltText : overlayBadge.name}
                                textBadgeCss={styles.badgeText}
                                imageBadgeProps={styles.badgeImageProps}
                            />
                        </StyledWrapper>
                    </StyledWrapper>
                )}
                {showBrand && product.brand && (
                    <StyledWrapper {...styles.productBrandWrapper}>
                        <ProductBrand brand={product.brand} extendedStyles={styles.productBrandStyles} />
                    </StyledWrapper>
                )}
                {showTitle && (
                    <ProductDescription
                        product={productContext}
                        onClick={() => trackProductRecommendation(true)}
                        extendedStyles={styles.productDescriptionStyles}
                    />
                )}
                {showPartNumbers && (
                    <ProductPartNumbers
                        productNumber={product.productNumber}
                        customerProductNumber={product.customerProductNumber}
                        manufacturerItem={product.manufacturerItem}
                        showCustomerName={false}
                        showManufacturerItem={false}
                        extendedStyles={styles.productPartNumbersStyles}
                    />
                )}
                {showTextBadges && textBadges && (
                    <ProductTextBadges badgeList={textBadges} maxBadges={maximumNumberOfTextBadges ?? 4} />
                )}
                {showImageBadges && imageBadges && (
                    <ProductImageBadges badgeList={imageBadges} maxBadges={maximumNumberOfImageBadges ?? 4} />
                )}
                {showPrice && (
                    <StyledWrapper {...styles.productPriceWrapper}>
                        <VisuallyHidden as="label" htmlFor={`${carouselId}-uom`} id={`${carouselId}-uom-label`}>
                            {translate("U/M")}
                        </VisuallyHidden>
                        <ProductPrice showLabel={false} product={productContext} />
                        {product.unitOfMeasures && (
                            <ProductUnitOfMeasureSelect
                                labelOverride=""
                                extendedStyles={styles.productUnitOfMeasureSelectStyles}
                                id={`${carouselId}-uom`}
                            />
                        )}
                        <ProductQuantityBreakPricing extendedStyles={styles.productQuantityBreakPricingStyles} />
                    </StyledWrapper>
                )}
                {showAddToCart && (
                    <GridContainer {...styles.addToCartContainer}>
                        <GridItem {...styles.qtyGridItem}>
                            <VisuallyHidden as="label" htmlFor={`${carouselId}-qty`} id={`${carouselId}-qty-label`}>
                                {translate("QTY")}
                            </VisuallyHidden>
                            <ProductQuantityOrdered
                                labelOverride=""
                                extendedStyles={styles.productQuantityOrderedStyles}
                                id={`${carouselId}-qty`}
                            />
                        </GridItem>
                        <GridItem {...styles.addToCartButtonGridItem}>
                            <ProductAddToCartButton
                                onAddToCartClick={() => trackProductRecommendation(false)}
                                data-test-selector="addToCartBtn"
                                extendedStyles={styles.productAddToCartButtonStyles}
                            />
                        </GridItem>
                    </GridContainer>
                )}
                {showAddToList && (
                    <ProductAddToListLink
                        data-test-selector="addToListLink"
                        extendedStyles={styles.productAddToListLinkStyles}
                    />
                )}
            </ProductContext.Provider>
        </>
    );
};

export default connect(mapStateToProps, mapDispatchToProps)(ProductCarouselProduct);
