import {API_SERVER} from '../../config';
import HtmlClient from '../../helpers/HtmlClient';
import {
    REQUEST_SHOP_CART_COUNT,
    RECEIVE_SHOP_CART_COUNT,
    REQUEST_SHOP_CART_ITEMS,
    RECEIVE_SHOP_CART_ITEMS,
    SET_CURRENT_STEP,
    RESET_STEPS,
    GO_TO_NEXT_STEP,
    GO_TO_PREVIOUS_STEP,
    LOAD_CART_STEPS,
    cartSteps,
    UPLOAD_DOCUMENT,
    REQUEST_CART_DOCUMENTS,
    RECEIVE_CART_DOCUMENTS,
    REQUEST_CUSTOMER_DETAILS,
    RECEIVE_CUSTOMER_DETAILS,
    SELECT_COUNTRY_DELIVERY,
    SELECT_COUNTRY_BILLING,
    SET_ORDER_INFO,
    IS_CART_ITEMS_DISABLED,
    RECEIVE_ORDER_TOTAL_PRICE,
    UPDATE_CART_ITEMS,
    SET_NEXT_STEP,
    SET_PREV_STEP,
    SET_ORDER_PLACED,
    SET_ORDER_PLACED_REDIRECT,
    cartMessages
} from '../../constants/cartConstants';
import {updateMessages} from '../notification/notificationActions';
const client = new HtmlClient();

export const requestShopCartCount = () => ({type: REQUEST_SHOP_CART_COUNT});
export const receiveShopCartCount = (json) => ({type: RECEIVE_SHOP_CART_COUNT, cartCount: json});

export const requestShopCartItems = () => ({
    type: REQUEST_SHOP_CART_ITEMS,
    isLoading: true
});
export const receiveShopCartItems = (json) => ({
    type: RECEIVE_SHOP_CART_ITEMS,
    isLoading: false,
    cartItems: json
});

export const requestCustomerDetails = () => ({
    type: REQUEST_CUSTOMER_DETAILS,
    isLoading: true
});
export const receiveCustomerDetails = (json) => ({
    type: RECEIVE_CUSTOMER_DETAILS,
    isLoading: false,
    customerDetails: json
});

export const fetchCartCount = () => {
    return dispatch => {
        dispatch(requestShopCartCount());
        return client.fetch({url: `${API_SERVER}/cart/api/getCartCount`}).then(response => {
            if (typeof response.data !== 'undefined' && 'cartItemsCount' in response.data) {
                dispatch(receiveShopCartCount(response.data.cartItemsCount));
            }
        }).catch(error => {
            client.onError(error, dispatch);
        });
    }
}

export const fetchCartItems = (isForSteps = false) => {
    return dispatch => {
        dispatch(requestShopCartItems());
        return client.fetch({url: `${API_SERVER}/cart/api/getCartItems`}).then(response => {
            if (typeof response.data !== 'undefined' && 'cartItems' in response.data) {
                dispatch(receiveShopCartItems(response.data.cartItems));
                dispatch(fetchCartDocuments(response.data.cartItems.map((cartItem) => cartItem.idPackage), isForSteps));
                dispatch(updateOrderTotalPrice(response.data.cartItems));
            }
        }).catch(error => {
            client.onError(error, dispatch);
        });
    }
}

const updateOrderTotalPrice = (cartItems) => ({type: RECEIVE_ORDER_TOTAL_PRICE, cartItems});

const updateCartItems = (newItem)=>(
    {type: UPDATE_CART_ITEMS, newItem}
);

export const updateQuantity = (cartItem, quantity, updateCartAllItems) => {
    const params = {
        idPackage: cartItem.idPackage || 0,
        idCustomerInstance: cartItem.idCustomerInstance || 0,
        idPrice: cartItem.idPrice || 0,
        quantity
    };

    return dispatch => {
        return client.fetch({
            url: `${API_SERVER}/cart/api/updateQuantity`,
            method: 'post',
            data: params
        }).then(response => {
            if (typeof response.data !== 'undefined' && 'messages' in response.data) {
                const filteredMessages = response.data.messages.filter(message => {
                    return message.code === 'error';
                });

                if(filteredMessages.length > 0){
                    dispatch(updateMessages(filteredMessages, cartMessages));
                }else{
                    cartItem.quantity = quantity;
                    dispatch(updateCartItems(cartItem));
                }
            }
        }).catch(error => {
            client.onError(error, dispatch);
        });
    }
}

export const removeCartItem = (idCart) => {
    return dispatch => {
        return client.fetch({
            url: `${API_SERVER}/cart/api/removeFromCart`,
            method: 'post',
            data: {idCart}
        }).then(response => {
            if (typeof response.data !== 'undefined' && 'messages' in response.data) {
                dispatch(updateMessages(response.data.messages, cartMessages));
                response.data.messages.forEach(messageObject => {
                    if (messageObject.code === 'success') {
                        dispatch(fetchCartCount());
                        dispatch(fetchCartItems(true));
                    }
                })
            }
        }).catch(error => {
            client.onError(error, dispatch);
        });
    }
}

const getSteps = (whitoutUploadDoc) => {
    const newSteps = Object.assign({}, cartSteps());

    if(whitoutUploadDoc) {
        delete newSteps.cartUploadDocuments;
        newSteps.cartCustomerDetails.previous = null;
        newSteps.cartCustomerDetails.status = 'active';
    }

    return {
        type: LOAD_CART_STEPS,
        cartSteps: newSteps
    };
};

