package org.springblade.system.bladeuserex.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springblade.core.log.annotation.ApiLog;
import org.springblade.core.mp.support.BaseEntityWrapper;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.modules.auth.granter.ITokenGranter;
import org.springblade.modules.auth.granter.TokenGranterBuilder;
import org.springblade.modules.auth.granter.TokenParameter;
import org.springblade.modules.auth.utils.TokenUtil;
import org.springblade.modules.system.entity.User;

import org.springblade.modules.system.entity.UserInfo;
import org.springblade.modules.system.service.IParamService;
import org.springblade.modules.system.service.IUserService;

import org.springblade.system.bladeuserex.social.SocialTokenGranter;
import org.springblade.system.bladeuserex.social.SocialUtil;
import org.springblade.system.bladeuserex.vo.UserVO;
import org.springblade.system.bladeuserex.wrapper.UserWrapper;
import org.springblade.system.orgposition.service.IOrgPositionService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * Created By lidexi in 2021/3/24
 **/
@RestController
@AllArgsConstructor
@RequestMapping("blade-user")
@Api(value = "", tags = "接口")
@Slf4j
public class UserExController {

	private IUserService userService;
	private IOrgPositionService orgPositionService;
	private RedisTemplate<String,String> redisTemplate;

	private final static String LOGIN_ERROR_PREFIX = "loginerror:";
	private IParamService paramService;

	@GetMapping("/info-strength")
	public R<UserVO> info(BladeUser user) {
		User detail = this.userService.getById(user.getUserId());
		return R.data(UserWrapper.build(orgPositionService).entityVO(detail));
	}


	@ApiLog("登录用户验证扩展-增加登录错误阈值")
	@PostMapping({"/oauth/token"})
	@ApiOperation(
		value = "获取认证token",
		notes = "传入租户ID:tenantId,账号:account,密码:password"
	)
	public Kv token(@ApiParam(value = "租户ID",required = true) @RequestParam String tenantId, @ApiParam(value = "账号",required = true) @RequestParam(required = false) String username, @ApiParam(value = "密码",required = true) @RequestParam(required = false) String password
	) {
		Kv authInfo = Kv.create();
		String loginMaxErrorTimes = paramService.getValue("login.error.times");//登录错误阈值
		String currentTimes = redisTemplate.opsForValue().get(LOGIN_ERROR_PREFIX + tenantId + ":" + username);
		if (currentTimes != null) {
			if (Integer.valueOf(currentTimes) > Integer.valueOf(loginMaxErrorTimes)) {
				return authInfo.set("error_code", 400).set("error_description", "错误次数超过系统配置的阈值");
			}
		} else {
			currentTimes = "0";
		}

		String grantType = WebUtil.getRequest().getParameter("grant_type");
		String refreshToken = WebUtil.getRequest().getParameter("refresh_token");
		String userType = Func.toStr(WebUtil.getRequest().getHeader("User-Type"), "web");
		TokenParameter tokenParameter = new TokenParameter();
		tokenParameter.getArgs().set("tenantId", tenantId).set("username", username).set("password", password).set("grantType", grantType).set("refreshToken", refreshToken).set("userType", userType);
		ITokenGranter granter = TokenGranterBuilder.getGranter(grantType);
		UserInfo userInfo = granter.grant(tokenParameter);
		if (userInfo != null && userInfo.getUser() != null) {
			if(Func.isEmpty(userInfo.getRoles())){
				redisTemplate.opsForValue().set(LOGIN_ERROR_PREFIX+tenantId+":"+username,String.valueOf(Integer.valueOf(currentTimes)+1));
				return 	authInfo.set("error_code", 400).set("error_description", "未获得用户的角色信息");
			}else {
				return  TokenUtil.createAuthInfo(userInfo);
			}

		} else {
			redisTemplate.opsForValue().set(LOGIN_ERROR_PREFIX+tenantId+":"+username,String.valueOf(Integer.valueOf(currentTimes)+1));
			return authInfo.set("error_code", 400).set("error_description", "用户名或密码不正确");
		}
	}

	@ApiLog("登录用户验证扩展-增加登录错误阈值")
	@PostMapping({"/third/oauth/token"})
	@ApiOperation(
		value = "获取认证token",
		notes = "传入租户ID:tenantId,账号:account,密码:password"
	)
	public Kv OauthToken(@ApiParam(value = "租户ID",required = true) @RequestParam String tenantId,
						 @ApiParam(value = "账号",required = true) @RequestParam(required = false) String username,
						 @ApiParam(value = "密码",required = true) @RequestParam(required = false) String password
	) {
		Kv authInfo = Kv.create();
		String grantType = WebUtil.getRequest().getParameter("grant_type");
		String refreshToken = WebUtil.getRequest().getParameter("refresh_token");
		String userType = Func.toStr(WebUtil.getRequest().getHeader("User-Type"), "web");
		TokenParameter tokenParameter = new TokenParameter();
		tokenParameter.getArgs().set("tenantId", tenantId).set("username", username).set("password", password).set("grantType", grantType).set("refreshToken", refreshToken).set("userType", userType);
		ITokenGranter granter = null;
		if(grantType.equals("social")){
			granter = SpringUtil.getBean(SocialTokenGranter.class);
		}else{
			granter = TokenGranterBuilder.getGranter(grantType);
		}
		UserInfo userInfo = granter.grant(tokenParameter);
		if (userInfo == null || userInfo.getUser() == null) {
			return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "授权登录失败，请联系平台开通账号！");
		}

		if (Func.isEmpty(userInfo.getRoles())) {
			return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "未获得用户的角色信息");
		}

		return TokenUtil.createAuthInfo(userInfo);
	}

	/**
	 * 功能描述: 第三方访问授权
	 * @return ResultBean
	 *
	 *
	 */
	@RequestMapping(value = "/oauth/render/{source}")
	@ResponseBody
	public R renderAuth(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
		log.warn("进入render：" + source);
		AuthRequest authRequest = SocialUtil.getAuthRequest(source);
		String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
		log.warn(authorizeUrl);
		return R.data(authorizeUrl);
	}


}
