import useAppDispatch from "@insite/client-framework/Common/Hooks/useAppDispatch";
import useAppSelector from "@insite/client-framework/Common/Hooks/useAppSelector";
import siteMessage from "@insite/client-framework/SiteMessage";
import resetWishLists from "@insite/client-framework/Store/Data/WishLists/Handlers/ResetWishLists";
import { getWishListState } from "@insite/client-framework/Store/Data/WishLists/WishListsSelectors";
import addWishListTags from "@insite/client-framework/Store/Pages/MyListDetails/Handlers/AddWishListTags";
import removeWishListTags from "@insite/client-framework/Store/Pages/MyListDetails/Handlers/RemoveWishListTags";
import setWishListTags from "@insite/client-framework/Store/Pages/MyListDetails/Handlers/SetWishListTags";
import translate from "@insite/client-framework/Translate";
import { WishListTagModel } from "@insite/client-framework/Types/ApiModels";
import Button, { ButtonPresentationProps } from "@insite/mobius/Button";
import GridContainer, { GridContainerProps } from "@insite/mobius/GridContainer";
import GridItem, { GridItemProps } from "@insite/mobius/GridItem";
import X from "@insite/mobius/Icons/X";
import Modal, { ModalPresentationProps } from "@insite/mobius/Modal";
import TextField, { TextFieldPresentationProps } from "@insite/mobius/TextField";
import Typography, { TypographyProps } from "@insite/mobius/Typography";
import { injectCss, resolveColor } from "@insite/mobius/utilities";
import getColor from "@insite/mobius/utilities/getColor";
import InjectableCss from "@insite/mobius/utilities/InjectableCss";
import React, { useState } from "react";
import styled, { css } from "styled-components";

interface OwnProps {
    isOpen: boolean;
    handleClose(): void;
}

type Props = OwnProps;

export interface AddTagsModalStyles {
    modal?: ModalPresentationProps;
    container?: GridContainerProps;
    descriptionGridItem?: GridItemProps;
    descriptionText?: TypographyProps;
    tagsGridItem?: GridItemProps;
    buttonsGridItem?: GridItemProps;
    cancelButton?: ButtonPresentationProps;
    saveButton?: ButtonPresentationProps;
    instructionsStyle?: InjectableCss;
    tagsInstructionGridItem?: GridItemProps;
    tagsInstructionText?: TypographyProps;
    fakeTextFieldStyle?: InjectableCss;
    tagText?: TypographyProps;
    tagCloseText?: TypographyProps;
    tagInputText?: TextFieldPresentationProps;
}

export const addTagsModalStyles: AddTagsModalStyles = {
    modal: {
        cssOverrides: {
            modalTitle: css`
                align-items: flex-start;
                padding: 15px 30px;
            `,
            modalContent: css`
                padding: 20px 30px;
            `,
            modalBody: css`
                overflow-y: visible;
            `,
        },
    },
    descriptionGridItem: {
        width: 12,
    },
    tagsGridItem: {
        width: 12,
        css: css`
            padding: 0 15px;
        `,
    },
    buttonsGridItem: {
        width: 12,
        css: css`
            justify-content: flex-end;
        `,
    },
    cancelButton: {
        color: "secondary",
        css: css`
            margin-right: 10px;
        `,
    },
    tagsInstructionGridItem: {
        width: 12,
        css: css`
            padding: 0 15px;
        `,
    },
    tagsInstructionText: {
        css: css`
            font-size: 12px;
            color: ${props => props.theme.colors.text};
        `,
    },
    tagText: {
        css: css`
            display: flex;
            background: ${getColor("primary.main")};
            color: ${getColor("primary.contrast")};
            &:hover {
                background: #1b3f76;
            }
            border-radius: 4px;
            white-space: nowrap;
            margin-right: 6px;
            margin-bottom: 6px;
            padding: 2px 6px;
            font-size: 15px;
            align-items: center;
        `,
    },
    tagCloseText: {
        css: css`
            line-height: 12px;
            margin-left: 6px;
            cursor: pointer;
        `,
    },
    tagInputText: {
        css: css`
            width: 100%;
            background: transparent;
            border: none !important;
            flex-grow: 1;
            font-family: inherit;
            font-size: inherit;
            margin-bottom: 9px;
            &:focus {
                outline: none;
            }
        `,
    },
};

const FakeTextFieldStyle = styled.div<{ isFocused: boolean } & InjectableCss>`
    border-radius: 4px;
    border: 1px solid ${({ theme }) => theme.colors.common.border};
    font-size: 16px;
    line-height: 19px;
    font-weight: 300;
    color: black;
    width: 100%;
    background: ${({ theme }) => resolveColor(theme.formField?.defaultProps?.backgroundColor, theme)};
    padding: 8px 8px 2px;
    margin-top: 10px;
    display: flex;
    flex-wrap: wrap;
    box-sizing: border-box;
    ${props =>
        props.isFocused
            ? css`
                  border-color: ${props => props.theme.focus.color};
                  border-style: ${props => props.theme.focus.style};
                  border-width: ${props => props.theme.focus.width};
                  padding: 7px 5px 1px 7px;
              `
            : ""}
    ${injectCss}
`;

const styles = addTagsModalStyles;

