import { getCookie } from "@insite/client-framework/Common/Cookies";
import StyledWrapper from "@insite/client-framework/Common/StyledWrapper";
import logger from "@insite/client-framework/Logger";
import ApplicationState from "@insite/client-framework/Store/ApplicationState";
import setSignInOverlayIsOpen from "@insite/client-framework/Store/Components/SignInOverlay/Handlers/SetSignInOverlayIsOpen";
import { getCurrentUserIsGuest, getIsPunchOutSession } from "@insite/client-framework/Store/Context/ContextSelectors";
import cancelPunchOut from "@insite/client-framework/Store/Context/Handlers/CancelPunchOut";
import setShowInventory from "@insite/client-framework/Store/Context/Handlers/SetShowInventory";
import setShowPricing from "@insite/client-framework/Store/Context/Handlers/SetShowPricing";
import signOut from "@insite/client-framework/Store/Context/Handlers/SignOut";
import { getCurrentPage, getLocation } from "@insite/client-framework/Store/Data/Pages/PageSelectors";
import { getPageLinkByPageType } from "@insite/client-framework/Store/Links/LinksSelectors";
import setIsReorderConfirmationModalOpen from "@insite/client-framework/Store/Pages/VmiBins/Handlers/SetIsReorderConfirmationModalOpen";
import setNextAction from "@insite/client-framework/Store/Pages/VmiBins/Handlers/SetNextAction";
import translate from "@insite/client-framework/Translate";
import WidgetModule from "@insite/client-framework/Types/WidgetModule";
import WidgetProps from "@insite/client-framework/Types/WidgetProps";
import { useMergeStyles } from "@insite/content-library/additionalStyles";
import { NavigationModeCookieName } from "@insite/content-library/Components/NavigationModeMenu";
import Clickable, { ClickablePresentationProps } from "@insite/mobius/Clickable";
import { BaseTheme } from "@insite/mobius/globals/baseTheme";
import Icon, { IconPresentationProps } from "@insite/mobius/Icon/Icon";
import Eye from "@insite/mobius/Icons/Eye";
import EyeOff from "@insite/mobius/Icons/EyeOff";
import User from "@insite/mobius/Icons/User";
import Menu, { MappedLink } from "@insite/mobius/Menu";
import Typography, { TypographyPresentationProps } from "@insite/mobius/Typography/Typography";
import { HasHistory, withHistory } from "@insite/mobius/utilities/HistoryContext";
import InjectableCss from "@insite/mobius/utilities/InjectableCss";
import React, { useEffect } from "react";
import { connect, ResolveThunks } from "react-redux";
import { css, ThemeProps, withTheme } from "styled-components";

const enum fields {
    visibilityState = "visibilityState",
    icon = "icon",
    includeAccountMenu = "includeAccountMenu",
    showPricingToggle = "showPricingToggle",
    showInventoryToggle = "showInventoryToggle",
}

const mapStateToProps = (state: ApplicationState) => ({
    isSignInPage: getCurrentPage(state).type === "SignInPage",
    userName: state.context.session.userName,
    myAccountPageLink: getPageLinkByPageType(state, "MyAccountPage"),
    signInUrl: getPageLinkByPageType(state, "SignInPage")?.url,
    currentUserIsGuest: getCurrentUserIsGuest(state),
    isPunchOutSession: getIsPunchOutSession(state),
    currentLocation: getLocation(state),
    displayChangeCustomerLink: state.context.session?.displayChangeCustomerLink || false,
    displayPricingAndInventory: state.context.session?.displayPricingAndInventory || false,
    showInventory: state.context.showInventory,
    showPricing: state.context.showPricing,
    isReorderConfirmationModalOpen: state.pages.vmiBins.isReorderConfirmationModalOpen,
    hasChangeLastQty:
        state.pages.vmiBins.selectVmiBinsChangedQty &&
        Object.keys(state.pages.vmiBins.selectVmiBinsChangedQty).length > 0,
});

const mapDispatchToProps = {
    signOut,
    cancelPunchOut,
    setSignInOverlayIsOpen,
    setShowInventory,
    setShowPricing,
    setIsReorderConfirmationModalOpen,
    setNextAction,
};

export interface HeaderSignInStyles {
    signOutWrapper?: InjectableCss;
    titleClickable?: ClickablePresentationProps;
    titleIcon?: IconPresentationProps;
    titleTypography?: TypographyPresentationProps;
    signOutClickable?: ClickablePresentationProps;
}

