import axios, { AxiosRequestHeaders } from 'axios';
import FormData                       from 'form-data';
import ClientsSharedConfig            from '../sharedByClients/config/ClientsSharedConfig.js';
import Config                         from '../config/Config.js';
import { version }                    from '../config/Version.js';
import boxen                          from 'boxen';
import DojoStatusCode                 from '../shared/types/Dojo/DojoStatusCode.js';
import DojoBackendResponse            from '../shared/types/Dojo/DojoBackendResponse.js';
import { StatusCodes }                from 'http-status-codes';


class HttpManager {
    registerAxiosInterceptor() {
        this.registerRequestInterceptor();
        this.registerResponseInterceptor();
    }

    private requestError(message: string) {
        console.log(boxen(message, {
            title         : 'Request error',
            titleAlignment: 'center',
            borderColor   : 'red',
            borderStyle   : 'bold',
            margin        : 1,
            padding       : 1,
            textAlignment : 'left'
        }));
        process.exit(1);
    }

    private registerRequestInterceptor() {
        axios.interceptors.request.use(config => {
            if ( config.data instanceof FormData ) {
                config.headers = { ...config.headers, ...config.data.getHeaders() } as AxiosRequestHeaders;
            }

            if ( config.url && (config.url.indexOf(ClientsSharedConfig.apiURL) !== -1) ) {
                config.headers['Accept-Encoding'] = 'gzip';

                if ( config.data && Object.keys(config.data).length > 0 ) {
                    config.headers['Content-Type'] = 'multipart/form-data';
                }

                config.headers['client'] = 'DojoAssignmentChecker';
                config.headers['client-version'] = version;
            }

            return config;
        });
    }

    private registerResponseInterceptor() {
        axios.interceptors.response.use(response => response, error => {
            if ( error.response ) {
                if ( error.response.status === StatusCodes.METHOD_NOT_ALLOWED && error.response.data ) {
                    const data: DojoBackendResponse<void> = error.response.data;

                    switch ( data.code ) {
                        case DojoStatusCode.CLIENT_NOT_SUPPORTED:
                            this.requestError('Client not recognized by the server. Please contact the administrator.');
                            break;
                        case DojoStatusCode.CLIENT_VERSION_NOT_SUPPORTED:
                            this.requestError(`AssignmentChecker version not supported by the server.\nPlease check that the CI/CD pipeline use the "${ Config.dockerhub.repositories.assignmentChecker }:latest" image.\nIf yes, try again later and if the problem persists, please contact the administrator.`);
                            break;
                        default:
                            break;
                    }
                }
            } else {
                this.requestError('Error connecting to the server. Please check your internet connection. If the problem persists, please contact the administrator.');
            }

            return Promise.reject(error);
        });
    }
}


export default new HttpManager();