import React from "react";

import * as cssLinter from "css";
import { connect, ResolveThunks } from "react-redux";
import { css } from "styled-components";

import { DndContext, DragEndEvent, DraggableAttributes } from "@dnd-kit/core";
import { SyntheticListenerMap } from "@dnd-kit/core/dist/hooks/utilities";
import { SortableContext, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { ProductInfo } from "@insite/client-framework/Common/ProductInfo";
import StyledWrapper from "@insite/client-framework/Common/StyledWrapper";
import { SafeDictionary } from "@insite/client-framework/Common/Types";
import siteMessage from "@insite/client-framework/SiteMessage";
import ApplicationState from "@insite/client-framework/Store/ApplicationState";
import { getWishListLinesDataView } from "@insite/client-framework/Store/Data/WishListLines/WishListLinesSelectors";
import { getWishListState } from "@insite/client-framework/Store/Data/WishLists/WishListsSelectors";
import deleteWishListLine from "@insite/client-framework/Store/Pages/MyListDetails/Handlers/DeleteWishListLine";
import loadWishListLines from "@insite/client-framework/Store/Pages/MyListDetails/Handlers/LoadWishListLines";
import setQuantityAdjustmentModalIsOpen from "@insite/client-framework/Store/Pages/MyListDetails/Handlers/SetQuantityAdjustmentModalIsOpen";
import updateLoadWishListLinesParameter from "@insite/client-framework/Store/Pages/MyListDetails/Handlers/UpdateLoadWishListLinesParameter";
import updateWishListLine from "@insite/client-framework/Store/Pages/MyListDetails/Handlers/UpdateWishListLine";
import translate from "@insite/client-framework/Translate";
import { WishListLineModel, WishListModel } from "@insite/client-framework/Types/ApiModels";
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 MyListsDetailsProductListLine from "@insite/content-library/Widgets/MyListsDetails/MyListsDetailsProductListLine";
import ViewReplacementProductModal from "@insite/content-library/Widgets/MyListsDetails/ViewReplacementProductModal";
import Button, { ButtonPresentationProps } from "@insite/mobius/Button";
import GridContainer, { GridContainerProps } from "@insite/mobius/GridContainer";
import GridItem, { GridItemProps } from "@insite/mobius/GridItem";
import Icon, { IconPresentationProps } from "@insite/mobius/Icon";
import Move from "@insite/mobius/Icons/Move";
import LoadingSpinner, { LoadingSpinnerProps } from "@insite/mobius/LoadingSpinner";
import Modal, { ModalPresentationProps } from "@insite/mobius/Modal";
import { PaginationPresentationProps } from "@insite/mobius/Pagination";
import TextArea, { TextAreaProps } from "@insite/mobius/TextArea";
import TextField, { TextFieldProps } from "@insite/mobius/TextField";
import Typography, { TypographyPresentationProps } from "@insite/mobius/Typography";
import InjectableCss from "@insite/mobius/utilities/InjectableCss";

const enum fields {
    showImageBadges = "showImageBadges",
    maximumNumberOfImageBadges = "maximumNumberOfImageBadges",
    showTextBadges = "showTextBadges",
    maximumNumberOfTextBadges = "maximumNumberOfTextBadges",
    customCSS = "customCSS",
}

interface OwnProps extends WidgetProps {
    fields: {
        [fields.showImageBadges]: boolean;
        [fields.maximumNumberOfImageBadges]: number;
        [fields.showTextBadges]: boolean;
        [fields.maximumNumberOfTextBadges]: number;
        [fields.customCSS]: string;
    };
}

const mapStateToProps = (state: ApplicationState) => ({
    wishListDataView: getWishListState(state, state.pages.myListDetails.wishListId),
    wishListLinesDataView: getWishListLinesDataView(state, state.pages.myListDetails.loadWishListLinesParameter),
    productInfosByWishListLineId: state.pages.myListDetails.productInfosByWishListLineId,
    loadWishListLinesParameter: state.pages.myListDetails.loadWishListLinesParameter,
    editingSortOrder: state.pages.myListDetails.editingSortOrder,
    quantityAdjustmentModalIsOpen: state.pages.myListDetails.quantityAdjustmentModalIsOpen,
    removingWishListTags: state.pages.myListDetails.removingWishListTags,
});

const mapDispatchToProps = {
    updateLoadWishListLinesParameter,
    loadWishListLines,
    updateWishListLine,
    deleteWishListLine,
    setQuantityAdjustmentModalIsOpen,
};

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

export interface MyListsDetailsProductListStyles {
    centeringWrapper?: InjectableCss;
    spinner?: LoadingSpinnerProps;
    messageText?: TypographyPresentationProps;
    container?: GridContainerProps;
    lineGridItem?: GridItemProps;
    sortOrderWrapper?: InjectableCss;
    dragHandleIcon?: IconPresentationProps;
    sortOrderTextField?: TextFieldProps;
    editNotesModal?: ModalPresentationProps;
    paginationContainer?: GridContainerProps;
    paginationGridItem?: GridItemProps;
    pagination?: PaginationPresentationProps;
    notesTextArea?: TextAreaProps;
    editNotesModalButtonsWrapper?: InjectableCss;
    editNotesModalDeleteButton?: ButtonPresentationProps;
    editNotesModalCancelButton?: ButtonPresentationProps;
    editNotesModalSubmitButton?: ButtonPresentationProps;
    quantityAdjustmentModal?: ModalPresentationProps;
    quantityAdjustedText?: TypographyPresentationProps;
}

const defaultCustomCss = `.wrapper {
}

.wishlist-line-sort-order-wrapper{
}

.wishlist-line-sort-order-text-field{
}

.wishlist-restricted-line-grid-container{
}

.wishlist-restricted-line-description-grid-item{
}

.wishlist-restricted-line-description-text{
}

.wishlist-restricted-line-part-number-grid-item{
}

.wishlist-restricted-line-message-text{
}

.wishlist-restricted-line-buttons-grid-item{
}

.wishlist-line-grid-container{
}

.wishlist-line-edit-notes-link{
} 

.wishlist-line-description-grid-item{
}

.wishlist-line-notes-grid-item{
}

.wishlist-line-product-part-number-grid-item{
}

.wishlist-line-price-availability-grid-container{
}

.wishlist-line-purchased-date-grid-container{
}

.wishlist-line-purchased-date-label-text{
}

.wishlist-line-purchased-date-text{
}

.wishlist-line-price-grid-container{
}

.wishlist-line-uom-quantity-grid-container{
}

.wishlist-line-quantity-grid-item{
}

.wishlist-line-availability-grid-item{
}

.wishlist-line-buttons-grid-item{
}

.wishlist-line-delete-link{
}

.wishlist-line-update-quantity-wrapper{
}

.wishlist-line-update-quantity-link{
}

.wishlist-line-quantity-updated-icon{
}

.wishlist-line-quantity-updated-text{
}

.wishlist-discontinued-line-grid-container{
}

.wishlist-discontinued-line-description-grid-item{
}

.wishlist-discontinued-line-description-text{
}

.wishlist-discontinued-line-product-part-number-grid-item{
}

.wishlist-discontinued-line-chip-grid-item{
}

.wishlist-discontinued-line-view-replacement-link{
}

.wishlist-discontinued-line-delete-link{
}`;

const basicTab = {
    displayName: "Basic",
    sortOrder: 0,
};

const advancedTab = {
    displayName: "Advanced",
    sortOrder: 1,
};

export const productListStyles: MyListsDetailsProductListStyles = {
    centeringWrapper: {
        css: css`
            height: 300px;
            display: flex;
            align-items: center;
        `,
    },
    spinner: {
        css: css`
            margin: auto;
        `,
    },
    messageText: {
        variant: "h4",
        css: css`
            display: block;
            margin: auto;
        `,
    },
    container: {
        gap: 0,
        css: css`
            /* Note: below line is to prevent a weird behavior where chrome wants to print anything that will fit
            * comprehensively on a single page on that page, which means the product list appears on page 2
            when rendering a common 8-item list with no notes. That's not ideal, so we're arbitrarily making
            the component large enough that it won't fit on a single page. */
            @media print {
                padding-bottom: 120px;
            }
            border-top: 1px lightgray solid;
        `,
    },
    lineGridItem: {
        width: 12,
        css: css`
            border-bottom: 1px lightgray solid;
            padding: 20px 0;
        `,
    },
    sortOrderWrapper: {
        css: css`
            display: flex;
            flex-direction: column;
            align-items: center;
            width: 60px;
            margin-right: 12px;
        `,
    },
    dragHandleIcon: {
        src: Move,
        size: 22,
        css: css`
            cursor: move;
        `,
    },
    sortOrderTextField: {
        labelPosition: "top",
        labelProps: {
            size: 9,
            transform: "uppercase",
            css: css`
                min-height: auto;
                text-align: center;
            `,
        },
        cssOverrides: {
            formInputWrapper: css`
                input[type="number"]::-webkit-outer-spin-button,
                input[type="number"]::-webkit-inner-spin-button {
                    /* ISC-11023 deal with this. */
                    /* stylelint-disable-next-line */
                    -webkit-appearance: none;
                    margin: 0;
                }
            `,
            formField: css`
                margin-top: 10px;
            `,
            inputSelect: css`
                text-align: center;

                /* ISC-11023 deal with this. */
                /* stylelint-disable-next-line */
                -moz-appearance: textfield;
            `,
        },
    },
    editNotesModal: { sizeVariant: "small" },
    editNotesModalButtonsWrapper: {
        css: css`
            @media print {
                display: none;
            }
            margin-top: 30px;
            text-align: right;
        `,
    },
    editNotesModalDeleteButton: { variant: "secondary" },
    editNotesModalCancelButton: {
        variant: "secondary",
        css: css`
            margin-left: 10px;
        `,
    },
    editNotesModalSubmitButton: {
        css: css`
            margin-left: 10px;
        `,
    },
    quantityAdjustmentModal: { sizeVariant: "medium" },
};

const styles = productListStyles;

const MyListsDetailsProductList: React.FC<Props> = ({
    wishListDataView,
    wishListLinesDataView,
    productInfosByWishListLineId,
    loadWishListLinesParameter,
    editingSortOrder,
    quantityAdjustmentModalIsOpen,
    removingWishListTags,
    updateWishListLine,
    deleteWishListLine,
    setQuantityAdjustmentModalIsOpen,
    fields,
}) => {
    const [wishListLineToAction, setWishListLineToAction] = React.useState<WishListLineModel | null>(null);
    const [wishListLineToReplacement, setWishListLineToReplacement] = React.useState<WishListLineModel | null>(null);
    const [deleteLineModalIsOpen, setDeleteLineModalIsOpen] = React.useState(false);
    const [editNotesModalIsOpen, setEditNotesModalIsOpen] = React.useState(false);
    const [viewReplacementProductModalIsOpen, setViewReplacementModelIsOpen] = React.useState(false);
    const [isLoading, setIsLoading] = React.useState(false);
    const { showImageBadges, showTextBadges, maximumNumberOfImageBadges, maximumNumberOfTextBadges } = fields;

    if (
        isLoading ||
        !wishListDataView.value ||
        !wishListLinesDataView.value ||
        wishListLinesDataView.isLoading ||
        !wishListLinesDataView.pagination ||
        removingWishListTags
    ) {
        return (
            <StyledWrapper {...styles.centeringWrapper}>
                <LoadingSpinner {...styles.spinner} />
            </StyledWrapper>
        );
    }

    const wishList = wishListDataView.value;
    const wishListLines = wishListLinesDataView.value;

    const deleteCancelHandler = () => {
        setDeleteLineModalIsOpen(false);
    };

    const deleteSubmitHandler = () => {
        if (!wishListLineToAction) {
            return;
        }

        deleteWishListLine({
            wishListId: wishList.id,
            wishListLineId: wishListLineToAction.id,
            onSuccess: () => {
                setDeleteLineModalIsOpen(false);
            },
            onComplete() {
                // "this" is targeting the object being created, not the parent SFC
                this.onSuccess?.();
            },
        });
    };

    const deleteClickHandler = (wishListLine: WishListLineModel) => {
        setWishListLineToAction(wishListLine);
        setDeleteLineModalIsOpen(true);
    };

    const editNotesModalCancelHandler = () => {
        setEditNotesModalIsOpen(false);
    };

    const editNotesClickHandler = (wishListLine: WishListLineModel) => {
        setWishListLineToAction(wishListLine);
        setEditNotesModalIsOpen(true);
    };

    const viewReplacementProductClickHandler = (wishListLine: WishListLineModel) => {
        setWishListLineToReplacement(wishListLine);
        setViewReplacementModelIsOpen(true);
    };

    const viewReplacementProductCancelHandler = () => {
        setViewReplacementModelIsOpen(false);
    };

    const editNotesModalSubmitHandler = (notes: string) => {
        const wishListLineToUpdate = { ...wishListLineToAction, notes } as WishListLineModel;
        updateWishListLine({
            wishListId: wishList.id,
            wishListLineId: wishListLineToUpdate.id,
            wishListLine: wishListLineToUpdate,
            skipResettingData: true,
            onSuccess: () => {
                setEditNotesModalIsOpen(false);
            },
            onComplete(resultProps) {
                if (resultProps.result?.wishListLine) {
                    // "this" is targeting the object being created, not the parent SFC

                    this.onSuccess?.();
                }
            },
        });
    };

    const updateSortOrder = (wishListLine: WishListLineModel, value: number | string) => {
        const sortOrder = parseInt(value.toString() || "1", 10);
        if (wishListLine.sortOrder === sortOrder) {
            return;
        }

        setIsLoading(true);
        const wishListLineToUpdate = { ...wishListLine, sortOrder };
        updateWishListLine({
            wishListId: wishList.id,
            wishListLineId: wishListLineToUpdate.id,
            wishListLine: wishListLineToUpdate,
            onComplete: () => {
                setIsLoading(false);
            },
        });
    };

    const quantityAdjustmentModalCancelHandler = () => {
        setQuantityAdjustmentModalIsOpen({ modalIsOpen: false });
    };

    if (!wishListLines || wishListLines.length === 0 || Object.keys(productInfosByWishListLineId).length === 0) {
        return (
            <StyledWrapper {...styles.centeringWrapper}>
                <Typography {...styles.messageText} data-test-selector="myListDetails_noItemsMessage">
                    {loadWishListLinesParameter.query
                        ? siteMessage("Lists_NoResultsMessage")
                        : siteMessage("Lists_NoItemsInList")}
                </Typography>
            </StyledWrapper>
        );
    }

    const customCssWrapper = {
        css: css`
            ${fields.customCSS}
        `,
    };

    return (
        <StyledWrapper {...customCssWrapper}>
            <>
                <LinesContainer
                    wishList={wishList}
                    wishListLines={wishListLines}
                    productInfosByWishListLineId={productInfosByWishListLineId}
                    editingSortOrder={editingSortOrder && !loadWishListLinesParameter.query}
                    canDrag={wishListLinesDataView.pagination.numberOfPages === 1}
                    updateSortOrder={updateSortOrder}
                    onDeleteClick={deleteClickHandler}
                    onEditNotesClick={editNotesClickHandler}
                    onDragEnd={(event: DragEndEvent) => {
                        const { active, over } = event;
                        if (over && over.id && active.id !== over?.id) {
                            const oldIndex = wishListLines.findIndex(wishListLine => wishListLine.id === active.id);
                            const newIndex = wishListLines.findIndex(wishListLine => wishListLine.id === over.id);
                            updateSortOrder(wishListLines[oldIndex], newIndex + 1);
                        }
                    }}
                    showImageBadges={showImageBadges}
                    showTextBadges={showTextBadges}
                    maximumNumberOfImageBadges={maximumNumberOfImageBadges}
                    maximumNumberOfTextBadges={maximumNumberOfTextBadges}
                    onViewProductReplacement={viewReplacementProductClickHandler}
                />
                <TwoButtonModal
                    modalIsOpen={deleteLineModalIsOpen}
                    headlineText={translate("Delete List Item")}
                    messageText={`${translate("Are you sure you want to delete this item?")}`}
                    cancelButtonText={translate("Cancel")}
                    submitButtonText={translate("Delete")}
                    onCancel={deleteCancelHandler}
                    onSubmit={deleteSubmitHandler}
                    submitTestSelector="submitDeleteListItem"
                />
                {wishListLineToAction && (
                    <Modal
                        {...styles.editNotesModal}
                        headline={translate(`${wishListLineToAction.notes ? "Edit" : "Add"} Notes`)}
                        isOpen={editNotesModalIsOpen}
                        handleClose={editNotesModalCancelHandler}
                    >
                        <EditNotesForm
                            wishListLine={wishListLineToAction}
                            onCancel={editNotesModalCancelHandler}
                            onSubmit={editNotesModalSubmitHandler}
                        />
                    </Modal>
                )}
                <Modal
                    {...styles.quantityAdjustmentModal}
                    headline={translate("Quantity Adjustment Has Been Made")}
                    isOpen={quantityAdjustmentModalIsOpen}
                    handleClose={quantityAdjustmentModalCancelHandler}
                >
                    <Typography {...styles.quantityAdjustedText}>{siteMessage("Lists_QuantitiesAdjusted")}</Typography>
                </Modal>

                {wishListLineToReplacement && (
                    <ViewReplacementProductModal
                        isOpen={viewReplacementProductModalIsOpen}
                        handleClose={viewReplacementProductCancelHandler}
                        wishList={wishList}
                        wishListLine={wishListLineToReplacement}
                        wishListLines={wishListLines}
                    />
                )}
            </>
        </StyledWrapper>
    );
};

const DragHandle = ({ listeners, attributes }: DragHandleProps) => (
    <Icon
        {...styles.dragHandleIcon}
        data-test-selector="myListDetailPage_DragSortOrder"
        {...listeners}
        {...attributes}
    />
);

interface DragHandleProps {
    listeners: SyntheticListenerMap | undefined;
    attributes: DraggableAttributes;
}

interface LineItemProps {
    id: string;
    wishList: WishListModel;
    wishListLine: WishListLineModel;
    productInfo: ProductInfo;
    editingSortOrder: boolean;
    canDrag: boolean;
    updateSortOrder: (wishListLine: WishListLineModel, value: number | string) => void;
    onDeleteClick: (wishListLine: WishListLineModel) => void;
    onEditNotesClick: (wishListLine: WishListLineModel) => void;
    showImageBadges: boolean;
    showTextBadges: boolean;
    maximumNumberOfImageBadges: number;
    maximumNumberOfTextBadges: number;
    onViewReplacementProduct: (wishListLine: WishListLineModel) => void;
}

const LineItem = ({
    id,
    wishList,
    wishListLine,
    productInfo,
    editingSortOrder,
    canDrag,
    updateSortOrder,
    onDeleteClick,
    onEditNotesClick,
    showImageBadges,
    showTextBadges,
    maximumNumberOfImageBadges,
    maximumNumberOfTextBadges,
    onViewReplacementProduct,
}: LineItemProps) => {
    const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
    const style = {
        transform: CSS.Transform.toString(transform),
        transition,
    };
    const sortOrderBlurHandler = (event: React.FocusEvent<HTMLInputElement>) => {
        updateSortOrder(wishListLine, event.target.value);
    };

    const sortOrderKeyPressHandler = (event: React.KeyboardEvent<HTMLInputElement>) => {
        if (event.which === 13) {
            (event.target as any).blur();
        }
    };

    return (
        <GridItem {...styles.lineGridItem} data-test-selector="myListDetails_line" ref={setNodeRef} style={style}>
            {editingSortOrder && (
                <StyledWrapper {...styles.sortOrderWrapper} className="wishlist-line-sort-order-wrapper">
                    {canDrag && <DragHandle listeners={listeners} attributes={attributes} />}
                    <TextField
                        {...styles.sortOrderTextField}
                        className="wishlist-line-sort-order-text-field"
                        label={translate("Sort Order")}
                        type="number"
                        min={1}
                        defaultValue={wishListLine.sortOrder}
                        onBlur={sortOrderBlurHandler}
                        onKeyPress={sortOrderKeyPressHandler}
                        data-test-selector="myListDetailPage_inputSortOrderLine"
                    />
                </StyledWrapper>
            )}
            <MyListsDetailsProductListLine
                wishList={wishList}
                wishListLine={wishListLine}
                productInfo={productInfo}
                onDeleteClick={onDeleteClick}
                onEditNotesClick={onEditNotesClick}
                showImageBadges={showImageBadges}
                showTextBadges={showTextBadges}
                maximumNumberOfImageBadges={maximumNumberOfImageBadges}
                maximumNumberOfTextBadges={maximumNumberOfTextBadges}
                onViewReplacementProduct={onViewReplacementProduct}
            />
        </GridItem>
    );
};

interface LinesContainerProps {
    wishList: WishListModel;
    wishListLines: WishListLineModel[];
    productInfosByWishListLineId: SafeDictionary<ProductInfo>;
    editingSortOrder: boolean;
    canDrag: boolean;
    updateSortOrder: (wishListLine: WishListLineModel, value: number | string) => void;
    onDeleteClick: (wishListLine: WishListLineModel) => void;
    onEditNotesClick: (wishListLine: WishListLineModel) => void;
    showImageBadges: boolean;
    showTextBadges: boolean;
    maximumNumberOfImageBadges: number;
    maximumNumberOfTextBadges: number;
    onViewProductReplacement: (wishListLine: WishListLineModel) => void;
    onDragEnd: (event: DragEndEvent) => void;
}

const LinesContainer = ({
    wishList,
    wishListLines,
    productInfosByWishListLineId,
    editingSortOrder,
    canDrag,
    updateSortOrder,
    onDeleteClick,
    onEditNotesClick,
    showImageBadges,
    showTextBadges,
    maximumNumberOfImageBadges,
    maximumNumberOfTextBadges,
    onViewProductReplacement,
    onDragEnd,
}: LinesContainerProps) => {
    const items = wishListLines.filter(wishListLine => !!productInfosByWishListLineId[wishListLine.id]);
    return (
        <DndContext onDragEnd={onDragEnd}>
            <GridContainer {...styles.container} className="wrapper" data-test-selector="myListDetails_lines">
                <SortableContext items={items} strategy={verticalListSortingStrategy}>
                    {items.map(wishListLine => (
                        <LineItem
                            id={wishListLine.id}
                            key={`${wishListLine.productId}_${wishListLine.selectedUnitOfMeasure}`}
                            wishList={wishList}
                            wishListLine={wishListLine}
                            productInfo={productInfosByWishListLineId[wishListLine.id]!}
                            editingSortOrder={editingSortOrder}
                            canDrag={canDrag}
                            updateSortOrder={updateSortOrder}
                            onDeleteClick={onDeleteClick}
                            onEditNotesClick={onEditNotesClick}
                            showImageBadges={showImageBadges}
                            showTextBadges={showTextBadges}
                            maximumNumberOfImageBadges={maximumNumberOfImageBadges}
                            maximumNumberOfTextBadges={maximumNumberOfTextBadges}
                            onViewReplacementProduct={onViewProductReplacement}
                        />
                    ))}
                </SortableContext>
            </GridContainer>
        </DndContext>
    );
};

interface EditNotesFormProps {
    wishListLine: WishListLineModel;
    onCancel: () => void;
    onSubmit: (notes: string) => void;
}

const EditNotesForm: React.FC<EditNotesFormProps> = ({ wishListLine, onCancel, onSubmit }) => {
    const [notes, setNotes] = React.useState(wishListLine.notes);
    const notesChangeHandler = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
        setNotes(event.target.value.length > 300 ? event.target.value.slice(0, 300) : event.target.value);
    };

    const deleteHandler = () => {
        setNotes("");
        onSubmit("");
    };

    return (
        <>
            <TextArea
                {...styles.notesTextArea}
                value={notes}
                onChange={notesChangeHandler}
                hint={`${300 - notes.length} ${translate("characters left")}`}
                data-test-selector="myLists_editNote"
            />
            <StyledWrapper {...styles.editNotesModalButtonsWrapper}>
                {wishListLine.notes && (
                    <Button
                        {...styles.editNotesModalDeleteButton}
                        onClick={deleteHandler}
                        data-test-selector="myLists_deleteNoteButton"
                    >
                        {translate("Delete Note")}
                    </Button>
                )}
                <Button
                    {...styles.editNotesModalCancelButton}
                    onClick={onCancel}
                    data-test-selector="myLists_cancelNoteButton"
                >
                    {translate("Cancel")}
                </Button>
                <Button
                    {...styles.editNotesModalSubmitButton}
                    onClick={() => onSubmit(notes)}
                    data-test-selector="myLists_submitNoteButton"
                >
                    {translate(`${wishListLine.notes ? "Save" : "Add Notes"}`)}
                </Button>
            </StyledWrapper>
        </>
    );
};

