import { createHandlerChainRunner, HandlerWithResult } from "@insite/client-framework/HandlerCreator";
import {
    batchCreateVmiUsers,
    BatchCreateVmiUsersApiParameter,
    getAccounts,
} from "@insite/client-framework/Services/AccountService";
import { ServiceResult } from "@insite/client-framework/Services/ApiService";
import {
    ParsedItem,
    VmiUserUploadRowError,
} from "@insite/client-framework/Store/Components/VmiUsersImportModal/VmiUsersImportModalState";
import { VmiUserImportCollectionModel, VmiUserImportModel } from "@insite/client-framework/Types/ApiModels";

export const enum VmiUserUploadError {
    None,
    NotFound,
    InvalidRole,
}

export interface BatchCreateVmiUsersParameter {
    firstRowHeading: boolean;
    validationOnly: boolean;
}

export interface BatchCreateVmiUsersResult {
    apiParameter: BatchCreateVmiUsersApiParameter;
    apiResult: ServiceResult<VmiUserImportCollectionModel>;
    vmiUsers: VmiUserImportModel[];
    errorEntries: VmiUserUploadRowError[];
    importedItems: VmiUserImportModel[];
}

type HandlerType = HandlerWithResult<BatchCreateVmiUsersParameter, BatchCreateVmiUsersResult>;

export const DispatchBeginBatchLoadProducts: HandlerType = props => {
    props.dispatch({
        type: "Components/VmiUsersImportModal/BeginValidateVmiUsers",
    });
};

export const InitializeResult: HandlerType = props => {
    props.result = {
        apiParameter: { validationOnly: false, vmiUsers: [] },
        apiResult: { successful: false, errorMessage: "" },
        vmiUsers: [],
        errorEntries: [],
        importedItems: [],
    };
};

export const PopulateApiParameter: HandlerType = async props => {
    const parsedItems = props.getState()?.components.vmiUsersImportModal.parsedItems;
    if (parsedItems.length === 0) {
        props.dispatch({
            type: "Components/VmiUsersImportModal/SetIsBadFile",
            parameter: { isBadFile: true },
        });
        return false;
    }

    const userNames = parsedItems.map(x => x.userName);
    const newParameter = {
        ...props.parameter,
        userNames,
    };

    const accountsResult = await getAccounts(newParameter);

    props.result.apiParameter = {
        vmiUsers: parsedItems.map(
            item =>
                ({
                    userId: accountsResult.accounts?.find(x => x.userName === item.userName)?.id,
                    vmiLocationNames: item.vmiLocations?.split(","),
                    vmiRoles: item.role?.split(","),
                } as VmiUserImportModel),
        ),
        validationOnly: props.parameter.validationOnly,
    };
};

export const RequestDataFromApi: HandlerType = async props => {
    props.result.apiResult = await batchCreateVmiUsers(props.result.apiParameter);
};

export const ProcessUsers: HandlerType = async props => {
    const {
        getState,
        parameter: { firstRowHeading },
        result: { errorEntries, importedItems, apiResult },
    } = props;
    if (!apiResult.successful) {
        return;
    }

    const parsedItems = getState()?.components.vmiUsersImportModal.parsedItems;
    const userNames = parsedItems.map(x => x.userName);
    const newParameter = {
        ...props.parameter,
        userNames,
    };

    const accountsResult = await getAccounts(newParameter);

    for (let i = 0; i < parsedItems.length; i++) {
        const index = firstRowHeading ? i + 2 : i + 1;
        const parsedItem = parsedItems[i];
        const error = validateUserData(parsedItem);
        if (error === VmiUserUploadError.None) {
            const account = accountsResult.accounts?.find(x => x.userName === parsedItem.userName);
            if (!account) {
                errorEntries.push(
                    mapUserErrorInfo(
                        index,
                        VmiUserUploadError.NotFound,
                        parsedItem.userName,
                        parsedItem.vmiLocations,
                        parsedItem.role,
                    ),
                );
            } else {
                importedItems.push({
                    userId: account.id,
                    vmiLocationNames: parsedItem.vmiLocations?.split(","),
                    vmiRoles: parsedItem.role?.split(","),
                } as VmiUserImportModel);
            }
        } else {
            errorEntries.push(
                mapUserErrorInfo(index, error, parsedItem.userName, parsedItem.vmiLocations, parsedItem.role),
            );
        }
    }
};

const validateUserData = (row: ParsedItem) => {
    if (!row.userName) {
        return VmiUserUploadError.NotFound;
    }
    if (row.role && row.role !== "VMI_User" && row.role !== "VMI_Admin") {
        return VmiUserUploadError.InvalidRole;
    }

    return VmiUserUploadError.None;
};

const mapUserErrorInfo = (
    index: number,
    error: VmiUserUploadError,
    userName: string,
    vmiLocations: string | null,
    role: string | null,
) => {
    return {
        userName,
        vmiLocations,
        role,
        index,
        error,
    };
};

export const DispatchCompleteBatchLoadProducts: HandlerType = props => {
    props.dispatch({
        type: "Components/VmiUsersImportModal/CompleteValidateVmiUsers",
        result: props.result,
    });
};

export const chain = [
    DispatchBeginBatchLoadProducts,
    InitializeResult,
    PopulateApiParameter,
    RequestDataFromApi,
    ProcessUsers,
    DispatchCompleteBatchLoadProducts,
];

const validateVmiUsers = createHandlerChainRunner(chain, "ValidateVmiUsers");
export default validateVmiUsers;
