import StyledWrapper from "@insite/client-framework/Common/StyledWrapper";
import getFileExtension from "@insite/client-framework/Common/Utilities/getFileExtension";
import { makeHandlerChainAwaitable } from "@insite/client-framework/HandlerCreator";
import siteMessage from "@insite/client-framework/SiteMessage";
import ApplicationState from "@insite/client-framework/Store/ApplicationState";
import cleanupUploadData from "@insite/client-framework/Store/Components/VmiLocationsImportModal/Handlers/CleanupUploadData";
import processFile from "@insite/client-framework/Store/Components/VmiLocationsImportModal/Handlers/ProcessFile";
import setAllowCancel from "@insite/client-framework/Store/Components/VmiLocationsImportModal/Handlers/SetAllowCancel";
import setErrorsModalIsOpen from "@insite/client-framework/Store/Components/VmiLocationsImportModal/Handlers/SetErrorsModalIsOpen";
import setIsBadFile from "@insite/client-framework/Store/Components/VmiLocationsImportModal/Handlers/SetIsBadFile";
import setIsUploading from "@insite/client-framework/Store/Components/VmiLocationsImportModal/Handlers/SetIsUploading";
import setUploadCancelled from "@insite/client-framework/Store/Components/VmiLocationsImportModal/Handlers/SetUploadCancelled";
import setUploadLimitExceeded from "@insite/client-framework/Store/Components/VmiLocationsImportModal/Handlers/SetUploadLimitExceeded";
import setVmiLocationsImportModalIsOpen from "@insite/client-framework/Store/Components/VmiLocationsImportModal/Handlers/SetVmiLocationsImportModalIsOpen";
import uploadVmiLocations from "@insite/client-framework/Store/Components/VmiLocationsImportModal/Handlers/UploadVmiLocations";
import validateVmiLocations from "@insite/client-framework/Store/Components/VmiLocationsImportModal/Handlers/ValidateVmiLocations";
import translate from "@insite/client-framework/Translate";
import { VmiLocationCollectionModel } from "@insite/client-framework/Types/ApiModels";
import Button, { ButtonPresentationProps } from "@insite/mobius/Button";
import Checkbox, { CheckboxPresentationProps, CheckboxProps } from "@insite/mobius/Checkbox";
import FileUpload, { FileUploadPresentationProps } from "@insite/mobius/FileUpload";
import GridContainer, { GridContainerProps } from "@insite/mobius/GridContainer";
import GridItem, { GridItemProps } from "@insite/mobius/GridItem";
import Link, { LinkPresentationProps } from "@insite/mobius/Link";
import LoadingSpinner, { LoadingSpinnerProps } from "@insite/mobius/LoadingSpinner";
import Modal, { ModalPresentationProps } from "@insite/mobius/Modal";
import Typography, { TypographyPresentationProps } from "@insite/mobius/Typography";
import getColor from "@insite/mobius/utilities/getColor";
import InjectableCss from "@insite/mobius/utilities/InjectableCss";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { connect, ResolveThunks } from "react-redux";
import { css } from "styled-components";

const mapStateToProps = (state: ApplicationState) => {
    return {
        isUploading: state.components.vmiLocationsImportModal.isUploading,
        vmiLocationsProcessed: state.components.vmiLocationsImportModal.vmiLocationsProcessed,
        errorEntries: state.components.vmiLocationsImportModal.errorEntries,
        isBadFile: state.components.vmiLocationsImportModal.isBadFile,
        fullFileError: state.components.vmiLocationsImportModal.fullFileError,
        importedItems: state.components.vmiLocationsImportModal.importedItems,
        allowCancel: state.components.vmiLocationsImportModal.allowCancel,
        uploadCancelled: state.components.vmiLocationsImportModal.uploadCancelled,
        uploadLimitExceeded: state.components.vmiLocationsImportModal.uploadLimitExceeded,
        isOpen: state.components.vmiLocationsImportModal.modalIsOpen,
        continueUpload: state.components.vmiLocationsImportModal.continueUpload,
    };
};

const mapDispatchToProps = {
    processFile,
    cleanupUploadData,
    setAllowCancel,
    validateVmiLocations,
    setUploadLimitExceeded,
    setErrorsModalIsOpen,
    setIsBadFile,
    setIsUploading,
    setUploadCancelled,
    setVmiLocationsImportModalIsOpen,
    uploadVmiLocations: makeHandlerChainAwaitable<Parameters<typeof uploadVmiLocations>[0], VmiLocationCollectionModel>(
        uploadVmiLocations,
    ),
};

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

export interface VmiLocationsImportModalStyles {
    modal?: ModalPresentationProps;
    container?: GridContainerProps;

    uploadInputGridItem?: GridItemProps;
    controlsGridItem?: GridItemProps;
    firstRowOptionCheckbox?: CheckboxPresentationProps;
    uploadButton?: ButtonPresentationProps;
    instructionGridItem?: GridItemProps;
    instructionText?: TypographyPresentationProps;

    fileUploader?: FileUploadPresentationProps;
    templateLink?: LinkPresentationProps;

