import { Reception } from './classes.reception.js';
import { User } from './classes.user.js';
import * as plugins from '../plugins.js';

/**
 * a user manager
 */
export class UserManager {
  // refs
  public receptionRef: Reception;
  public typedrouter = new plugins.typedrequest.TypedRouter();
  public get db() {
    return this.receptionRef.db.smartdataDb;
  }

  // classes
  public CUser = plugins.smartdata.setDefaultManagerForDoc(this, User);

  constructor(receptionRefArg: Reception) {
    this.receptionRef = receptionRefArg;
    this.receptionRef.typedrouter.addTypedRouter(this.typedrouter);
    this.typedrouter.addTypedHandler<plugins.idpInterfaces.request.IReq_GetRolesAndOrganizationsForUserId>(
      new plugins.typedrequest.TypedHandler('getRolesAndOrganizationsForUserId', async reqArg => {
        console.log('user manager: getting roles and orgs');
        const user = await this.getUserByJwtValidation(reqArg.jwt);
        const organizations = await this.receptionRef.organizationmanager.getAllOrganizationsForUser(
          user
        );
        const roles = await this.receptionRef.roleManager.getAllRolesForUser(user);
        return {
          organizations,
          roles
        }
      })
    )

    this.typedrouter.addTypedHandler<plugins.idpInterfaces.request.IReq_WhoIs>(
      new plugins.typedrequest.TypedHandler('whoIs', async reqArg => {
        const user = await this.getUserByJwtValidation(reqArg.jwt);
        if (!user) {
          throw new plugins.typedrequest.TypedResponseError('User not found');
        }
        return {
          user: {
            id: user.id,
            data: {
              name: user.data.name,
              username: user.data.username,
              email: user.data.email,
              mobileNumber: user.data.mobileNumber,
              connectedOrgs: user.data.connectedOrgs,
              status: null,
              password: null,
            } as plugins.idpInterfaces.data.IUser['data']
          }
        }
      })
    )
  }

  /**
   * gets the user by validating a JWT
   */
  public async getUserByJwt(jwtString: string) {
    const jwtInstance = await this.receptionRef.jwtManager.verifyJWTAndGetData(jwtString);
    const user = await this.CUser.getInstance({
      id: jwtInstance.data.userId
    });
    return user;
  }

  /**
   * just validate jwt
   * faster than the "getUserByJwt"
   */
  public async getUserByJwtValidation(jwtStringArg: string) {
    const jwtDataArg: plugins.idpInterfaces.data.IJwt = await this.receptionRef.jwtManager.smartjwtInstance.verifyJWTAndGetData(jwtStringArg);
    const resultingUser = await this.CUser.getInstance({
      id: jwtDataArg.data.userId
    });
    return resultingUser;
  }

}
