import mergeToNew from "@insite/client-framework/Common/mergeToNew";
import StyledWrapper from "@insite/client-framework/Common/StyledWrapper";
import ApplicationState from "@insite/client-framework/Store/ApplicationState";
import { getAddressFieldsDataView } from "@insite/client-framework/Store/Data/AddressFields/AddressFieldsSelector";
import { getBillToState } from "@insite/client-framework/Store/Data/BillTos/BillTosSelectors";
import { getCurrentCartState } from "@insite/client-framework/Store/Data/Carts/CartsSelector";
import { getCurrentCountries } from "@insite/client-framework/Store/Data/Countries/CountriesSelectors";
import { getPageLinkByPageType } from "@insite/client-framework/Store/Links/LinksSelectors";
import updateBillTo from "@insite/client-framework/Store/Pages/OnePageCheckout/Handlers/UpdateBillTo";
import translate from "@insite/client-framework/Translate";
import { BillToModel } from "@insite/client-framework/Types/ApiModels";
import BillToSelector, { BillToSelectorStyles } from "@insite/content-library/Components/BillToSelector";
import CustomerAddressForm, { CustomerAddressFormStyles } from "@insite/content-library/Components/CustomerAddressForm";
import Button, { ButtonPresentationProps } from "@insite/mobius/Button";
import Modal, { ModalPresentationProps } from "@insite/mobius/Modal";
import { HasToasterContext, withToaster } from "@insite/mobius/Toast/ToasterContext";
import { HasHistory, withHistory } from "@insite/mobius/utilities/HistoryContext";
import InjectableCss from "@insite/mobius/utilities/InjectableCss";
import React, { useState } from "react";
import { connect, ResolveThunks } from "react-redux";
import { css } from "styled-components";

interface OwnProps {
    isOpen: boolean;
    onModalClose: () => void;
    extendedStyles?: BillToSelectorModalStyles;
}

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

const mapStateToProps = (state: ApplicationState) => {
    const cart = getCurrentCartState(state).value;
    return {
        cartBillTo: getBillToState(state, cart?.billToId)?.value,
        cartPageUrl: getPageLinkByPageType(state, "CartPage")?.url,
        countries: getCurrentCountries(state),
        billToAddressFields: getAddressFieldsDataView(state).value?.billToAddressFields,
    };
};

const mapDispatchToProps = {
    updateBillTo,
};

export interface BillToSelectorModalStyles {
    modal?: ModalPresentationProps;
    billToSelector?: BillToSelectorStyles;
    buttonsWrapper?: InjectableCss;
    cancelButton?: ButtonPresentationProps;
    addCustomerAddressForm?: CustomerAddressFormStyles;
    editCustomerAddressForm?: CustomerAddressFormStyles;
}

export const billToSelectorModalStyles: BillToSelectorModalStyles = {
    modal: { sizeVariant: "medium" },
    buttonsWrapper: {
        css: css`
            display: flex;
            justify-content: flex-end;
            margin-top: 1rem;
        `,
    },
    cancelButton: { variant: "secondary" },
};

const BillToSelectorModal = ({
    cartBillTo,
    cartPageUrl,
    countries,
    billToAddressFields,
    isOpen,
    extendedStyles,
    history,
    toaster,
    updateBillTo,
    onModalClose,
}: Props) => {
    const [styles] = useState(() => mergeToNew(billToSelectorModalStyles, extendedStyles));

    const [billToBeingEdited, setBillToBeingEdited] = useState<BillToModel | undefined>(undefined);

    const selectBillToHandler = (billTo: BillToModel) => {
        onModalClose();
        updateBillTo({
            billTo,
            isEdit: false,
            onSuccess: hasCartlines => {
                if (!hasCartlines && cartPageUrl) {
                    history.push(cartPageUrl);
                }
            },
        });
    };

    const editBillToHandler = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>, billTo: BillToModel) => {
        event.preventDefault();
        setBillToBeingEdited(billTo);
    };

    const editBillToFormSubmitHandler = (_: React.FormEvent<HTMLFormElement>, billTo: BillToModel) => {
        updateBillTo({
            billTo,
            isEdit: true,
            onSuccess: hasCartlines => {
                toaster.addToast({
                    messageType: "success",
                    body: translate("Address updated."),
                });
                if (!hasCartlines && cartPageUrl) {
                    history.push(cartPageUrl);
                }
            },
        });
        setBillToBeingEdited(undefined);
        onModalClose();
    };

    const editAddressCancelHandler = () => {
        setBillToBeingEdited(undefined);
    };

    return (
        <Modal
            {...styles.modal}
            headline={billToBeingEdited ? translate("Edit Address") : translate("Address Book")}
            isOpen={isOpen}
            handleClose={onModalClose}
            data-test-selector="onePageCheckoutBilling_addressModal"
        >
            {!billToBeingEdited && (
                <>
                    <BillToSelector
                        onSelect={selectBillToHandler}
                        onEdit={editBillToHandler}
                        currentBillTo={cartBillTo}
                        extendedStyles={styles.billToSelector}
                    />
                    <StyledWrapper {...styles.buttonsWrapper}>
                        <Button {...styles.cancelButton} onClick={onModalClose}>
                            {translate("Cancel")}
                        </Button>
                    </StyledWrapper>
                </>
            )}
            {billToBeingEdited && countries && billToAddressFields && (
                <CustomerAddressForm
                    address={billToBeingEdited}
                    countries={countries}
                    addressFieldDisplayCollection={billToAddressFields}
                    onSubmit={editBillToFormSubmitHandler}
                    saveButtonTextOverride={translate("Save & Apply")}
                    onCancel={editAddressCancelHandler}
                    extendedStyles={styles.editCustomerAddressForm}
                />
            )}
        </Modal>
    );
};

export default connect(mapStateToProps, mapDispatchToProps)(withHistory(withToaster(BillToSelectorModal)));
