'use strict';
const fs = require('fs');
const chalk = require('chalk');
const { prompt, Form, Select, Confirm } = require('enquirer');
const Table = require('cli-table3');

const config = require('./config');

const Auth = require('../lib/Auth');
const API = require('../lib/API');
const SSH = require('./sshconnect');

module.exports.connect = async (args) => {
	const alias = args._[0];

	try {
		const serverData = await API.getForConnect(alias).then(d => d.data);

		const dataConnect = {
			host: serverData.host,
			port: serverData.port,
			username: serverData.username,
		}

		if(serverData.password) dataConnect.password = serverData.password;
		if(serverData.perm && serverData.perm.pvkey) dataConnect.privateKey = serverData.perm.pvkey;
		if(serverData.perm && serverData.perm.keypass) dataConnect.passphrase = serverData.perm.keypass;
		
		SSH(dataConnect);

	} catch(err) {
		console.log(chalk.red.bold(`Ocorreu um erro ao obter informações.`))
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red.bold(err.response.body.message));
		else
			console.log(chalk.red.bold(err.message || 'unknown'));
		process.exit('SIGKILL');
	}
}

module.exports.purge = () => {
	config.clear();
}

module.exports.debug = () => {
	console.log(config.get('tokenData'))
}

module.exports.validate = async () => {
	if(await Auth.validateSession())
		console.log(chalk.green.bold(`Sessão é válida!`));
	else
		console.log(chalk.red.bold(`Sessão invalida!`));
}

module.exports.refresh = async () => {
	try {
		const r = await Auth.refreshSession(true);
		if(r != true && r.data) {
			config.delete('tokenData');
			config.set('tokenData', r.data);
			console.log(chalk.green(`Sessão atualizada.`))
		} else {
			console.log(chalk.green(`Sessão ainda é valida.`));
		}
	} catch(err) {
		console.log(chalk.red.bold(`Ocorreu um erro ao renovar sessão!`))
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red.bold(err.response.body.message));
		else
			console.log(chalk.red.bold(err.message || 'unknown'));
	}
}

module.exports.register = async () => {
	if(config.has('tokenData')) {
		console.log(chalk.bold(`Você já está logado`));
		console.log(chalk.bold(`Use sshc --logout`));
		process.exit(0);
	}

	if(!config.has('preRegisterEmail')) {

		const formData = await prompt([{
			type: 'input',
			name: 'username',
			message: 'Digite seu email:',
			validate: v => /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(v),
			required: true
		},
		{
			type: 'password',
			name: 'password',
			message: 'Digite sua senha (min 8 caracteres):',
			required: true
		},
		{
			type: 'password',
			name: 'rpassword',
			message: 'Confirme sua senha:',
			required: true
		}]);

		if(formData.password != formData.rpassword) {
			console.log(chalk.red.bold(`Senhas não conferem, tente novamente.`));
			process.exit(1);
		}

		try {
			await Auth.register(formData.username, formData.password);
			console.log(chalk.green(`Cadastro efetuado!`));
			console.log(chalk.magenta(`Um codigo de confirmação foi enviado para o seu email!`));
			config.set('preRegisterEmail', formData.username);
		} catch(err) {
			console.error(chalk.red.bold('Ocorreu um erro...'));
			if(err.response && err.response.body && err.response.body.message) 
				console.error(chalk.red(err.response.body.message));
			else
				console.error(chalk.red(err.message || err.stack || err));
			
			process.exit(1);
		}
	} else {
		console.log(chalk.magenta.bold(`Existe um cadastro em andamento...`));
		console.log(chalk.magenta.bold(`Um codigo de confirmação foi enviado para o seu email (${config.get('preRegisterEmail')})`));
	}

	const confirmCode = await prompt({
		type: 'numeral',
		name: 'code',
		message: 'Digite codigo de confirmação:',
		validate: v => !/[^0-9]+/g.test(v),
		required: true
	});
	
	try {
		await Auth.registerConfirm(config.get('preRegisterEmail'), confirmCode.code);
		console.log(chalk.green(`Cadastrado com sucesso! Digite 'sshc --login'`));
		config.delete('preRegisterEmail');
	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um erro...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(1);
	}
}

