import jwtDecode from 'jwt-decode';

import {
    API_SERVER
} from '../../config';
import {
    LOGIN,
    LOGOUT,
    LOGIN_SUCCESS,
    LOGIN_FAIL,
    VALIDATE_TOKEN,
    REQUEST_MODULES,
    RECIEVE_MODULES,
    REQUEST_FORGOT_PASSWORD,
    FORGOT_PASSWORD,
    REFRESH_TOKEN,
    REQUEST_CHANGE,
    PASSWORD_CHANGED,
    SET_COMPANY_ADMIN_FLAG,
    authActivity
} from '../../constants/authConstants';
import HtmlClient from '../../helpers/HtmlClient';

const htmlClient = new HtmlClient();
let refreshToken = '';
let refreshTimer = {};
const REFRESH_TIME = 1000 * 60 * 50; //refresh 10 minutes before expired

export const login = () => ({
    type: LOGIN
});

export const validateToken = () => ({
    type: VALIDATE_TOKEN
});

export const validateAccessToken = (token) => {
    return dispatch => {
        dispatch(validateToken());
        return htmlClient.fetch({
                url: `${API_SERVER}/login/api/validateToken`
            })
            .then(response => {
                if (response.data && response.data.status === 'success') {
                    const serverTime = response.data.serverTime || 1;

                    dispatch(loggedIn({
                        accessToken: token,
                        userInfo: response.data.userInfo
                    }));
                    refreshToken = response.data.refreshToken;
                    startRefreshTimer(dispatch, serverTime);
                    dispatch(setUserAsCompanyAdmin(response.data.userInfo.wiaas_is_company_admin));
                } else {
                    dispatch(loginFail(response.data));
                }

            })
            .catch(error => {
                htmlClient.onError(error, dispatch);
            });
    }
}

export const setUserAsCompanyAdmin = (isCompanyAdmin) => ({type: SET_COMPANY_ADMIN_FLAG, isCompanyAdmin});

export const validateCredentials = (username, password) => {
    return dispatch => {
        dispatch(login());
        return htmlClient.fetch({
                url: `${API_SERVER}/login/api/getToken`,
                method: 'post',
                data: {
                    username,
                    password,
                    login: true
                },
                header: {}
            })
            .then(response => {
                if (response.data.status === 'success') {
                    const decodedAceessToken = jwtDecode(response.data.accessToken);
                    if(decodedAceessToken.data.wiaas_user_type === 'customer'){
                        localStorage.setItem('accessToken', response.data.accessToken);
                        const serverTime = response.data.serverTime || 1;
                        refreshToken = response.data.refreshToken;
                        startRefreshTimer(dispatch, serverTime);
                        dispatch(loggedIn(response.data));
                        dispatch(setUserAsCompanyAdmin(response.data.userInfo.wiaas_is_company_admin));
                    }else{
                        dispatch(loginFail({status: 'fail', errorMessage: 'INVALID_USER_TYPE'}));
                    }
                } else {
                    dispatch(loginFail(response.data));
                }
            })
            .catch(error => {
                htmlClient.onError(error, dispatch);
            });
    }
}

const startRefreshTimer = (dispatch, serverTime) => {
    const decodedAceessToken = jwtDecode(localStorage.accessToken);
    const TEN_MINUTES = 600;
    const tokenTimeLeft = decodedAceessToken.exp - serverTime;
    const refreshTime = tokenTimeLeft ? (tokenTimeLeft - TEN_MINUTES) * 1000 : REFRESH_TIME;

    if(refreshTime <= 0){
        dispatch(validateRefreshToken());
    }else{
        refreshTimer = setTimeout(()=>{
            dispatch(validateRefreshToken());
        }, refreshTime);
    }
}

const requestRefreshToken = () => ({
    type: REFRESH_TOKEN
});

const validateRefreshToken = () => {
    return dispatch => {
        dispatch(requestRefreshToken());
        return htmlClient.fetch({
                url: `${API_SERVER}/login/api/refreshToken`,
                method: 'post',
                data: {
                    refreshToken,
                    lastActivity: authActivity.lastActivity
                }
            })
        .then(response => {
            if (response.data.status === 'success') {
                localStorage.setItem('accessToken', response.data.accessToken);
                const serverTime = response.data.serverTime || 1;
                refreshToken = response.data.refreshToken;
                dispatch(setUserAsCompanyAdmin(response.data.userInfo.wiaas_is_company_admin));
                startRefreshTimer(dispatch, serverTime);
            } else {
                dispatch(logout(response.data));
                dispatch(loginFail(response.data));
            }
        })
        .catch(error => {
            htmlClient.onError(error, dispatch);
        });

    }
}

export const getModules = () => {
    return dispatch => {
        dispatch(requestModules());
        return htmlClient.fetch({
                url: `${API_SERVER}/login/api/getModules`,
            })
        .then(response => {
            dispatch(recieveModules(response.data));
        })
        .catch(error => {
            htmlClient.onError(error, dispatch);
        });

    }
}

const requestModules = () => ({
    type: REQUEST_MODULES
});

const recieveModules = (json) => ({
    type: RECIEVE_MODULES,
    modules: json.modules
});

export const logout = () => {
    localStorage.removeItem('accessToken');
    clearInterval(refreshTimer);
    return {
        type: LOGOUT,
        isLoggedIn: false,
        errorMessage: 'LOGGED_OUT'
    }
}

export const loggedIn = (jsonData) => {
    return {
        type: LOGIN_SUCCESS,
        isLoggedIn: true,
        userInfo: jsonData.userInfo
    }
}

export const loginFail = (jsonData) => {
    return {
        type: LOGIN_FAIL,
        isLoggedIn: false,
        errorMessage: jsonData.errorMessage
    }
}

export const generatePassword = (mail) => {
    return dispatch => {
        dispatch(requestForgotPassword());
        return htmlClient.fetch({
                url: `${API_SERVER}/login/api/forgotPassword`,
                method: 'post',
                data: {mail},
                header: {}
            })
            .then(response => {
                if(typeof response.data !== 'undefined' && 'messages' in response.data) {
                    dispatch(forgotPasswordMessage(response.data.messages[0]));
                }
            })
            .catch(error => {
                htmlClient.onError(error, dispatch);
            });
    }
}

const requestForgotPassword =  () => ({
    type: REQUEST_FORGOT_PASSWORD,
    errorMessage: 'FORGOT_REQUEST_SENT'
});
const forgotPasswordMessage = (jsonData) => {
    return {
        type: FORGOT_PASSWORD,
        errorMessage: jsonData.message,
        messageColor: jsonData.code
    }
}

const requestChange = () => ({
    type: REQUEST_CHANGE
});

const passwordChanged = (messageObj) => {
    const code = messageObj.code === 'error' ? 'danger' : messageObj.code;
    const isPasswordChanged = messageObj.message === 'PASSWORD_GENERATED' ? true : false;
    return {
        type: PASSWORD_CHANGED,
        errorMessage: messageObj.message,
        messageColor: code,
        isPasswordChanged: isPasswordChanged
    }
};

export const changePassword = (token, newPassword, confirmPassword) => {
    return dispatch => {
        dispatch(requestChange());
        return htmlClient.fetch({
                url: `${API_SERVER}/login/api/changePassword`,
                method: 'post',
                data: {token, newPassword, confirmPassword},
                header: {}
            })
            .then(response => {
                if(response.data.messages && response.data.messages.length > 0){
                    dispatch(passwordChanged(response.data.messages[0]));
                }
            })
            .catch(error => {
                htmlClient.onError(error, dispatch);
            });
    }
}