const widgetModule: WidgetModule = {
    component: connect(mapStateToProps, mapDispatchToProps)(MyListsDetailsProductList),
    definition: {
        group: "My Lists Details",
        displayName: "Product List",
        allowedContexts: ["MyListsDetailsPage"],
        fieldDefinitions: [
            {
                name: fields.showImageBadges,
                displayName: "Image Badges",
                editorTemplate: "CheckboxField",
                defaultValue: false,
                fieldType: "General",
                sortOrder: 1,
                tab: basicTab,
            },
            {
                name: fields.maximumNumberOfImageBadges,
                editorTemplate: "DropDownField",
                isVisible: widget => widget.fields.showImageBadges,
                defaultValue: "4",
                options: [
                    { displayName: "1", value: "1" },
                    { displayName: "2", value: "2" },
                    { displayName: "3", value: "3" },
                    { displayName: "4", value: "4" },
                    { displayName: "5", value: "5" },
                    { displayName: "6", value: "6" },
                    { displayName: "7", value: "7" },
                    { displayName: "8", value: "8" },
                ],
                fieldType: "General",
                sortOrder: 2,
                tab: basicTab,
            },
            {
                name: fields.showTextBadges,
                displayName: "Text Badges",
                editorTemplate: "CheckboxField",
                defaultValue: false,
                fieldType: "General",
                sortOrder: 3,
                tab: basicTab,
            },
            {
                name: fields.maximumNumberOfTextBadges,
                editorTemplate: "DropDownField",
                isVisible: widget => widget.fields.showTextBadges,
                defaultValue: "4",
                options: [
                    { displayName: "1", value: "1" },
                    { displayName: "2", value: "2" },
                    { displayName: "3", value: "3" },
                    { displayName: "4", value: "4" },
                    { displayName: "5", value: "5" },
                    { displayName: "6", value: "6" },
                    { displayName: "7", value: "7" },
                    { displayName: "8", value: "8" },
                ],
                fieldType: "General",
                sortOrder: 4,
                tab: basicTab,
            },
            {
                name: fields.customCSS,
                displayName: "Custom CSS",
                editorTemplate: "CodeField",
                fieldType: "General",
                tab: advancedTab,
                defaultValue: defaultCustomCss,
                isVisible: (item, shouldDisplayAdvancedFeatures) => !!shouldDisplayAdvancedFeatures,
                validate: value => {
                    if (value === undefined || value === null) {
                        return "";
                    }

                    const result = cssLinter.parse(value, { silent: true });
                    if (result?.stylesheet?.parsingErrors) {
                        // the error output at this time only has room for one line so we just show the first error
                        return result.stylesheet.parsingErrors.length <= 0
                            ? ""
                            : result.stylesheet.parsingErrors.map(error => `${error.reason} on line ${error.line}`)[0];
                    }

                    return "Unable to parse Css";
                },
                options: {
                    mode: "css",
                    lint: true,
                    autoRefresh: true,
                },
            },
        ],
    },
};

export default widgetModule;