module.exports.login = async () => {

	if(config.has('tokenData')) {
		console.log(chalk.bold(`Você já está logado`));
		console.log(chalk.bold(`Use sshc --logout`));
		process.exit(1);
	}

	if(config.has('loginSessionMFA')) {
		this.loginMFA();
		return;
	}

	const formData = await prompt([{
		type: 'input',
		name: 'username',
		message: 'Digite seu email de login:',
		required: true
	},
	{
		type: 'password',
		name: 'password',
		message: 'Digite senha:',
		required: true
	}]);

	try {
		const r = await Auth.login(formData.username, formData.password);
		config.set('userEmail', formData.username);
		
		if(r.logged) {
			config.set('tokenData', r.data);
			console.log(chalk.green(`Login efetuado!`));
		} else if(r.data.nextStep) {
			switch(r.data.nextStep) {
				case 'MFA_AUTH':
					config.set('loginSessionMFA', r.data.loginSession);
					await this.loginMFA();
					break;
				default:
					console.log(chalk.red(`Unknown step (${r.data.nextStep})`));
					break;
			}
		}
	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um erro ao fazer login...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(1);
	}
}

module.exports.relogin = async () => {

	if(!config.has('userEmail')) {
		console.error(chalk.red(`É necessário fazer o login novamente, tente 'sshc --login'`));
		process.exit(0);
	}

	const formData = await prompt({
		type: 'password',
		name: 'password',
		message: 'Digite senha:',
		required: true
	});

	try {
		const r = await Auth.login(config.get('userEmail'), formData.password);
		if(r.logged) {
			config.delete('tokenData');
			config.set('tokenData', r.data);
			console.log(chalk.green(`Login efetuado!`));
		} else if(r.data.nextStep) {
			switch(r.data.nextStep) {
				case 'MFA_AUTH':
					config.set('loginSessionMFA', r.data.loginSession);
					await this.loginMFA();
					break;
				default:
					console.log(chalk.red(`Unknown step (${r.data.nextStep})`));
					break;
			}
		}
	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um erro ao fazer login...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		process.exit(1);
	}
}

module.exports.loginMFA = async () => {

	console.log(chalk.magenta.bold(`Autenticação multifator (MFA)\nFoi enviado um código para o número cadastrado.`));

	const formData = await prompt({
		type: 'input',
		name: 'loginCode',
		message: 'Digite o código recebido por SMS:',
		required: true
	});

	try {
		const r = await Auth.loginMFA(formData.loginCode);
		config.set('tokenData', r.data);
		console.log(chalk.green(`Login efetuado!`));
	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um erro ao fazer login...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(1);
	}
}

module.exports.logout = async () => {
	config.delete('tokenData');
	config.delete('userEmail');
	await Auth.logout();
	console.log(chalk.green(`Deslogado com sucesso!`));
}

module.exports.removePhoneNumber = async (args) => {
	try {
		const resp = await Auth.editPhoneNumber(null);
		if(resp.changed) console.log(chalk.green('Número removido com sucesso!'));
		else console.log(chalk.red('Não foi possivel remover.'));
	} catch(err) {
		console.log(chalk.red.bold(`Ocorreu um erro...`))
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red.bold(err.response.body.message));
		else
			console.log(chalk.red.bold(err.message || 'unknown'));
		process.exit('SIGKILL');
	}
}

module.exports.registerPhoneNumber = async (args) => {
	let phone = args.phone || null;

	if(!phone || phone === true) {
		const formData = await prompt({
			type: 'input',
			name: 'phone',
			message: 'Digite um número de celular Ex.: 551199999999',
			required: true
		}).then(d => {
			if(!d.phone.startsWith('+')) d.phone = '+'+d.phone;
			return d;
		});

		const confirmationPhone = await new Confirm({
			name: 'question',
			message: `Este número está correto? ${chalk.magenta(formData.phone)}`
		}).run();

		if(!confirmationPhone) {
			console.log(chalk.red(`Tente novamente.`));
			return false;
		}

		phone = formData.phone;
	}

	try {
		const resp = await Auth.editPhoneNumber(phone);
		if(resp.changed) console.log(chalk.green('Número cadastrado com sucesso!'));
		else console.log(chalk.red('Número não foi cadastrado.'), resp);
	} catch(err) {
		console.log(chalk.red.bold(`Ocorreu um erro...`))
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red.bold(err.response.body.message));
		else
			console.log(chalk.red.bold(err.message || 'unknown'));
		process.exit('SIGKILL');
	}
}

