package com.jeequan.jeepay.agent.ctrl.anon;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.agent.ctrl.CommonCtrl;
import com.jeequan.jeepay.agent.service.AuthService;
import com.jeequan.jeepay.bizcommons.manage.auth.AuthByQrcodeManage;
import com.jeequan.jeepay.bizcommons.manage.sms.SmsManager;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.jwt.JWTPayload;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.JsonKit;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * 登录鉴权
 *
 * @author terrfly
 * @date 2021-04-27 15:50
 */
@RestController
@RequestMapping("/api/anon/auth")
public class AuthController extends CommonCtrl {

	@Autowired private AuthService authService;
	@Autowired private SmsManager smsManager;

	/** 用户信息认证 获取iToken  **/
	@RequestMapping(value = "/validate", method = RequestMethod.POST)
	@MethodLog(remark = "登录认证")
	public ApiRes validate() throws BizException {

		String loginPageType = Base64.decodeStr(getValStringRequired("lt"));	//登录页面（终端）类型,  已做base64处理

		// 是否app登录
		boolean isApp = loginPageType.equals(JWTPayload.LOGIN_PAGE_TYPE.APP) || loginPageType.equals(JWTPayload.LOGIN_PAGE_TYPE.LITE);

		String account = Base64.decodeStr(getValStringRequired("ia"));  //用户名 i account, 已做base64处理
		String ipassport = Base64.decodeStr(getValStringRequired("ip"));	//密码 i passport,  已做base64处理

		String vercode = isApp ? "" : Base64.decodeStr(getValStringRequired("vc"));	// 验证码 vercode,  已做base64处理
		String vercodeToken = isApp ? "" : Base64.decodeStr(getValStringRequired("vt"));	//验证码token, vercode token ,  已做base64处理

		String mfaCode = StringUtils.isEmpty(getValString("mc")) ? null : Base64.decodeStr(getValString("mc"));	// MFACode,  已做base64处理

		// 验证码校验: WEB登录 & 第一次认证（MFACode为空的情况）
		if(!isApp && StringUtils.isEmpty(mfaCode)){
			String cacheCode = RedisUtil.getString(CS.getCacheKeyImgCode(vercodeToken));
			if(StringUtils.isEmpty(cacheCode) || !cacheCode.equalsIgnoreCase(vercode)){
				throw new BizException("验证码有误！");
			}
		}

		// 返回前端 accessToken
		return authService.authByAuthentication(account, ipassport, loginPageType, vercodeToken, mfaCode);
	}

	/** 用户信息认证[手机验证码登录] 获取iToken  **/
	@RequestMapping(value = "/phoneCode", method = RequestMethod.POST)
	@MethodLog(remark = "手机验证码登录")
	public ApiRes phoneCode() throws BizException {

		String loginPageType = Base64.decodeStr(getValStringRequired("lt"));	//登录页面（终端）类型,  已做base64处理
		String phone = Base64.decodeStr(getValStringRequired("phone"));	// 手机号,  已做base64处理
        String code = Base64.decodeStr(getValStringRequired("code"));	// 验证码 code,  已做base64处理

		// 校验验证码 && 如果有异常 抛异常
		smsManager.checkSmsVercodeThrowBizEx(phone, code, CS.SMS_TYPE_API_ENUM.TYPE_AUTH);

		// 返回前端 accessToken
		return authService.authByPhoneCode(phone, loginPageType);
	}

	/** 图片验证码  **/
	@RequestMapping(value = "/vercode", method = RequestMethod.GET)
	public ApiRes vercode() throws BizException {

		//定义图形验证码的长和宽 // 4位验证码
		LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(137, 40, 4, 80);
        lineCaptcha.createCode(); //生成code

        //redis
		String vercodeToken = UUID.fastUUID().toString();
        RedisUtil.setString(CS.getCacheKeyImgCode(vercodeToken), lineCaptcha.getCode(), CS.VERCODE_CACHE_TIME ); //图片验证码缓存时间: 1分钟

        JSONObject result = new JSONObject();
        result.put("imageBase64Data", lineCaptcha.getImageBase64Data());
        result.put("vercodeToken", vercodeToken);
		result.put("expireTime", CS.VERCODE_CACHE_TIME);

		return ApiRes.ok(result);
	}


	/** 轮询  登录二维码状态  **/
	@GetMapping("/qrcodeStatus")
	public ApiRes qrcodeStatus() {

		String qrcodeNo = getValString("qrcodeNo");

		// 未传入qrcodeNo，直接返回一个，并存入redis，key：JEEPAY_LOGIN_QR_qrcodeNo
		if (StringUtils.isBlank(qrcodeNo)) {
			qrcodeNo = CS.getCacheKeyLoginQrcode(IdUtil.simpleUUID());
			AuthByQrcodeManage.setQrcodeStatusWaiting(qrcodeNo);
			return ApiRes.ok(JsonKit.newJson("qrcodeNo", qrcodeNo));
		}

		// 根据传入的qrcodeNo，判断二维码被扫状态
		String qrCodeStatus = RedisUtil.getString(qrcodeNo);

		// redis未查询到qrcodeNo信息
		if (StringUtils.isBlank(qrCodeStatus)) {
			return ApiRes.ok(JsonKit.newJson("qrcodeStatus", AuthByQrcodeManage.QRCODE_STATUS_EXPRIED));
		}

		JSONObject resJSON = new JSONObject();

		if (qrCodeStatus.startsWith(AuthByQrcodeManage.QRCODE_STATUS_CONFIRMED + "_")){

			String tokenStr = qrCodeStatus.replaceFirst(AuthByQrcodeManage.QRCODE_STATUS_CONFIRMED + "_", "");
			resJSON = JSONObject.parseObject(tokenStr);
			resJSON.put("qrcodeStatus", AuthByQrcodeManage.QRCODE_STATUS_CONFIRMED);

			// 清空二维码缓存
			AuthByQrcodeManage.delQrcodeStatus(qrcodeNo);

		}else if (qrCodeStatus.equals(AuthByQrcodeManage.QRCODE_STATUS_CANCELED)){

			resJSON.put("qrcodeStatus", AuthByQrcodeManage.QRCODE_STATUS_CANCELED);

			// 清空二维码缓存
			AuthByQrcodeManage.delQrcodeStatus(qrcodeNo);

		}else {
			resJSON.put("qrcodeStatus", qrCodeStatus);
		}

		return ApiRes.ok(resJSON);
	}

}
