import StyledWrapper, { getStyledWrapper } from "@insite/client-framework/Common/StyledWrapper";
import { GetAccountApiParameter } from "@insite/client-framework/Services/AccountService";
import ApplicationState from "@insite/client-framework/Store/ApplicationState";
import loadAccount from "@insite/client-framework/Store/Data/Accounts/Handlers/LoadAccount";
import setUserFields from "@insite/client-framework/Store/Pages/UserSetup/Handlers/SetUserFields";
import { getCurrentEditingUser } from "@insite/client-framework/Store/Pages/UserSetup/UserSetupSelectors";
import translate from "@insite/client-framework/Translate";
import WidgetModule from "@insite/client-framework/Types/WidgetModule";
import DynamicDropdown, { DynamicDropdownPresentationProps, OptionObject } from "@insite/mobius/DynamicDropdown";
import Select, { SelectPresentationProps, SelectProps } from "@insite/mobius/Select";
import Typography, { TypographyPresentationProps } from "@insite/mobius/Typography";
import InjectableCss from "@insite/mobius/utilities/InjectableCss";
import debounce from "lodash/debounce";
import React, { useEffect, useState } from "react";
import { connect, ResolveThunks } from "react-redux";
import { css } from "styled-components";

const mapStateToProps = (state: ApplicationState) => ({
    editingUser: getCurrentEditingUser(state),
});

const mapDispatchToProps = {
    setUserFields,
    loadAccount,
};

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

export interface UserSetupSettingsStyles {
    title?: TypographyPresentationProps;
    fieldset?: InjectableCss;
    wrapper?: InjectableCss;
    userRoleSelect?: SelectPresentationProps;
    approverSelect?: SelectPresentationProps;
    approverDynamicDropdown?: DynamicDropdownPresentationProps;
}

export const userSetupSettingsStyles: UserSetupSettingsStyles = {
    title: { variant: "h5" },
    fieldset: {
        css: css`
            margin: 0;
            padding: 0;
            border: 0;
        `,
    },
    wrapper: {
        css: css`
            padding-bottom: 15px;
            font-weight: 400;
        `,
    },
};

const styles = userSetupSettingsStyles;
const StyledFieldSet = getStyledWrapper("fieldset");

const UserSetupSettings = ({ editingUser, setUserFields, loadAccount }: Props) => {
    if (!editingUser) {
        return null;
    }

    const [options, setOptions] = useState<OptionObject[]>([]);

    useEffect(() => {
        if (options.length < 1) {
            setApproverOptions("");
        }

        loadAccount({ accountId: editingUser.id, numberOfApprovers: 20 });
    }, [editingUser]);

    const userRoleChangeHandler: SelectProps["onChange"] = event => {
        setUserFields({ role: event.target.value });
        setUserFields({ approver: "" });
    };

    const approverChangeHandler = (value?: string) => {
        const approverValue = value || "";
        setUserFields({ approver: approverValue });
    };

    const onInputChanged = (event: React.ChangeEvent<HTMLInputElement>) => {
        const filterValue = event.currentTarget.value;
        debouncedSearchApprovers(filterValue);
    };

    const debouncedSearchApprovers = debounce((filterValue: string) => {
        setApproverOptions(filterValue);
    }, 300);

    const setApproverOptions = (filterValue: string) => {
        const currentAccountId = editingUser.id;
        if (!currentAccountId) {
            return;
        }

        let approverOptions: OptionObject[] = [{ optionText: translate("Select an Approver"), optionValue: "" }];
        const parameter = {
            accountId: currentAccountId,
            numberOfApprovers: 20,
        } as GetAccountApiParameter;

        if (filterValue !== "") {
            parameter.approversUsernameFilter = filterValue;
        }

        loadAccount({
            ...parameter,
            onComplete: result => {
                if (!result?.apiResult?.availableApprovers) {
                    return;
                }

                approverOptions = approverOptions.concat(
                    result.apiResult.availableApprovers.map(o => ({ optionText: o, optionValue: o })),
                );

                setOptions(approverOptions);
            },
        });
    };

    return (
        <>
            <Typography as="h2" {...styles.title} data-test-selector="userSetupSetting_title">
                {translate("Settings")}
            </Typography>
            <StyledFieldSet {...styles.fieldset}>
                <StyledWrapper {...styles.wrapper}>
                    <Select
                        {...styles.userRoleSelect}
                        label={translate("User Role")}
                        value={editingUser.role}
                        onChange={userRoleChangeHandler}
                        data-test-selector="userSetupSetting_userRole"
                    >
                        <option value="">{translate("Select User Role")}</option>
                        {editingUser.availableRoles?.map(role => (
                            <option key={role} value={role}>
                                {(editingUser.availableRolesTranslated &&
                                    editingUser.availableRolesTranslated[role.toLowerCase()]) ||
                                    role}
                            </option>
                        ))}
                    </Select>
                </StyledWrapper>
                <StyledWrapper {...styles.wrapper}>
                    <DynamicDropdown
                        {...styles.approverDynamicDropdown}
                        label={translate("Assign Approver")}
                        onInputChange={onInputChanged}
                        onSelectionChange={approverChangeHandler}
                        selected={editingUser.approver}
                        options={options}
                        data-test-selector="userSetupSetting_assignApprover"
                        placeholder={translate("Select an Approver")}
                    />
                </StyledWrapper>
            </StyledFieldSet>
        </>
    );
};

const widgetModule: WidgetModule = {
    component: connect(mapStateToProps, mapDispatchToProps)(UserSetupSettings),
    definition: {
        group: "User Setup",
        displayName: "Settings",
        allowedContexts: ["UserSetupPage"],
    },
};

export default widgetModule;