module.exports.statusMFA = async (args) => {

	try {
		const resp = await Auth.statusMFA();
		if(resp.statusMFA) {
			console.log(chalk.cyan.bold('MFA ativado para esta conta.'));
		} else {
			console.log(chalk.red.bold('MFA desativado para esta conta.'));
		}
	} catch(err) {
		console.log(chalk.red.bold(`Ocorreu um erro ao obter informações.`))
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red.bold(err.response.body.message));
		else
			console.log(chalk.red.bold(err.message || 'unknown'));
		process.exit('SIGKILL');
	}
}

module.exports.enableMFA = async (args) => {

	try {
		const resp = await Auth.changeStatusMFA(true);
		if(resp.changed)
			console.log(chalk.green.bold('MFA desativado com sucesso.'));
		else
			console.log(chalk.red.bold('Ocorreu um erro ao ativar.'));
	} catch(err) {
		if(err.response && err.response.body) {
			if(err.response.body.errCode == 'MissingPhoneNumber')
				console.log(chalk.cyan(`Para ativar MFA, você precisa cadastrar um número de celular a sua conta, tente '${chalk.bold('sshc --register-phone 551199999999')}'`));
			else
				console.log('Erro desconhecido');
		} else {
			console.log(chalk.red.bold(`Ocorreu um erro...`))
			if(err.response && err.response.body && err.response.body.message) 
				console.error(chalk.red.bold(err.response.body.message));
			else
				console.log(chalk.red.bold(err.message || 'unknown'));
			process.exit('SIGKILL');
		}
	}
}

module.exports.disableMFA = async (args) => {

	try {
		const resp = await Auth.changeStatusMFA(false);
		if(resp.changed)
			if(resp.changedTo == false)
				console.log(chalk.green.bold('MFA desativado com sucesso.'));

	} catch(err) {
		console.log(chalk.red.bold(`Ocorreu um erro ao obter informações.`))
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red.bold(err.response.body.message));
		else
			console.log(chalk.red.bold(err.message || 'unknown'));
		process.exit('SIGKILL');
	}
}

module.exports.keyUnlink = async (args) => {
	const params = args._;

	if(!args.s && !args.g) {
		console.log(chalk.red.bold(`Uso incorreto, tente 'sshc key unlink [-s|-g] [server alias|group name]'`));
		process.exit(1);
	}

	if(args.s) {
		try {
			await API.unlinkKey(args.s, args.g);
			console.log(chalk.green.bold(`Chave desassociada com sucesso!`))
		} catch(err) {
			console.error(chalk.red.bold('Ocorreu um erro ao desassociada chave...'));
			if(err.response && err.response.body && err.response.body.message) 
				console.error(chalk.red(err.response.body.message));
			else
				console.error(chalk.red(err.message || err.stack || err));
			
			process.exit(1);
		}
	}
}

module.exports.keyLink = async (args) => {
	const params = args._;

	if(!params[2]) {
		console.log(chalk.red.bold(`Uma chave deve ser especificada, tente 'sshc key link [name] [-s|-g] [server alias|group name]'`));
		process.exit(1);
	}

	if(!args.s && !args.g) {
		console.log(chalk.red.bold(`Uso incorreto, tente 'sshc key link [name] [-s|-g] [server alias|group name]'`));
		process.exit(1);
	}
	
	try {
		await API.linkKey(params[2], { server: args.s || null, group: args.g || null });
		console.log(chalk.green.bold(`Chave associada com sucesso!`))
	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um erro ao associar chave...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(1);
	}
}

