import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core";
import { UserSettingsService } from "./user-settings-service.js";
import { UserTwoFactorSetting } from "./models.js";
import { UserService } from "../../sys/authority/service/user-service.js";

/**
 * 授权
 */
@Provide()
@Scope(ScopeEnum.Request, { allowDowngrade: true })
export class TwoFactorService {
  @Inject()
  userSettingsService: UserSettingsService;
  @Inject()
  userService: UserService;


  async getAuthenticatorQrCode(userId: any) {
    const setting = await this.getSetting(userId)

    const authenticatorSetting = setting.authenticator;
    if (!authenticatorSetting.secret) {
      const { authenticator  } = await import("otplib");

      authenticatorSetting.secret = authenticator.generateSecret()
      await this.userSettingsService.saveSetting(userId, setting);
    }

    const user = await this.userService.info(userId);
    const username = user.username;
    const secret = authenticatorSetting.secret;
    const qrcodeContent = `otpauth://totp/Certd:${username}?secret=${secret}&issuer=Certd`;

    //生成qrcode base64
    const qrcode = await import("qrcode");
    return await qrcode.toDataURL(qrcodeContent);

  }

  async saveAuthenticator(req: { userId: any; verifyCode: any }) {
    const userId = req.userId;
    const { authenticator } = await import("otplib");
    const setting = await this.getSetting(userId)

    const authenticatorSetting = setting.authenticator;
    if (!authenticatorSetting.secret) {
      throw new Error("secret is required");
    }
    const secret = authenticatorSetting.secret;
    const token = req.verifyCode;

    const isValid = authenticator.verify({ token, secret });
    if (!isValid) {
      throw new Error("authenticator 校验错误");
    }

    //校验成功，保存开启状态
    authenticatorSetting.enabled = true;
    authenticatorSetting.verified = true;

    await this.userSettingsService.saveSetting(userId, setting);
  }

  async offAuthenticator(userId:number) {
    if (!userId) {
      throw new Error("userId is required");
    }

    const setting = await this.getSetting(userId)
    setting.authenticator.enabled = false;
    setting.authenticator.verified = false;
    setting.authenticator.secret = '';
    await this.userSettingsService.saveSetting(userId, setting);
  }

  async getSetting(userId:number) {
    return await this.userSettingsService.getSetting<UserTwoFactorSetting>(userId, UserTwoFactorSetting);

  }

  async verifyAuthenticatorCode(userId: any, verifyCode: string) {
    const { authenticator } = await import("otplib");
    const setting = await this.getSetting(userId)
    if (!setting.authenticator.enabled) {
      throw new Error("authenticator 未开启");
    }
    if (!authenticator.verify({ token: verifyCode, secret: setting.authenticator.secret })) {
      throw new Error("验证码错误");
    }
    return true;
  }
}
