package com.inspect.admin.service;

import com.inspect.admin.SystemClient;
import com.inspect.base.core.domain.Response;
import com.inspect.base.core.domain.SysWarning;
import com.inspect.base.core.enums.UserStatus;
import com.inspect.base.core.exception.ServiceException;
import com.inspect.base.core.utils.JwtUtils;
import com.inspect.base.core.utils.ServletUtils;
import com.inspect.base.core.utils.StringUtils;
import com.inspect.base.core.utils.ip.IpUtils;
import com.inspect.base.redis.service.RedisService;
import com.inspect.common.security.utils.SecurityUtils;
import com.inspect.system.base.RemoteLogService;
import com.inspect.system.base.RemoteUserService;
import com.inspect.system.base.domain.SysLoginFor;
import com.inspect.system.base.domain.SysUser;
import com.inspect.system.base.model.LoginUser;
import io.jsonwebtoken.Claims;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

@Component
public class SysLoginService {
   @Autowired
   private RemoteLogService remoteLogService;
   @Autowired
   private RemoteUserService remoteUserService;
   @Resource
   RedisService redisService;
   @Resource
   SystemClient systemClient;
   protected static final long MINUTE_SECOND = 60L;
   private static Logger logger = LoggerFactory.getLogger(SysLoginService.class);

   public LoginUser login(String username, String password, HttpServletRequest request) {
      this.verifyLoginFailTimes(username);
      LoginUser userInfo = this.commonLogin(username, password);
      this.verifyUserLoginIp(userInfo, request);
      this.recordLogininfor(username, "Success", "登录成功");
      return userInfo;
   }

   public String secondLogin(String username, String password, HttpServletRequest request) {
      try {
         String token = this.getToken(request);
         Claims claims = JwtUtils.parseToken(token);
         String tokenUserName = JwtUtils.getUserName(claims);
         this.commonLogin(tokenUserName, password);
         return this.awardTicket();
      } catch (Exception var7) {
         throw var7;
      }
   }

   private String getToken(HttpServletRequest request) {
      String token = request.getHeader("Authorization");
      if(StringUtils.isNotEmpty(token) && token.startsWith("Bearer ")) {
         token = token.replaceFirst("Bearer ", "");
      }

      return token;
   }

   public String awardTicket() {
      String ticket = UUID.randomUUID().toString().replaceAll("-", "");
      this.redisService.redisTemplate.opsForValue().set(ticket, Integer.valueOf(1), 5L, TimeUnit.MINUTES);
      return ticket;
   }

   public LoginUser commonLogin(String username, String password) {
      if(StringUtils.isAnyBlank(new CharSequence[]{username, password})) {
         this.recordLogininfor(username, "Error", "用户/密码必须填写");
         throw new ServiceException("用户/密码必须填写");
      } else if(password.length() >= 5 && password.length() <= 40) {
         logger.info("[GABRIEL] username: {}, password: {}", username, password);
         if(username.length() >= 2 && username.length() <= 20) {
            Response<LoginUser> userResult = this.remoteUserService.getUserInfo(username, "inner");
            if(Response.FAIL == userResult.getCode()) {
               throw new ServiceException(userResult.getMsg());
            } else if(!StringUtils.isNull(userResult) && !StringUtils.isNull(userResult.getData())) {
               LoginUser userInfo = (LoginUser)userResult.getData();
               SysUser user = ((LoginUser)userResult.getData()).getSysUser();
               if(UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
                  this.recordLogininfor(username, "Error", "对不起，您的账号已被删除");
                  throw new ServiceException("对不起，您的账号：" + username + " 已被删除");
               } else if(UserStatus.DISABLE.getCode().equals(user.getStatus())) {
                  this.recordLogininfor(username, "Error", "用户已停用，请联系管理员");
                  throw new ServiceException("对不起，您的账号：" + username + " 已停用");
               } else if(!SecurityUtils.matchesPassword(password, user.getPassword())) {
                  int failNum = this.incrWrongNum(username);
                  this.recordLogininfor(username, "Error", "用户密码错误");
                  int surplusNum = 5 - failNum + 1;
                  throw new ServiceException("密码错误,再错误" + surplusNum + "次后将被锁定");
               } else {
                  this.resetWrongNum(username);
                  return userInfo;
               }
            } else {
               this.recordLogininfor(username, "Error", "登录用户不存在");
               throw new ServiceException("登录用户：" + username + " 不存在");
            }
         } else {
            this.recordLogininfor(username, "Error", "用户名不在指定范围");
            throw new ServiceException("用户名不在指定范围");
         }
      } else {
         this.recordLogininfor(username, "Error", "用户密码不在指定范围");
         throw new ServiceException("用户密码不在指定范围");
      }
   }