module.exports.keyImport = async (args) => {
	const params = args._;

	if(!params[2]) {
		console.log(chalk.red.bold(`Falta o caminho do arquivo! Tente 'sshc key import /path/to/private /path/to/public'`));
		process.exit(1);
	}

	if(!args.n) {
		console.log(chalk.red.bold(`Falta nome para a chave, tente 'sshc key import -n nomeChave ${params[2]}'`));
		process.exit(1);
	}

	if(/[^a-z0-9\.\-_]/gi.test(args.n)) {
		console.log(chalk.red.bold(`Nome inválido, é permitido apenas os caracteres [a-Z 0-9 - _ .]`));
		process.exit(1);
	}
	
	const formData = await prompt({
		type: 'password',
		name: 'password',
		message: 'Digite a senha da chave (ou deixe em branco):'
	});

	try {
		const name = args.n ? args.n : null;
		const privateFile = params[2] ? params[2] : null;
		const publicFile = params[3] ? params[3] : null;

		if(!privateFile || !fs.existsSync(privateFile)) {
			console.log(chalk.red(`O arquivo '${privateFile}' não existe.`));
			process.exit(1);
		}

		if(publicFile && !fs.existsSync(publicFile)) {
			console.log(chalk.red(`O arquivo '${publicFile}' não existe.`));
			process.exit(1);
		}
		
		const privateFileData = fs.readFileSync(privateFile).toString('utf8');
		const publicFileData = publicFile ? fs.readFileSync(publicFile).toString('utf8') : null;

		let r = await API.newKey(name, privateFileData, formData.password, publicFileData);

		console.log(chalk.green.bold(`Chave salva com sucesso!`))

	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um ao importar key...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(1);
	}
	
}

module.exports.keyAdd = async (args) => {
	console.log(chalk.gray(`Not implemented`));
}

module.exports.keyList = async (args) => {
	const table = new Table({
		head: ['Nome']
	});

	try {
		let r = await API.search(args._[2] || null).listKeys(args.g || null);

		if(!r.data || r.data.length == 0) {
			console.log(chalk.red(`Nenhuma chave cadastrada`));
			process.exit(0);
		}
		
		for (const item of r.data) {
			table.push([
				// item.id,
				item.name
			]);
		}
		console.log(chalk.yellow.bold(`Chaves cadastradas:`));
		console.log(table.toString());

	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um ao listar...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(0);
	}
}

