import axios from 'axios';
import analyticsMixIn from '@/mixins/analytics-mixin.js';
import { useMainStore } from '@/store';
import applicationConfig from '@/constants/application-config.js';
import { GaCategories, GaActions, GaLabels } from '@/constants/analytics';
import headerKeys from '@/constants/header-keys';
import axiosResponseInterceptorMessages from '@/constants/axios-response-interceptor-messages.js';
import { getSessionKeyValue } from '@/helpers/cookie-helper';

// Add a response interceptor for global axios error handing.
axios.interceptors.response.use(
    (response) => response,
    (error) => {
        let rejectionError = '';
        if (typeof error.response === 'undefined') {
            // The request was not made, could be a bad url, bad connection or a CORS error.
            rejectionError = {
                message:
                    'A network error occurred. '
                    + 'This could be a CORS issue or a dropped internet connection. '
                    + 'It is impossible for us to know.',
                cause: error,
                response: error,
                message: axiosResponseInterceptorMessages.NETWORK_ERROR
            };
        } else if (error.response) {
            // The request was made and the server responded with a status code
            // that falls out of the range of 2xx
            rejectionError = {
                response: error.response,
                message: axiosResponseInterceptorMessages.STATUS_CODE_ERROR
            };
        } else if (error.request) {
            // The request was made but no response was received
            // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
            // http.ClientRequest in node.js
            rejectionError = {
                response: error.request,
                message: axiosResponseInterceptorMessages.NO_RESPONSE_ERROR
            };
        } else {
            // Something happened in setting up the request that triggered an Error
            rejectionError = {
                response: error.message,
                message: axiosResponseInterceptorMessages.GENERIC_ERROR
            };
        }

        return Promise.reject(rejectionError);
    }
);

export default {
    callHttpClient({ method, endpoint, payload, logApiCall = true }) {
        return new Promise((resolve, reject) => {
            const store = useMainStore();
            const cfDistroUrl = applicationConfig.CONSUMER_CF_DISTRO;
            const payloadAndAnalyticsData = { ...payload, AppName: 'ISS' };
            const sessionKey = getSessionKeyValue();
            const headers = {
                [headerKeys.EXPERIMENT]: JSON.stringify(store.experimentSettings),
                [headerKeys.APPLICATION_NAME]: applicationConfig.APPLICATION_NAME,
                [headerKeys.TRANSACTION_ID]: crypto.randomUUID(),
                [headerKeys.ENTERPRISE_ORDER_NUMBER]: store.order.eon,
                [headerKeys.REFERRAL_SEQUENCE_NUMBER]: store.order.referralSequenceNumber,
                [headerKeys.SESSION_SEQUENCE_NUMBER]: sessionKey
            };

            axios({
                method,
                url: cfDistroUrl + endpoint,
                data: payloadAndAnalyticsData,
                crossDomain: true,
                responseType: 'json',
                headers
            })
                .then(
                    (response) => {
                        if (logApiCall) {
                            analyticsMixIn.methods.pushEventToGA(
                                GaCategories.API_RESPONSE,
                                GaActions.RESULT,
                                `${GaLabels.SUCCESS}_${endpoint}`,
                                true
                            );
                        }
                        return resolve(response);
                    },
                    (error) => {
                        if (logApiCall) {
                            analyticsMixIn.methods.pushEventToGA(
                                GaCategories.API_RESPONSE,
                                GaActions.RESULT,
                                `${GaLabels.ERROR}_${endpoint}`,
                                true
                            );
                        }

                        if (error.response.status != '404') {
                            global.$logger.logError(
                                `${method}: ${endpoint}: ${error.message}`,
                                error.response
                            );
                        }
                        return reject(error.response);
                    }
                );
        });
    },

    // used for mocked services
    async mockCallHttpClient(method, endpoint) {
        return new Promise((resolve, reject) => {
            axios({
                method,
                url: endpoint,
                crossDomain: true,
                responseType: {}
            })
                .then(
                    (response) => resolve(response),
                    (error) => {
                        window.console.error(error);
                        return reject(error.response);
                    }
                );
        });
    }
};