    uploadingModal?: ModalPresentationProps;
    centeringWrapper?: InjectableCss;
    spinner?: LoadingSpinnerProps;
    uploadingModalText?: TypographyPresentationProps;
    cancelUploadButton?: ButtonPresentationProps;

    uploadsuccessModal?: ModalPresentationProps;
    returnToVmiLocationsButton?: ButtonPresentationProps;
}

export const vmiLocationsImportModalStyles: VmiLocationsImportModalStyles = {
    modal: {
        cssOverrides: {
            modalBody: css`
                overflow: visible;
            `,
        },
    },
    container: { gap: 15 },
    uploadInputGridItem: { width: 6 },
    controlsGridItem: {
        width: 12,
        css: css`
            display: block;
            border: 1px solid ${getColor("common.border")};
            padding: 20px;
        `,
    },
    firstRowOptionCheckbox: {
        css: css`
            margin: 15px 0;
            display: block;
        `,
    },
    uploadButton: {
        css: css`
            float: right;
        `,
    },
    instructionGridItem: { width: 6 },
    instructionText: {
        css: css`
            margin-bottom: 12px;
        `,
    },
    fileUploader: {
        buttonProps: {
            variant: "tertiary",
        },
    },
    centeringWrapper: {
        css: css`
            height: 50px;
            display: flex;
            align-items: center;
        `,
    },
    uploadingModal: {
        cssOverrides: {
            modalTitle: css`
                border-bottom: none;
                padding: 0;
            `,
            modalContent: css`
                text-align: center;
            `,
        },
    },
    spinner: {
        css: css`
            margin: 0 auto;
        `,
    },
    uploadingModalText: {
        css: css`
            margin: 15px 0;
        `,
    },
    uploadsuccessModal: {
        headlineTypographyProps: {
            size: 19,
            color: "success.main",
        },
        cssOverrides: {
            modalTitle: css`
                border-bottom: none;
            `,
            modalContent: css`
                padding: 0 30px 25px 30px;
            `,
        },
    },
};

const styles = vmiLocationsImportModalStyles;