const AddTagsModal = ({ isOpen, handleClose }: Props) => {
    const [tagsControlIsFocused, setTagsControlIsFocused] = useState(false);
    const [tagsValue, setTagsValue] = useState("");
    const wishListId = useAppSelector(state => state.pages.myListDetails.wishListId);
    const wishListDataView = useAppSelector(state => getWishListState(state, state.pages.myListDetails.wishListId));
    const tags = useAppSelector(state => state.pages.myListDetails.wishListTags);
    const addingWishListTags = useAppSelector(state => state.pages.myListDetails.addingWishListTags);
    const removingWishListTags = useAppSelector(state => state.pages.myListDetails.removingWishListTags);

    if (!wishListDataView.value) {
        return null;
    }

    const dispatch = useAppDispatch();
    const onChange = (event: React.FormEvent<HTMLInputElement>) => {
        setTagsValue(event.currentTarget.value.replace(/[^a-zA-Z0-9\-\_\s]/g, ""));
    };

    const addValue = (value: string) => {
        let currentArray = tags;
        if (!currentArray) {
            currentArray = [];
        }
        const nextValue = value?.trim().toLowerCase();
        if (nextValue && !currentArray.some(o => o.toLowerCase() === nextValue)) {
            currentArray = [...currentArray, nextValue];

            dispatch(setWishListTags({ wishListTags: currentArray }));
        }

        setTagsValue("");
        return currentArray;
    };

    const onKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
        if (event.key === "Enter") {
            addValue(event.currentTarget.value);
        }
    };

    const removeTag = (tag: string) => {
        const currentArray = [...tags];
        currentArray.splice(currentArray.indexOf(tag), 1);
        dispatch(setWishListTags({ wishListTags: currentArray }));
    };

    const onFocus = () => {
        setTagsControlIsFocused(true);
    };

    const onBlur = (event: React.FocusEvent<HTMLInputElement>) => {
        setTagsControlIsFocused(false);
        const newTags = addValue(tagsValue);
        const id = (event.relatedTarget as any)?.id;
        if (id === "addTagsModal_cancel") {
            handleClose();
        } else if (id === "addTagsModal_save") {
            save(newTags);
        }
    };

    const saveHandler = () => {
        save(tags);
    };

    const save = (newTags: string[]) => {
        const tagsSet = new Set(newTags.map(o => o.toLowerCase()));
        const currentTags = wishListDataView.value.wishListTags || [];
        const tagsToRemove = currentTags.filter(o => !tagsSet.has(o.tag.toLowerCase())).map(o => o.id);
        const currentTagsSet = new Set(currentTags.map(o => o.tag.toLowerCase()));
        const tagsToAdd = newTags
            .filter(o => !currentTagsSet.has(o.toLowerCase()))
            .map(o => {
                return { tag: o } as WishListTagModel;
            });

        if (wishListId && tagsToAdd.length) {
            dispatch(
                addWishListTags({
                    wishListId,
                    tags: tagsToAdd,
                    onComplete: () => {
                        if (!removingWishListTags) {
                            handleClose();
                            dispatch(resetWishLists());
                        }
                    },
                }),
            );
        }
        if (wishListId && tagsToRemove.length) {
            dispatch(
                removeWishListTags({
                    wishListId,
                    wishListTagIds: tagsToRemove,
                    onComplete: () => {
                        if (!addingWishListTags) {
                            handleClose();
                            dispatch(resetWishLists());
                        }
                    },
                }),
            );
        }

        if (!wishListId || (!tagsToAdd.length && !tagsToRemove.length)) {
            handleClose();
        }
    };

    return (
        <Modal {...styles.modal} handleClose={handleClose} headline={translate("Add Tags")} isOpen={isOpen} size={600}>
            <GridContainer {...styles.container} data-test-selector="addTagsForm">
                <GridItem {...styles.descriptionGridItem}>
                    <Typography {...styles.descriptionText}>{siteMessage("Lists_Add_Tags_Description")}</Typography>
                </GridItem>
                <GridItem {...styles.tagsGridItem}>
                    <FakeTextFieldStyle isFocused={tagsControlIsFocused} {...styles.fakeTextFieldStyle}>
                        {tags &&
                            tags.map(tag => (
                                <Typography {...styles.tagText} key={tag} data-test-selector={`addTagItem_${tag}`}>
                                    {tag}
                                    <Typography
                                        {...styles.tagCloseText}
                                        onClick={() => removeTag(tag)}
                                        data-test-selector={`removeAddTagItem_${tag}`}
                                    >
                                        <X />
                                    </Typography>
                                </Typography>
                            ))}
                        <TextField
                            {...styles.tagInputText}
                            disabled={addingWishListTags || removingWishListTags}
                            type="text"
                            value={tagsValue}
                            onChange={onChange}
                            onKeyPress={onKeyPress}
                            onFocus={onFocus}
                            onBlur={onBlur}
                            pattern="[0-9a-zA-Z_\-\s]"
                            maxLength={50}
                            data-test-selector="myListsAddTagsFormName"
                        />
                    </FakeTextFieldStyle>
                </GridItem>
                <GridItem {...styles.tagsInstructionGridItem}>
                    <Typography {...styles.tagsInstructionText}>
                        {translate('Type and press "Enter" to save')}
                    </Typography>
                </GridItem>
                <GridItem {...styles.buttonsGridItem}>
                    <Button
                        id="addTagsModal_cancel"
                        {...styles.cancelButton}
                        onClick={handleClose}
                        data-test-selector="myListsAddTagsFormCancel"
                    >
                        {translate("Cancel")}
                    </Button>
                    <Button
                        id="addTagsModal_save"
                        {...styles.saveButton}
                        disabled={addingWishListTags || removingWishListTags}
                        onClick={saveHandler}
                        data-test-selector="myListsAddTagsFormSubmit"
                    >
                        {translate("Save")}
                    </Button>
                </GridItem>
            </GridContainer>
        </Modal>
    );
};

export default AddTagsModal;