export const headerSignInStyles: HeaderSignInStyles = {
    signOutWrapper: {
        css: css`
            display: inline-flex;
            padding: 6px 0;
        `,
    },
    titleClickable: {
        css: css`
            margin-left: 10px;
        `,
    },
    titleIcon: {
        size: 22,
    },
    titleTypography: {
        css: css`
            margin-left: 10px;
            max-width: 150px;
        `,
        ellipsis: true,
        transform: "uppercase",
    },
    signOutClickable: {
        css: css`
            flex: 0 0 auto;
            margin-left: 16px;
            text-transform: uppercase;
        `,
    },
};

interface OwnProps extends WidgetProps {
    fields: {
        [fields.visibilityState]: string;
        [fields.icon]: string;
        [fields.includeAccountMenu]: boolean;
        [fields.showPricingToggle]: boolean;
        [fields.showInventoryToggle]: boolean;
    };
}

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

let icon: React.ComponentType<IconPresentationProps>;

export const HeaderSignIn = ({
    userName,
    isSignInPage,
    currentUserIsGuest,
    signOut,
    cancelPunchOut,
    fields,
    history,
    myAccountPageLink,
    signInUrl,
    isPunchOutSession,
    currentLocation,
    displayChangeCustomerLink,
    displayPricingAndInventory,
    showInventory,
    showPricing,
    setSignInOverlayIsOpen,
    setShowInventory,
    setShowPricing,
    theme,
    isReorderConfirmationModalOpen,
    hasChangeLastQty,
    setIsReorderConfirmationModalOpen,
    setNextAction,
}: Props) => {
    const styles = useMergeStyles("headerSignIn", headerSignInStyles);

    useEffect(() => {
        window.onpageshow = function (event) {
            if (event.persisted) {
                window.location.reload();
            }
        };
    }, [userName]);

    if (!myAccountPageLink) {
        return null;
    }

    const { visibilityState, includeAccountMenu, showInventoryToggle, showPricingToggle } = fields;
    const showIcon = visibilityState === "both" || visibilityState === "icon";
    const showLabel = visibilityState === "both" || visibilityState === "label";

    if (fields.icon === "User") {
        icon = User;
    }

    const currentMode = getCookie(NavigationModeCookieName);
    let menuItems = (myAccountPageLink?.children?.filter(
        pageLink => !(pageLink.type === "ChangeCustomerPage" && !displayChangeCustomerLink),
    ) ?? []) as MappedLink[];

    const getMenuItem = (title: "Inventory" | "Pricing"): MappedLink => {
        return {
            title: title === "Inventory" ? translate("Inventory") : translate("Pricing"),
            iconProps: {
                src: (title === "Inventory" && showInventory) || (title === "Pricing" && showPricing) ? EyeOff : Eye,
                size: 22,
                css: css`
                    margin-left: 20px;
                    margin-right: -12px;
                `,
            },
            clickableProps: {
                css: css`
                    display: flex;
                    text-transform: uppercase;
                `,
                onClick: () => {
                    title === "Inventory"
                        ? setShowInventory({ showInventory: !showInventory })
                        : setShowPricing({ showPricing: !showPricing });
                },
            },
        };
    };

    if (!currentMode || currentMode === "Storefront") {
        menuItems = menuItems?.filter(pageLink => pageLink.type !== "VmiUsersPage");

        showInventoryToggle && displayPricingAndInventory && menuItems.push(getMenuItem("Inventory"));
        showPricingToggle && displayPricingAndInventory && menuItems.push(getMenuItem("Pricing"));
    }

    const onSignInHandler = (e: React.MouseEvent) => {
        if ((!userName || currentUserIsGuest) && !isSignInPage) {
            e.preventDefault();

            if (theme.signIn?.useOverlay) {
                setSignInOverlayIsOpen({ isOpen: true });
                return;
            }

            if (!signInUrl) {
                logger.warn("No url was found for SignInPage, defaulting to /SignIn");
                history.push("/MyAccount/SignIn");
            } else {
                const returnUrl = currentLocation.pathname + currentLocation.search;
                if (returnUrl === "/") {
                    history.push(`${signInUrl}`);
                } else {
                    history.push(`${signInUrl}?returnUrl=${encodeURIComponent(returnUrl)}&clientRedirect=true`);
                }
            }
        }
    };

    const onSignOutHandler = () => {
        if (!isReorderConfirmationModalOpen && hasChangeLastQty) {
            setIsReorderConfirmationModalOpen({ isReorderConfirmationModalOpen: true });
            setNextAction({ nextAction: signOutFunc });
        } else {
            signOutFunc();
        }
    };

    const signOutFunc = () => {
        isPunchOutSession ? cancelPunchOut() : signOut();
    };

    let signInStatusText = translate("Sign In");
    if (userName && !currentUserIsGuest) {
        signInStatusText = userName;
    }

    return (
        <StyledWrapper {...styles.signOutWrapper}>
            {includeAccountMenu && userName && !currentUserIsGuest && (
                <Menu
                    descriptionId="accountMenu"
                    menuItems={menuItems}
                    displayChangeCustomerLink={displayChangeCustomerLink}
                    maxDepth={1}
                    menuTrigger={
                        <Clickable {...styles.titleClickable} data-test-selector="header_signIn">
                            {showIcon && <Icon {...styles.titleIcon} src={icon} />}
                            {showLabel && (
                                <Typography {...styles.titleTypography} data-test-selector="header_userName">
                                    {userName}
                                </Typography>
                            )}
                        </Clickable>
                    }
                    cssOverrides={{
                        wrapper: css`
                            flex: 0 1 auto;
                            min-width: 0;
                        `,
                    }}
                    data-test-selector="header_accountMenu"
                />
            )}
            {(!includeAccountMenu || !userName || (userName && currentUserIsGuest)) && (
                <Clickable
                    {...styles.titleClickable}
                    onClick={onSignInHandler}
                    href={!signInUrl ? "/MyAccount/SignIn" : signInUrl}
                    data-test-selector="header_signIn"
                >
                    {showIcon && <Icon {...styles.titleIcon} src={icon} />}
                    {showLabel && <Typography {...styles.titleTypography}>{signInStatusText}</Typography>}
                </Clickable>
            )}
            {userName && !currentUserIsGuest && (
                <Clickable
                    {...styles.signOutClickable}
                    onClick={onSignOutHandler}
                    data-test-selector="headerSignOutLink"
                >
                    {isPunchOutSession ? translate("Cancel PunchOut") : translate("Sign Out")}
                </Clickable>
            )}
        </StyledWrapper>
    );
};