const VmiLocationsImportModal = ({
    isOpen,
    isUploading,
    vmiLocationsProcessed,
    errorEntries,
    isBadFile,
    fullFileError,
    importedItems,
    allowCancel,
    uploadCancelled,
    uploadLimitExceeded,
    continueUpload,
    processFile,
    cleanupUploadData,
    setAllowCancel,
    validateVmiLocations,
    setUploadLimitExceeded,
    setErrorsModalIsOpen,
    setIsBadFile,
    setIsUploading,
    setUploadCancelled,
    setVmiLocationsImportModalIsOpen,
    uploadVmiLocations,
}: Props) => {
    const fileUploadRef = useRef({ value: "" } as HTMLInputElement);

    const [file, setFile] = useState<any>(null);
    const [incorrectFileExtension, setIncorrectFileExtension] = React.useState(false);
    const [firstRowHeading, setFirstRowHeading] = useState(true);
    const [uploadedItemsCount, setUploadedItemsCount] = useState(0);

    const [isUploadingModalOpen, setIsUploadingModalOpen] = useState(false);
    const [isUploadSuccessModalOpen, setIsUploadSuccessModalOpen] = useState(false);

    useEffect(() => {
        if (isUploading) {
            setVmiLocationsImportModalIsOpen({ modalIsOpen: false });
            setIsUploadingModalOpen(true);
            cleanupUploadData();
            validateVmiLocations({ firstRowHeading: false, validationOnly: true });
        }
    }, [isUploading]);

    useEffect(() => checkCompletion(), [vmiLocationsProcessed]);

    useEffect(() => {
        if (!isOpen) {
            resetState();
            cleanupUploadData();
        }
    }, [isOpen]);

    useEffect(() => {
        if (continueUpload) {
            uploadLocations();
        }
    }, [continueUpload]);

    const checkCompletion = useCallback(() => {
        if (!vmiLocationsProcessed || uploadCancelled) {
            return;
        }

        if (importedItems && errorEntries.length === 0 && !fullFileError) {
            uploadLocations();
        } else {
            setIsUploadingModalOpen(false);
            setErrorsModalIsOpen({ errorsModalIsOpen: true });
        }
    }, [vmiLocationsProcessed, uploadCancelled, errorEntries]);

    const resetState = () => {
        setFile(null);
        setIncorrectFileExtension(false);
        setUploadLimitExceeded({ uploadLimitExceeded: false });
        setIsBadFile({ isBadFile: false });
        setErrorsModalIsOpen({ errorsModalIsOpen: false });
    };

    const closeModalHandler = () => {
        setIsUploading({ isUploading: false });
        setVmiLocationsImportModalIsOpen({ modalIsOpen: false });
    };

    const firstRowHeadingChangeHandler: CheckboxProps["onChange"] = (_, value) => setFirstRowHeading(value);

    const uploadLocations = async () => {
        setAllowCancel({ allowCancel: false });
        await uploadVmiLocations({ vmiLocations: importedItems, validationOnly: false });
        onUploadingSuccess();
    };

    const onUploadingSuccess = () => {
        setIsUploadingModalOpen(false);
        setUploadedItemsCount(importedItems.length);
        setIsUploading({ isUploading: false });
        setIsUploadSuccessModalOpen(true);
        cleanupUploadData();
    };

    const cancelUploadingHandler = () => {
        setUploadCancelled({ uploadCancelled: true });
        setIsUploadingModalOpen(false);
        setIsUploading({ isUploading: false });
        cleanupUploadData();
        setFile(null);
        if (fileUploadRef.current?.value) {
            fileUploadRef.current.value = "";
        }
        setFirstRowHeading(true);
    };

    const returnToVmiLocationsHandler = () => {
        setIsUploadSuccessModalOpen(false);
    };

    const fileChangeHandler = (event: React.ChangeEvent<any>) => {
        const uploadedFile = event.target.files[0];
        setFile(uploadedFile);
        if (uploadedFile) {
            const fileExtension = getFileExtension(uploadedFile.name);
            const incorrectFileExtension = ["xls", "xlsx", "csv"].indexOf(fileExtension) === -1;
            setIncorrectFileExtension(incorrectFileExtension);
            setIsBadFile({ isBadFile: incorrectFileExtension });
            setUploadLimitExceeded({ uploadLimitExceeded: false });
        }
    };

    const onUploadClick = () => {
        setUploadCancelled({ uploadCancelled: false });

        const reader = new FileReader();
        reader.onload = onReaderLoad(getFileExtension(file.name));
        reader.readAsArrayBuffer(file);
    };

    const onReaderLoad = (fileExtension: string) => {
        return (e: Event) => {
            const data = (e.target as any).result;
            processFile({ data, fileExtension, firstRowHeading });
        };
    };

    return (
        <>
            <Modal
                {...styles.modal}
                handleClose={() => closeModalHandler()}
                headline={translate("Import Locations")}
                data-test-selector="vmiImportLocationModal"
                isOpen={isOpen}
                size={800}
            >
                <GridContainer {...styles.container}>
                    <GridItem {...styles.uploadInputGridItem}>
                        <GridItem {...styles.controlsGridItem}>
                            <FileUpload
                                {...styles.fileUploader}
                                inputRef={fileUploadRef}
                                fileName={file?.name || ""}
                                accept=".xls,.xlsx,.csv"
                                labelPosition="top"
                                buttonText={translate("Browse")}
                                error={
                                    incorrectFileExtension
                                        ? translate("must be .xls, .xlsx or .csv")
                                        : uploadLimitExceeded
                                        ? siteMessage("LocationUpload_RowsLimitExceeded")
                                        : isBadFile
                                        ? siteMessage("VmiLocationUpload_Failure")
                                        : undefined
                                }
                                onFileChange={fileChangeHandler}
                                uid="vmiLocationUploadFile"
                            />
                            <Checkbox
                                {...styles.firstRowOptionCheckbox}
                                checked={firstRowHeading}
                                onChange={firstRowHeadingChangeHandler}
                            >
                                {translate("First row is column headings")}
                            </Checkbox>
                            <Button
                                {...styles.uploadButton}
                                type="button"
                                disabled={!file || isBadFile}
                                onClick={onUploadClick}
                                data-test-selector="vmiLocationUpload"
                            >
                                {translate("Upload VMI Locations")}
                            </Button>
                        </GridItem>
                    </GridItem>
                    <GridItem {...styles.instructionGridItem}>
                        <Typography as="p" {...styles.instructionText}>
                            {siteMessage("VmiLocationUpload_Instructions_Line1_Part1")}
                            <Link
                                href="/Excel/VMIImport_LocationsTemplate.csv"
                                target="_blank"
                                {...styles.templateLink}
                            >
                                {translate("Download the template")}
                            </Link>
                            {siteMessage("VmiLocationUpload_Instructions_Line1_Part2")}
                        </Typography>
                    </GridItem>
                </GridContainer>
            </Modal>
            <Modal {...styles.uploadingModal} isOpen={isUploadingModalOpen} size={290} isCloseable={false}>
                <StyledWrapper {...styles.centeringWrapper}>
                    <LoadingSpinner {...styles.spinner} />
                </StyledWrapper>
                <Typography as="h3" {...styles.uploadingModalText}>
                    {uploadCancelled ? translate("Cancelling") : translate("Uploading Locations")}...
                </Typography>
                <Button
                    {...styles.cancelUploadButton}
                    onClick={cancelUploadingHandler}
                    disabled={!isUploading || !allowCancel || uploadCancelled}
                    data-test-selector="vmiLocationCancelUpload"
                >
                    {translate("Cancel Upload")}
                </Button>
            </Modal>
            <Modal
                {...styles.uploadsuccessModal}
                isOpen={isUploadSuccessModalOpen}
                headline={`${uploadedItemsCount} ${translate("locations uploaded")}.`}
                size={290}
                isCloseable={false}
            >
                <Button {...styles.returnToVmiLocationsButton} onClick={returnToVmiLocationsHandler}>
                    {translate("Return To Vmi Locations")}
                </Button>
            </Modal>
        </>
    );
};

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