export const loadSteps = (whitoutUploadDoc) => {
    const firstStep = whitoutUploadDoc ? 'cartCustomerDetails' : 'cartUploadDocuments';

    return dispatch => {
        dispatch(getSteps(whitoutUploadDoc));
        dispatch(selectStep(firstStep));
        dispatch(resetSteps());
        dispatch(setCartItemsDisabled(false));
    }
}

export const selectStep = (step, params={}) => {
    return {type: SET_CURRENT_STEP, currentStep: step, params};
}

const resetSteps = () => ({type: RESET_STEPS});

export const getCustomerDetails = () => {
    return dispatch => {
        return client.fetch({url: `${API_SERVER}/cart/api/getCustomerDetails`})
        .then(response => {
            if (typeof response.data !== 'undefined' && response.data.customerDetails) {
                const customerDetails = response.data.customerDetails;
                dispatch(receiveCustomerDetails(customerDetails));
            }
        }).catch(error => {
            client.onError(error, dispatch);
        });
    }
}

export const nextStep = (step) => ({type: GO_TO_NEXT_STEP});
export const previousStep = (params) => ({type: GO_TO_PREVIOUS_STEP, params});

export const uploadDocumnet = () => ({type: UPLOAD_DOCUMENT});

export const uploadOrderDocument = (idPackage, idDocumentType, file, packages) => {
    return dispatch => {
        dispatch(uploadDocumnet());

        return client.uploadFile(file, {
            url: `${API_SERVER}/cart/api/uploadOrderDocument`,
            data: {
                idDocumentType,
                idPackage
            }
        }).then(response => {
            if (typeof response.data !== 'undefined' && 'messages' in response.data) {
                dispatch(updateMessages(response.data.messages, cartMessages));
                dispatch(fetchCartDocuments(packages));
            }
        }).catch(error => {
            client.onError(error, dispatch);
        });
    }
}

export const badFile = () =>{
    return dispatch => {
        dispatch(updateMessages([{code: 'warning', message: 'INVALID_FILE'}], cartMessages));
    }
}

export const requestCartDocuments = () => ({
    type: REQUEST_CART_DOCUMENTS,
    isLoading: true
});
export const receiveCartDocuments = (json) => ({
    type: RECEIVE_CART_DOCUMENTS,
    isLoading: false,
    cartDocuments: json
});

export const fetchCartDocuments = (packages, isForSteps = false) => {
    return dispatch => {
        dispatch(requestCartDocuments());

        return client.fetch({
            url: `${API_SERVER}/cart/api/getCartDocuments`,
            method: 'post',
            data: {packages}
        }).then(response => {
            if (response.data) {
                dispatch(receiveCartDocuments(response.data));
                if(isForSteps) {
                    const whitoutUploadDoc = response.data.templates.length === 0;
                    dispatch(loadSteps(whitoutUploadDoc));
                }
            }
        }).catch(error => {
            client.onError(error, dispatch);
        });
    }
}

export const selectCountryDelivery = (country) => ({type: SELECT_COUNTRY_DELIVERY, selectedCountryDelivery: country});
export const selectCountryBilling = (country) => ({type: SELECT_COUNTRY_BILLING, selectedCountryBilling: country});

export const saveOrderDetails = (orderDetails, cartItems) => {
    const orderInfo = {orderDetails, cartItems};
    return dispatch => {
        return client.fetch({
            url: `${API_SERVER}/cart/api/saveOrderDetails`,
            method: 'post',
            data: {orderDetails, cartItems}
        }).then(response => {
            if (typeof response.data !== 'undefined' && 'messages' in response.data) {
                dispatch(getCustomerDetails());
                dispatch(setOrderInfo(orderInfo));
            }
        }).catch(error => {
            client.onError(error, dispatch);
        });
    }
}

export const setOrderInfo = (info) => ({type: SET_ORDER_INFO, orderInfo: info});

export const setOrderPlacedFlag = (flag) => ({type: SET_ORDER_PLACED, orderPlaced: flag});
export const setOrderPlacedRedirectFlag = (flag) => ({type: SET_ORDER_PLACED_REDIRECT, orderPlacedRedirect: flag});

export const placeOrder = (orderInfo) => {
    const {orderDetails, cartItems} = orderInfo;
    return dispatch => {
        return client.fetch({
            url: `${API_SERVER}/cart/api/placeOrder`,
            method: 'post',
            data: {orderDetails, cartItems}
        }).then(response => {
            if (typeof response.data !== 'undefined' && 'messages' in response.data) {
                dispatch(updateMessages(response.data.messages, cartMessages));
                if(!checkIfErrorMessageExists(response.data.messages)) {
                    dispatch(fetchCartCount());
                    dispatch(setOrderPlacedFlag(true));
                    dispatch(setOrderPlacedRedirectFlag(true));
                }
            }
        }).catch(error => {
            client.onError(error, dispatch);
        });
    }
}

const checkIfErrorMessageExists = (messagesArray) => {
    return messagesArray.some(messageObj => {
        return messageObj.code === 'error';
    });
}

export const setCartItemsDisabled = (flag) => ({type: IS_CART_ITEMS_DISABLED, isCartItemsDisabled: flag});

export const setNextActionFct = (fct) => ({type: SET_NEXT_STEP, nextStepAction: fct});
export const setPrevActionFct = (fct) => ({type: SET_PREV_STEP, prevStepAction: fct});
