'use strict';

const {
  readConfigFile,
  writeConfigFile,
  refreshToken,
  listTenants,
} = require('@serverless/platform-sdk');
const configUtils = require('@serverless/utils/config');
const accountUtils = require('@serverless/utils/account');
const { ServerlessSDK } = require('@serverless/platform-client');

const sdk = new ServerlessSDK();

class User {
  constructor() {
    const user = configUtils.getLoggedInUser() || {};

    this.userId = user.userId;
    this.username = user.username;
    this.refreshToken = user.refreshToken;
    this.token = user.idToken;
    this.accessKeys = user.accessKeys;

    this.loginBrokerUrl = 'https://api.serverless.com/login/';

    if (process.env.SERVERLESS_PLATFORM_STAGE === 'dev') {
      this.loginBrokerUrl = 'https://api.serverless-dev.com/login/';
    }
  }

  isLoggedIn() {
    const user = configUtils.getLoggedInUser();

    if (!user) {
      return false;
    }

    return true;
  }

  async getToken() {
    if (!this.isLoggedIn()) {
      return null;
    }

    // refresh token if it's expired.
    // this platform-sdk method returns immediately if the idToken did not expire
    // if it did expire, it'll refresh it and update the config file
    await refreshToken();

    const userConfigFile = readConfigFile();

    // Verify config file and that the user is logged in
    if (!userConfigFile || !userConfigFile.users || !userConfigFile.users[userConfigFile.userId]) {
      return null;
    }

    const user = userConfigFile.users[userConfigFile.userId];

    this.token = user.idToken;

    return user.dashboard.idToken;
  }

  async startLogin() {
    // for some reason this env var is required by the SDK in order to open the browser
    process.env.DISPLAY = true;

    const { loginUrl, loginData } = await sdk.login({ loginBrokerUrl: this.loginBrokerUrl }); // eslint-disable-line

    // save the loginData promise to await it later
    this.loginData = loginData;

    return loginUrl;
  }

  async endLogin() {
    // await the loginData promise, which resolves
    // after the user logs in
    const loginData = await this.loginData;

    const loginDataToSaveInConfig = {
      userId: loginData.id,
      users: {
        [loginData.id]: {
          userId: loginData.id,
          name: loginData.name,
          email: loginData.email,
          username: loginData.username,
          dashboard: {
            refreshToken: loginData.refreshToken,
            accessToken: loginData.accessToken,
            idToken: loginData.idToken,
            expiresAt: loginData.expiresAt,
            username: loginData.username,
          },
        },
      },
    };

    configUtils.set(loginDataToSaveInConfig);
  }

  logout() {
    if (this.isLoggedIn()) {
      accountUtils.logout();
    }
  }

  async getOrgName() {
    const res = readConfigFile();

    if (!res.userId || !res.users || !res.users[res.userId] || !res.users[res.userId].dashboard) {
      return null;
    }

    let { defaultOrgName } = res.users[res.userId].dashboard;

    // if defaultOrgName is not in RC file, fetch it from the platform
    if (!defaultOrgName) {
      await refreshToken();

      const userConfigFile = readConfigFile();

      const { username, dashboard } = userConfigFile.users[userConfigFile.userId];
      const { idToken } = dashboard;
      const orgsList = await listTenants({ username, idToken });

      // filter by owner
      const filteredOrgsList = orgsList.filter((org) => org.role === 'owner');

      defaultOrgName = filteredOrgsList[0].orgName;

      res.users[res.userId].dashboard.defaultOrgName = defaultOrgName;

      writeConfigFile(res);
    }

    return defaultOrgName;
  }
}

module.exports = User;
