import * as plugins from '../plugins.js';
import { JwtManager } from './classes.jwtmanager.js';

/**
 * a User is identified by its username or email.
 * Both need to be unique and both can be changed.
 */
@plugins.smartdata.Manager()
export class Jwt extends plugins.smartdata.SmartDataDbDoc<Jwt, plugins.idpInterfaces.data.IJwt, JwtManager> {
  // STATIC
  public static async createJwtForRefreshToken(
    jwtManagerInstance: JwtManager,
    refreshTokenArg: string
  ) {
    const loginSession =
      await jwtManagerInstance.receptionRef.loginSessionManager.CLoginSession.getLoginSessionByRefreshToken(
        refreshTokenArg
      );
    if (!loginSession) {
      return null;
    }
    const refreshTokenValid = await loginSession.validateRefreshToken(refreshTokenArg);
    if (!refreshTokenValid) {
      return null;
    }
    const user = await jwtManagerInstance.receptionRef.userManager.CUser.getInstance({
      id: loginSession.data.userId,
    });
    const validUntil = plugins.smarttime.ExtendedDate.fromMillis(
      Date.now() + plugins.smarttime.getMilliSecondsFromUnits({ days: 1 })
    );
    const jwt = new Jwt();
    jwt.id = plugins.smartunique.shortId();
    jwt.data = {
      userId: user.id,
      validUntil: validUntil.getTime(),
      refreshEvery: 1000000,
      refreshFrom: Date.now() + plugins.smarttime.getMilliSecondsFromUnits({ days: 0.5 }),
      refreshToken: await loginSession.getRefreshToken(), // TODO: handle multiple refresh tokens
      justForLooks: {
        validUntilIsoString: validUntil.toISOString(),
      }
    };

    await jwt.save();

    const jwtString = await jwtManagerInstance.smartjwtInstance.createJWT({
      id: jwt.id,
      blocked: null,
      data: jwt.data,
    } as plugins.idpInterfaces.data.IJwt);
    return jwtString;
  }

  // INSTANCE
  @plugins.smartdata.unI()
  public id: string;

  @plugins.smartdata.svDb()
  public blocked: boolean = false;

  @plugins.smartdata.svDb()
  public data: plugins.idpInterfaces.data.IJwt['data'];

  public async block() {
    this.blocked = true;
    await this.save();
  }

  public async getLoginSession() {
    const loginSession = await this.manager.receptionRef.loginSessionManager.CLoginSession.getInstance({
      data: {
        refreshToken: this.data.refreshToken,
      }
    });
    return loginSession;
  }
}
