import axios, { AxiosError } from 'axios';
import Config                from '../config/Config';
import ora                   from 'ora';
import ApiRoutes             from '../types/ApiRoutes';
import { StatusCodes }       from 'http-status-codes';
import Enonce                from '../types/Enonce';
import GitlabUser            from '../shared/types/Gitlab/GitlabUser';
import DojoResponse          from '../types/DojoResponse';


class DojoBackendManager {
    constructor() { }

    private static _instance: DojoBackendManager;

    public static get instance(): DojoBackendManager {
        if ( !DojoBackendManager._instance ) {
            DojoBackendManager._instance = new DojoBackendManager();
        }

        return DojoBackendManager._instance;
    }

    public getApiUrl(route: ApiRoutes): string {
        return `${ Config.apiURL }${ route }`;
    }

    public async checkTemplateAccess(idOrNamespace: string, verbose: boolean = true): Promise<boolean> {
        const spinner: ora.Ora = ora('Checking template access');

        if ( verbose ) {
            spinner.start();
        }

        try {
            await axios.get(this.getApiUrl(ApiRoutes.GITLAB_CHECK_TEMPLATE_ACCESS).replace('{{id}}', idOrNamespace));

            if ( verbose ) {
                spinner.succeed('Template access granted');
            }

            return true;
        } catch ( error ) {
            if ( verbose ) {
                if ( error instanceof AxiosError ) {
                    if ( error.response ) {
                        if ( error.response.status === StatusCodes.NOT_FOUND ) {
                            spinner.fail(`Template not found or access denied. Please check the template ID or url. Also, please check that the template have public/internal visibility or that your and Dojo account (${ Config.gitlab.dojoAccount.username }) have at least reporter role to the template (if private).`);
                        } else if ( error.response.status === StatusCodes.UNAUTHORIZED ) {
                            spinner.fail(`Please check that the template have public/internal visibility or that your and Dojo account (${ Config.gitlab.dojoAccount.username }) have at least reporter role to the template (if private).`);
                        } else {
                            spinner.fail(`Template error: ${ error.response.statusText }`);
                        }
                    }
                } else {
                    spinner.fail(`Template error: ${ error }`);
                }
            }

            return false;
        }
    }

    public async createProject(name: string, members: Array<GitlabUser>, templateIdOrNamespace: string | null, verbose: boolean = true): Promise<Enonce> {
        const spinner: ora.Ora = ora('Creating enonce...');

        if ( verbose ) {
            spinner.start();
        }

        try {
            const response = await axios.post<DojoResponse<Enonce>>(this.getApiUrl(ApiRoutes.ENONCE_CREATE), Object.assign({
                                                                                                                               name   : name,
                                                                                                                               members: JSON.stringify(members)
                                                                                                                           }, templateIdOrNamespace ? { template: templateIdOrNamespace } : {}));

            if ( verbose ) {
                spinner.succeed(`Enonce successfully created`);
            }

            return response.data.data;
        } catch ( error ) {
            if ( verbose ) {
                if ( error instanceof AxiosError ) {
                    spinner.fail(`Error...`);
                } else {
                    spinner.fail(`Error...`);
                }
            }

            throw error;
        }
    }
}


export default DojoBackendManager.instance;