import {
    createHandlerChainRunner,
    Handler,
    HasOnError,
    HasOnSuccess,
    markSkipOnCompleteIfOnErrorIsSet,
    markSkipOnCompleteIfOnSuccessIsSet,
} from "@insite/client-framework/HandlerCreator";
import logger from "@insite/client-framework/Logger";
import {
    getCartRealTimeInventory,
    GetRealTimeCartInventoryApiParameter,
} from "@insite/client-framework/Services/CartService";
import siteMessage from "@insite/client-framework/SiteMessage";
import { getSettingsCollection } from "@insite/client-framework/Store/Context/ContextSelectors";
import { AvailabilityDto, RealTimeCartInventoryModel } from "@insite/client-framework/Types/ApiModels";

type Parameter = GetRealTimeCartInventoryApiParameter & HasOnSuccess<RealTimeCartInventoryModel> & HasOnError<unknown>;

type Props = {
    apiParameter: GetRealTimeCartInventoryApiParameter;
    apiResult: RealTimeCartInventoryModel;
    error?: unknown;
};

type HandlerType = Handler<Parameter, Props>;

export const PopulateApiParameter: HandlerType = props => {
    const { onSuccess, onError, ...apiParameter } = props.parameter;
    props.apiParameter = apiParameter;
};

export const SetEmptyData: HandlerType = props => {
    if (getSettingsCollection(props.getState()).productSettings.showInventoryAvailability) {
        return;
    }

    const { isAuthenticated } = props.getState().context.session;

    const initialValue = {} as RealTimeCartInventoryModel;
    props.apiResult =
        props.apiParameter.warehouseIds?.reduce((acc, id) => {
            return {
                ...acc,
                [id]: {
                    message: isAuthenticated ? "" : siteMessage("Inventory_SignInForAvailability"),
                    messageType: isAuthenticated ? 0 : 1,
                    requiresRealTimeInventory: false,
                } as AvailabilityDto,
            };
        }, initialValue) || initialValue;
};

export const RequestDataFromApi: HandlerType = async props => {
    if (!getSettingsCollection(props.getState()).productSettings.showInventoryAvailability) {
        return;
    }

    try {
        props.apiResult = await getCartRealTimeInventory(props.apiParameter);
    } catch (error) {
        logger.warn(`Failed to load cart inventory data: ${error}`);
        props.error = error;
    }
};

export const ExecuteOnSuccessCallback: HandlerType = props => {
    if (!props.error) {
        markSkipOnCompleteIfOnSuccessIsSet(props);
        props.parameter.onSuccess?.(props.apiResult);
    }
};

export const ExecuteOnErrorCallback: HandlerType = props => {
    if (props.error) {
        markSkipOnCompleteIfOnErrorIsSet(props);
        props.parameter.onError?.(props.error);
    }
};

export const chain = [
    PopulateApiParameter,
    SetEmptyData,
    RequestDataFromApi,
    ExecuteOnSuccessCallback,
    ExecuteOnErrorCallback,
];

const loadRealTimeCartInventory = createHandlerChainRunner(chain, "LoadRealTimeCartInventory");

export default loadRealTimeCartInventory;
