const {auth: {read, write, drop}} = require("./config");
const Api = require("./socket-api")
const url = require("url");

function checkHost(str) {
  const {protocol, host} = url.parse(str);
  if(host && ["http:", "https:"].includes(protocol)) return protocol+"//"+host;
  throw "Invalid host";
}

const promptPassword = username => new Promise(resolve => {
  const prompt = require("prompt");
  prompt.message = prompt.delimiter = "";
  prompt.start({stdout: process.stderr});
  prompt.get([{
    name: "password",
    description: `Password for '${username}': `,
    hidden: true, required: true, replace: "*"
  }], (err, res) => {
    if(err){
      err.message == "canceled" || console.error(err);
      process.stderr.write("\n")
      process.exit(1);
    }
    resolve(res.password);
  })
})

const connect = host => Api(host, {
  timeout: 60 * 1000, keepConnection: 5 * 60 * 1000,
  socket: {secure: true, rejectUnauthorized: false, verify: false}
});

async function login({_, username, password, host} = {}) {
  if(username && !_.includes("login")) {
    host = checkHost(host || "http://localhost:3000")
    const api = connect(host);
    api.host = host;
    try{
      await api.auth.login({data: {username, password: password || await promptPassword(username)}})
    } catch(error) {
      console.error(error);
      process.exit(1);
    }
    return {api}
  }
  const config = read() || {};
  username = username || config.username;
  host = checkHost(host || config.host || "http://localhost:3000");
  if(!username || !host) throw "Please login";
  const api = connect(host);
  api.host = host;

  if(_.includes("login") || config.username != username || config.host != host) {
    await api.auth.login({data: {username, password: password || await promptPassword(username)}});
    const {data} = await api.socket.refreshToken();
    write({...config, username, token: data, host});
    return {api};
  }

  try {
    await api.auth.login({query: {refreshToken: config.token}});
    const {data} = await api.socket.refreshToken();
    config.token = data;
    write(config);
    return {api};
  } catch (error) {
    if (error.code != 'api.auth.token_expired') {
      console.error(error)
      process.exit(1)
    }
    console.error("Token expired. Relogin")
  }

  try {
    await api.auth.login({data: {username, password: password || await promptPassword(username)}});
    const {data} = await api.socket.refreshToken();
    write({username, token: data, host});
    return {api};
  } catch (error) {
    console.error(error)
    process.exit(1)
  }
}

login.cli = yargs => yargs.command({
  command: 'login',
  desc: 'Login to api',
  builder: yargs => yargs
    .demandOption('username')
    .demandOption('host'),
  handler: argv => login(argv).then(({api}) => (console.log("Logged in"), api.close())).catch(error => {
    console.error(error)
    process.exit(1)
  })
}).command({
  command: 'logout',
  desc: 'Logout',
  handler() {drop()},
})

module.exports = login