   private void verifyUserLoginIp(LoginUser userInfo, HttpServletRequest request) {
      String requestIp = IpUtils.getIpAddr(request);
      Set<String> roles = userInfo.getRoles();
      String username = userInfo.getUsername();
      if(!roles.contains("admin")) {
         String aollowIp = userInfo.getSysUser().getAollowIp();
         if(StringUtils.isBlank(aollowIp)) {
            throw new ServiceException("用户未绑定登录ip，不允许登录");
         } else if(!StringUtils.equals(requestIp, aollowIp)) {
            try {
               SysWarning sysWarning = this.generateLoginErrorLogVo("用户登录ip与绑定ip不同，已禁止登录", Integer.valueOf(2), username);
               this.systemClient.saveWarning(sysWarning);
            } catch (Exception var8) {
               logger.error("记录登录错误次数超限日志时，捕获异常", var8);
            }

            throw new ServiceException("登录IP与用户绑定的IP不同，不允许登录");
         }
      }
   }

   public void logout(String loginName) {
      this.recordLogininfor(loginName, "Logout", "退出成功");
   }

   public int incrWrongNum(String username) {
      RedisTemplate redisTemplate = this.redisService.redisTemplate;
      ValueOperations valueOperations = redisTemplate.opsForValue();
      String loginFailKey = this.getLoginFailKey(username);
      if(redisTemplate.hasKey(loginFailKey).booleanValue()) {
         valueOperations.increment(loginFailKey);
         Object o = valueOperations.get(loginFailKey);
         return ((Integer)o).intValue();
      } else {
         valueOperations.set(loginFailKey, Integer.valueOf(1), 30L, TimeUnit.MINUTES);
         return 1;
      }
   }

   public void resetWrongNum(String username) {
      RedisTemplate redisTemplate = this.redisService.redisTemplate;
      ValueOperations valueOperations = redisTemplate.opsForValue();
      String loginFailKey = this.getLoginFailKey(username);
      this.redisService.deleteObject(loginFailKey);
   }

   public void verifyLoginFailTimes(String username) {
      RedisTemplate redisTemplate = this.redisService.redisTemplate;
      ValueOperations<String, Integer> valueOperations = redisTemplate.opsForValue();
      String loginFailKey = this.getLoginFailKey(username);
      if(redisTemplate.hasKey(loginFailKey).booleanValue()) {
         Integer failNum = (Integer)valueOperations.get(loginFailKey);
         if(failNum.intValue() >= 5) {
            Long expire = redisTemplate.getExpire(loginFailKey);
            long minute = 0L;
            if(expire.longValue() > 0L) {
               minute = expire.longValue() / 60L;
               if(minute < 1L) {
                  minute = 1L;
               }
            }

            try {
               SysWarning sysWarning = this.generateLoginErrorLogVo("登录失败次数已达最大限制，限制登录" + minute + "分钟", Integer.valueOf(1), username);
               this.systemClient.saveWarning(sysWarning);
            } catch (Exception var10) {
               logger.error("记录登录错误次数超限日志时，捕获异常", var10);
            }

            throw new ServiceException("用户锁定，请等待" + minute + "分钟后重试");
         }
      }

   }

   public SysWarning generateLoginErrorLogVo(String text, Integer level, String userName) {
      SysWarning warning = new SysWarning();
      warning.setText(text);
      warning.setLevel(level);
      warning.setSourceName("系统");
      warning.setUserName(userName);
      warning.setType(Integer.valueOf(0));
      return warning;
   }

   public String getLoginFailKey(String username) {
      return "login_fail_times:" + username;
   }

   public void register(String username, String password) {
      if(StringUtils.isAnyBlank(new CharSequence[]{username, password})) {
         throw new ServiceException("用户/密码必须填写");
      } else if(username.length() >= 2 && username.length() <= 20) {
         if(password.length() >= 5 && password.length() <= 40) {
            SysUser sysUser = new SysUser();
            sysUser.setUserName(username);
            sysUser.setNickName(username);
            sysUser.setPassword(SecurityUtils.encryptPassword(password));
            Response<?> registerResult = this.remoteUserService.registerUserInfo(sysUser, "inner");
            if(Response.FAIL == registerResult.getCode()) {
               throw new ServiceException(registerResult.getMsg());
            } else {
               this.recordLogininfor(username, "Register", "注册成功");
            }
         } else {
            throw new ServiceException("密码长度必须在5到20个字符之间");
         }
      } else {
         throw new ServiceException("账户长度必须在2到20个字符之间");
      }
   }

   public void recordLogininfor(String username, String status, String message) {
      SysLoginFor logininfor = new SysLoginFor();
      logininfor.setUserName(username);
      logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
      logininfor.setMsg(message);
      if(StringUtils.equalsAny(status, new CharSequence[]{"Success", "Logout", "Register"})) {
         logininfor.setStatus("0");
      } else if("Error".equals(status)) {
         logininfor.setStatus("1");
      }

      this.remoteLogService.saveLogininfor(logininfor, "inner");
   }
}
