import { createReducer } from '@reduxjs/toolkit';
import { setError } from '../../error/error-actions.js';
import { fetchMoreRecommendations, fetchRecommendations, promoteChildToParent, registerRecommendationsSlot, } from './recommendations-actions.js';
import { getRecommendationsInitialState, getRecommendationsSliceInitialState, } from './recommendations-state.js';
export const recommendationsReducer = createReducer(getRecommendationsInitialState(), (builder) => {
    builder
        .addCase(registerRecommendationsSlot, (state, action) => {
        const slotId = action.payload.slotId;
        const productId = action.payload.productId;
        if (slotId in state) {
            return;
        }
        if (!productId) {
            state[slotId] = buildRecommendationsSlice();
            return;
        }
        state[slotId] = buildRecommendationsSlice({ productId });
    })
        .addCase(fetchRecommendations.rejected, (state, action) => {
        handleError(state, action.meta.arg.slotId, action.payload);
    })
        .addCase(fetchMoreRecommendations.rejected, (state, action) => {
        handleError(state, action.meta.arg.slotId, action.payload);
    })
        .addCase(fetchRecommendations.fulfilled, (state, action) => {
        const slotId = action.meta.arg.slotId;
        const response = action.payload.response;
        handleFulfilled(state, slotId, response);
        const recommendations = state[slotId];
        if (!recommendations) {
            return;
        }
        const paginationOffset = getPaginationOffset(action.payload);
        recommendations.products = response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1, response.responseId));
    })
        .addCase(fetchMoreRecommendations.fulfilled, (state, action) => {
        if (!action.payload) {
            return;
        }
        const slotId = action.meta.arg.slotId;
        const response = action.payload.response;
        handleFulfilled(state, slotId, response);
        const recommendations = state[slotId];
        if (!recommendations) {
            return;
        }
        const paginationOffset = getPaginationOffset(action.payload);
        recommendations.products = recommendations.products.concat(response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1, response.responseId)));
    })
        .addCase(fetchRecommendations.pending, (state, action) => {
        handlePending(state, action.meta.arg.slotId);
    })
        .addCase(fetchMoreRecommendations.pending, (state, action) => {
        handlePending(state, action.meta.arg.slotId);
    })
        .addCase(promoteChildToParent, (state, action) => {
        const recommendations = state[action.payload.slotId];
        if (!recommendations) {
            return;
        }
        const { products } = recommendations;
        let childToPromote;
        const currentParentIndex = products.findIndex((product) => {
            childToPromote = product.children.find((child) => child.permanentid === action.payload.child.permanentid);
            return !!childToPromote;
        });
        if (currentParentIndex === -1 || childToPromote === undefined) {
            return;
        }
        const responseId = products[currentParentIndex].responseId;
        const position = products[currentParentIndex].position;
        const { children, totalNumberOfChildren } = products[currentParentIndex];
        const newParent = {
            ...childToPromote,
            children,
            totalNumberOfChildren,
            position,
            responseId,
        };
        products.splice(currentParentIndex, 1, newParent);
    })
        .addCase(setError, (state, action) => {
        // We do not know the slotId here, so we need to error on all slots.
        Object.keys(state).forEach((slotId) => {
            handleError(state, slotId, action.payload);
        });
    });
});
function buildRecommendationsSlice(config) {
    return {
        ...getRecommendationsSliceInitialState(),
        ...config,
    };
}
function handleError(state, slotId, error) {
    const recommendations = state[slotId];
    if (!recommendations) {
        return;
    }
    recommendations.error = error ?? null;
    recommendations.isLoading = false;
}
function handleFulfilled(state, slotId, response) {
    const recommendations = state[slotId];
    if (!recommendations) {
        return;
    }
    recommendations.error = null;
    recommendations.headline = response.headline;
    recommendations.responseId = response.responseId;
    recommendations.isLoading = false;
}
function handlePending(state, slotId) {
    const recommendations = state[slotId];
    if (!recommendations) {
        return;
    }
    recommendations.isLoading = true;
}
function getPaginationOffset(actionPayload) {
    const pagination = actionPayload.response.pagination;
    return pagination.page * pagination.perPage;
}
function preprocessProduct(product, position, responseId) {
    const isParentAlreadyInChildren = product.children.some((child) => child.permanentid === product.permanentid);
    if (product.children.length === 0 || isParentAlreadyInChildren) {
        return { ...product, position, responseId };
    }
    const { children, totalNumberOfChildren: _totalNumberOfChildren, ...restOfProduct } = product;
    return {
        ...product,
        children: [restOfProduct, ...children],
        position,
        responseId,
    };
}