module.exports.keyDelete = async (args) => {
	const idOrAlias = args._[2] || null;
	if(!idOrAlias) {
		console.log(chalk.red(`ID ou Alias da chave é obrigatório, tente 'sshc key delete/del/rm [id OR name]'`));
		process.exit(1);
	}

	try {
		await API.deleteKey(idOrAlias);
		console.log(chalk.green.bold(`Chave excluida com sucesso!`));
	} catch(err){
		console.error(chalk.red.bold('Ocorreu um erro ao deletar chave...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(0);
	}
}

module.exports.serverAdd = async (args) => {

	const params = {
		name: args.n || args.name || null,
		alias: args.a || args.alias || null,
		host: args.h || args.host || null,
		port: args.p || args.port || null,
		username: args.u || args.username || null,
		password: null,
		description: args.d || args.description || null,
		permId: args.k || null,
		groupId: args.g || null
	}

	// if(!params.name || typeof params.name != "string") {
	// 	console.log(chalk.red.bold(`Nome é obrigatório [-n|--name]`));
	// 	process.exit(1);
	// }

	if(!params.alias || typeof params.alias != "string") {
		console.log(chalk.red.bold(`Alias é obrigatória [-a|--alias]`));
		process.exit(1);
	}

	if(/[^a-z0-9\.\-_]/gi.test(params.alias)) {
		console.log(chalk.red.bold(`Alias inválido, é permitido apenas os caracteres [a-Z 0-9 - _ .]`));
		process.exit(1);
	}

	// if(!params.host || typeof params.host != "string") {
	// 	console.log(chalk.red.bold(`Host é obrigatório [-h|--host]`));
	// 	process.exit(1);
	// }

	if(params.host && /\:[0-9]{2,5}$/g.test(params.host)) {
		let hostPort = params.host.split(':',2);
		params.host = hostPort[0];
		params.port = +hostPort[1];
	}

	// if(!params.port || typeof params.port != "number") {
	// 	console.log(chalk.red.bold(`Porta é obrigatória, tente ex.: [--port] OU ${params.host}:22 `));
	// 	process.exit(1);
	// }

	// if(!params.username || typeof params.username != "string") {
	// 	console.log(chalk.red.bold(`Username é obrigatório [-u|--username]`));
	// 	process.exit(1);
	// }

	if(args.pass || args.password) {
		const formData = await prompt({
			type: 'password',
			name: 'password',
			message: 'Digite a senha do servidor (ou deixe em branco):'
		});
		params.password = formData.password;
	}

	if(args.key) {
		try {
			const choices = { 'Não associar': null };
			const keys = await API.getKeys();
			for (const k of keys.data) {
				choices[k.name] = k.id;
			}

			const selectedKey = await new Select({
				name: 'chave',
				message: 'Selecione uma chave:',
				choices: Object.keys(choices)
			}).run();

			if(selectedKey && typeof choices[selectedKey] != "undefined") {
				params.permId = choices[selectedKey];
			}

		} catch(err) {
			console.error(chalk.red.bold('Ocorreu um ao buscar chaves...'));
			if(err.response && err.response.body && err.response.body.message) 
				console.error(chalk.red(err.response.body.message));
			else
				console.error(chalk.red(err.message || err.stack || err));
			process.exit(1);
		}
	}

	if(args.group || args.grup) {
		try {
			const choices = { 'Não associar': null };
			const keys = await API.getGroups();
			for (const k of keys.data) {
				choices[k.name] = k.id;
			}
			const selectedOption = await new Select({
				name: 'grupo',
				message: 'Selecione um grupo:',
				choices: Object.keys(choices)
			}).run();

			if(selectedOption && typeof choices[selectedOption] != "undefined") {
				params.groupId = choices[selectedOption];
			}

		} catch(err) {
			console.error(chalk.red.bold('Ocorreu um ao buscar grupos...'));
			if(err.response && err.response.body && err.response.body.message) 
				console.error(chalk.red(err.response.body.message));
			else
				console.error(chalk.red(err.message || err.stack || err));
			process.exit(1);
		}
	}

	console.log(params)

	try {
		let r = await API.newServer(params);
		console.log(chalk.green.bold(`Servidor salvo com sucesso!`));
	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um ao salvar servidor...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(1);
	}

}

module.exports.serverAddWithForm = async (args) => {
	console.log(chalk.gray(`Not implemented`));
	// const formData = await new Form({
	// 	name: 'server',
	// 	message: 'Adicionar um novo servidor:',
	// 	choices: [
	// 	  { name: 'name', message: 'Nome', initial: '', required: true },
	// 	  { name: 'alias', message: 'Alias/Atalho', initial: '', required: true, validate: s => !/[^a-z0-9\.\-_]/gi.test(s) },
	// 	  { name: 'host', message: 'Host', initial: '', required: true },
	// 	  { name: 'port', message: 'Porta', initial: '', required: true },
	// 	  { name: 'username', message: 'User', initial: '', required: true },
	// 	  { name: 'description', message: 'Descrição', initial: '', required: false }
	// 	]
	//   }).run();

	//   console.dir(formData);
}

module.exports.serverDelete = async (args) => {
	const idOrAlias = args._[2] || null;
	if(!idOrAlias) {
		console.log(chalk.red(`ID ou Alias do servidor é obrigatório, tente 'sshc server delete/del/rm [id OR alias]'`));
		process.exit(1);
	}

	try {
		await API.deleteServer(idOrAlias);
		console.log(chalk.green.bold(`Servidor excluido com sucesso!`));
	} catch(err){
		console.error(chalk.red.bold('Ocorreu um erro ao deletar servidor...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		process.exit(1);
	}
}

module.exports.serverList = async (args) => {
	const table = new Table({
		head: ['Alias','Name', 'Username','Host/Port', 'Key', 'Description']
	});

	try {
		const r = await API.search(args._[2] || null).listServers(args.g || null);

		if(!r.data || r.data.length == 0) {
			console.error(chalk.red(`Nenhum servidor cadastrado`));
			process.exit(0);
		} 

		for (const item of r.data) {
			if(item.groupName) item.alias = `${item.alias} (${chalk.bold.cyan(item.groupName)})`;
			table.push([
				item.alias,
				item.name || '-',
				item.username,
				item.port ? `${item.host}:${item.port}` : item.host,
				item.perm.name || '-',
				item.description || '-'
			]);
		}

		console.log(chalk.yellow.bold(`Servidores cadastrados:`));
		console.log(table.toString());

	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um ao listar...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(1);
	}
}

module.exports.groupAdd = async (args) => {
	const params = {
		name: args.n || args.name || null,
		port: args.p || args.port || null,
		username: args.u || args.username || null,
		password: null,
		description: args.d || args.description || null,
		permId: args.k || null
	}

	if(!params.name || typeof params.name != "string") {
		console.log(chalk.red.bold(`Nome é obrigatório [-n|--name]`));
		process.exit(1);
	}

	if(/[^a-z0-9\.\-_]/gi.test(params.name)) {
		console.log(chalk.red.bold(`Nome inválido, é permitido apenas os caracteres [a-Z 0-9 - _ .]`));
		process.exit(1);
	}

	if(args.pass || args.password) {
		const formData = await prompt({
			type: 'password',
			name: 'password',
			message: 'Digite a senha do servidor (ou deixe em branco):'
		});
		params.password = formData.password;
	}

	if(args.key) {
		try {
			const choices = { 'Não associar': null };
			const keys = await API.getKeys();
			for (const k of keys.data) {
				choices[k.name] = k.id;
			}

			const selectedKey = await new Select({
				name: 'chave',
				message: 'Selecione uma chave:',
				choices: Object.keys(choices)
			}).run();

			if(selectedKey && typeof choices[selectedKey] != "undefined") {
				params.permId = choices[selectedKey];
			}

		} catch(err) {
			console.error(chalk.red.bold('Ocorreu um ao buscar chaves...'));
			if(err.response && err.response.body && err.response.body.message) 
				console.error(chalk.red(err.response.body.message));
			else
				console.error(chalk.red(err.message || err.stack || err));
			process.exit(1);
		}
	}

	try {
		let r = await API.newGroup(params);
		console.log(chalk.green.bold(`Grupo salvo com sucesso!`));
	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um ao salvar...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(1);
	}
}

module.exports.groupList = async (args) => {
	const table = new Table({
		head: ['Nome','Porta','Usuário','Key']
	});

	try {
		const r = await API.search(args._[2] || null).listGroups();
		
		if(!r.data || r.data.length == 0) {
			console.log(chalk.red(`Nenhum grupo cadastrado`));
			process.exit(0);
		}
		
		for (const item of r.data) {
			table.push([
				item.name,
				item.port || '-',
				item.username || '-',
				item.perm.name || '-'
			]);
		}
		console.log(chalk.yellow.bold(`Grupos cadastrados:`));
		console.log(table.toString());

	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um ao listar...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(0);
	}
}

module.exports.groupDelete = async (args) => {
	const idOrAlias = args._[2] || null;
	if(!idOrAlias) {
		console.log(chalk.red(`Nome do grupo é obrigatório, tente 'sshc group delete/del/rm <group name>'`));
		process.exit(1);
	}

	try {
		await API.deleteGroup(idOrAlias);
		console.log(chalk.green.bold(`Grupo excluido com sucesso!`));
	} catch(err){
		console.error(chalk.red.bold('Ocorreu um erro ao deletar...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(0);
	}
}

module.exports.groupUnlink = async (args) => {
	const params = args._;

	if(!params[2]) {
		console.log(chalk.red.bold(`Uso incorreto, tente 'sshc group unlink <server alias>'`));
		process.exit(1);
	}

	try {
		await API.unlinkGroup(params[2]);
		console.log(chalk.green.bold(`Grupo desassociado com sucesso!`))
	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um erro ao desassociar...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(1);
	}
}

module.exports.groupLink = async (args) => {
	const params = args._;

	if(!params[2] || !params[3]) {
		console.log(chalk.red.bold(`Uso incorreto, tente 'sshc group <group name> <server alias>'`));
		process.exit(1);
	}
	
	try {
		await API.linkGroup(params[2], params[3]);
		console.log(chalk.green.bold(`Group associado com sucesso!`))
	} catch(err) {
		console.error(chalk.red.bold('Ocorreu um erro ao associar...'));
		if(err.response && err.response.body && err.response.body.message) 
			console.error(chalk.red(err.response.body.message));
		else
			console.error(chalk.red(err.message || err.stack || err));
		
		process.exit(1);
	}
}

// module.exports.x = async () => {}