package im.zhaojun.zfile.module.user.service.login;

import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import dev.samstevens.totp.code.CodeVerifier;
import dev.samstevens.totp.exceptions.QrGenerationException;
import dev.samstevens.totp.qr.QrData;
import dev.samstevens.totp.qr.QrDataFactory;
import dev.samstevens.totp.qr.QrGenerator;
import dev.samstevens.totp.secret.SecretGenerator;
import im.zhaojun.zfile.core.exception.ErrorCode;
import im.zhaojun.zfile.core.exception.status.ForbiddenAccessException;
import im.zhaojun.zfile.module.config.model.dto.SystemConfigDTO;
import im.zhaojun.zfile.module.config.service.SystemConfigService;
import im.zhaojun.zfile.module.user.model.request.VerifyLoginTwoFactorAuthenticatorRequest;
import im.zhaojun.zfile.module.user.model.result.LoginTwoFactorAuthenticatorResult;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;

import static dev.samstevens.totp.util.Utils.getDataUriForImage;

/**
 * 2FA 双因素认证 Service
 *
 * @author zhaojun
 */
@Service
public class TwoFactorAuthenticatorVerifyService {

	@Resource
	private SecretGenerator secretGenerator;

	@Resource
	private QrDataFactory qrDataFactory;

	@Resource
	private QrGenerator qrGenerator;

	@Resource
	private CodeVerifier verifier;

	@Resource
	private SystemConfigService systemConfigService;


	/**
	 * 生成 2FA 双因素认证二维码和密钥
	 *
	 * @return  2FA 双因素认证二维码和密钥
	 * @throws  QrGenerationException   二维码生成异常
	 */
	public LoginTwoFactorAuthenticatorResult setupDevice() throws QrGenerationException {
		// 生成 2FA 密钥
		String secret = secretGenerator.generate();
		QrData data = qrDataFactory.newBuilder().secret(secret).issuer("ZFile").build();

		// 将生成的 2FA 密钥转换为 Base64 图像字符串
		String qrCodeImage = QrCodeUtil.generateAsBase64(data.getUri(), new QrConfig(300, 300), QrCodeUtil.QR_TYPE_SVG);

		return new LoginTwoFactorAuthenticatorResult(qrCodeImage, secret);
	}


	/**
	 * 验证 2FA 双因素认证是否正确，正确则进行绑定.
	 *
	 * @param   verifyLoginTwoFactorAuthenticatorRequest
	 *          2FA 双因素认证请求参数
	 */
	public void deviceVerify(VerifyLoginTwoFactorAuthenticatorRequest verifyLoginTwoFactorAuthenticatorRequest) {
		String secret = verifyLoginTwoFactorAuthenticatorRequest.getSecret();
		String code = verifyLoginTwoFactorAuthenticatorRequest.getCode();

		checkCode(secret, code);

		SystemConfigDTO systemConfig = systemConfigService.getSystemConfig();
//			systemConfig.setLoginVerifyMode(LoginVerifyModeEnum.TWO_FACTOR_AUTHENTICATION_MODE);
		systemConfig.setAdminTwoFactorVerify(true);
		systemConfig.setLoginVerifySecret(secret);
		systemConfigService.updateSystemConfig(systemConfig);
	}


	/**
	 * 验证 2FA 双因素认证.
	 *
	 * @param   loginVerifySecret
	 *          2FA 双因素认证密钥
	 *
	 * @param   verifyCode
	 *          2FA 双因素认证验证码
	 *
	 * @throws 	ForbiddenAccessException 	2FA 双因素认证失败会抛出此异常
	 */
	public void checkCode(String loginVerifySecret, String verifyCode) {
		if (!verifier.isValidCode(loginVerifySecret, verifyCode)) {
			throw new ForbiddenAccessException(ErrorCode.BIZ_2FA_CODE_ERROR);
		}
	}

}