const widgetModule: WidgetModule = {
    component: connect(mapStateToProps, mapDispatchToProps)(withHistory(withTheme(HeaderSignIn))),
    definition: {
        displayName: "Header Sign In",
        icon: "arrow-right-to-bracket",
        fieldDefinitions: [
            {
                name: fields.visibilityState,
                displayName: "Settings",
                editorTemplate: "RadioButtonsField",
                options: [
                    {
                        displayName: "Both",
                        value: "both",
                    },
                    {
                        displayName: "Show Label",
                        value: "label",
                    },
                    {
                        displayName: "Show Icon",
                        value: "icon",
                    },
                ],
                defaultValue: "both",
                fieldType: "General",
                sortOrder: 1,
            },
            {
                name: fields.icon,
                displayName: "SignIn Icon",
                editorTemplate: "DropDownField",
                options: [
                    {
                        displayName: "User",
                        value: "User",
                    },
                ],
                defaultValue: "User",
                fieldType: "General",
                sortOrder: 2,
            },
            {
                name: fields.includeAccountMenu,
                displayName: "Include My Account Menu",
                editorTemplate: "CheckboxField",
                defaultValue: true,
                fieldType: "General",
                sortOrder: 3,
            },
            {
                name: fields.showPricingToggle,
                displayName: "Show/Hide Pricing Toggle",
                editorTemplate: "CheckboxField",
                isVisible: widget => widget.fields.includeAccountMenu,
                defaultValue: false,
                fieldType: "General",
                sortOrder: 4,
            },
            {
                name: fields.showInventoryToggle,
                displayName: "Show/Hide Inventory Toggle",
                editorTemplate: "CheckboxField",
                isVisible: widget => widget.fields.includeAccountMenu,
                defaultValue: false,
                fieldType: "General",
                sortOrder: 5,
            },
        ],
        group: "Common",
    },
};

export default widgetModule;
