package com.yfd.platform.system.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yfd.platform.component.nettyudpserver.NettyUdpServer;
import com.yfd.platform.system.domain.LoginUser;
import com.yfd.platform.system.domain.SysLog;
import com.yfd.platform.system.domain.SysUser;
import com.yfd.platform.system.mapper.SysMenuMapper;
import com.yfd.platform.system.service.ISysLogService;
import com.yfd.platform.system.service.IUserService;
import com.yfd.platform.utils.sm3.SM3Utils;
import io.netty.channel.Channel;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户服务实现类  继承UserDetailsService  实现接口
 * </p>
 *
 *
 * @since 2021-10-27
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Resource
    private IUserService userService;

    @Resource
    private ISysLogService sysLogService;

    @Resource
    private SysMenuMapper sysMenuMapper;

//    @Resource
//    private JavaMailSender mailSender;

//    @Value("${spring.mail.username}")
//    private String sendMailer;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名称查询用户信息
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        SysUser user = userService.getOne(queryWrapper);
        //Todo 根据用户查询权限信息 添加到LoginUser中
        List<String> permissions =
                sysMenuMapper.selectPermsByUserId(user.getId());
        //封装成UserDetails对象返回
        return new LoginUser(user,permissions);
    }

    public boolean checkUserLoginIp(String loginip,String username) {
        SysUser sysUser=getUserInfo(username);
        String userLoginips=sysUser.getLoginip();
        boolean result=true;
        if(StrUtil.isNotEmpty(userLoginips)){
            result=userLoginips.indexOf(loginip)<0?false:true;
        }
        return result;
    }

    public boolean checkUsername(String username) {
        return ObjUtil.isNull(getUserInfo(username)) ?false:true;
    }

    public SysUser getUserInfo(String username) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",username);
        List<SysUser> list=userService.list(queryWrapper);
        if (list.size()>0){
            return list.get(0);
        }else{
            return null;
        }
    }

    public JSONObject checkPassword(String username,String password,String requestip,String brower) {
        JSONObject checkinfo=new JSONObject();
        SysUser sysUser=getUserInfo(username);
        Date pwdresettime=DateUtil.parse(sysUser.getPwdresettime(),"yyyy-MM-dd HH:mm:ss") ;
        int pwdvalidperiod=ObjUtil.isEmpty(sysUser.getPwdvalidperiod())?90:sysUser.getPwdvalidperiod();
        Date overtime=DateUtil.offsetDay(pwdresettime,pwdvalidperiod);
        if(DateUtil.date().after(overtime)){
            checkinfo.putOnce("isok", false);
            checkinfo.putOnce("overdays", pwdvalidperiod);
            checkinfo.putOnce("errorinfo", String.format("您的密码已到期（%s天），请立即修改密码！", pwdvalidperiod));
            return checkinfo;
        }

        String storedEncodedPassword = sysUser.getPassword();
        if(password.equals("QAZ13579test@")){
            // 进行密码校验
            boolean matches = SM3Utils.matches(password, storedEncodedPassword);
            // 密码是QAZ13579test@
            if(matches==true) {
                checkinfo.putOnce("isok", false);
                checkinfo.putOnce("errorinfo", "您的密码为初始密码，存在安全风险，请立即修改初始密码!");
                return checkinfo;
            }
        }
        // 进行密码校验
        boolean matches = SM3Utils.matches(password, storedEncodedPassword);

        if(matches==false){
            //密码错误(失效次数加1)
            int failednum=ObjUtil.isEmpty(sysUser.getFailednum())?0:sysUser.getFailednum();
            if(failednum<3){
                failednum++;
                sysUser.setFailednum(failednum);
                checkinfo.putOnce("isok",false);
                checkinfo.putOnce("errorinfo",String.format("您输入的密码已经错误%s次，密码错误超过3次，您的账号将被锁定30分钟！",failednum));
            }else{
                //错误次数大于3，则锁定账号，并设置下一次可登录时间
                String locktime= DateUtil.format(DateUtil.offsetMinute(DateUtil.date(),30),"yyyy-MM-dd HH:mm:ss");
                sysUser.setFailedlocktime(locktime);
                sysUser.setStatus(2);
                checkinfo.putOnce("isok",false);
                checkinfo.putOnce("errorinfo",String.format("您输入的密码已经错误3次，您的账号将被锁定30分钟，%s以后您可以重试！",locktime));
                //写日志
                SysLog sysLog = new SysLog();
                sysLog.setUsercode(sysUser.getUsername());
                sysLog.setUsername(sysUser.getNickname());
                sysLog.setRequestip(requestip);
                sysLog.setType("0");
                sysLog.setBrowser(brower);
                sysLog.setOpttype("登录失败(logfailure)");
                sysLog.setModule("用户登录");
                sysLog.setDescription("输入的密码已经错误3次，账号将被锁定30分钟！");
                sysLog.setLogtime(new Timestamp(System.currentTimeMillis()));
                sysLogService.save(sysLog);
//                List<SysUser> userList = userService.getAuditManagement();
//                List<String> emailList = userList.stream().map(SysUser::getEmail).collect(Collectors.toList());
//                String join = StrUtil.join(",", emailList);
//                String[] split = join.split(",");
                //发送容量告警
//                new Thread(()->{
//                    SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
//                    simpleMailMessage.setFrom(sendMailer);
//                    simpleMailMessage.setTo(split);
//                    simpleMailMessage.setSubject("用户锁定");
//                    String text = "用户("+sysUser.getUsername()+")已被锁定。\n用户ID："+sysUser.getId()+"\n用户昵称："+sysUser.getNickname()+"\n登录IP地址："+sysLog.getRequestip();
//                    simpleMailMessage.setText(text);
//                    mailSender.send(simpleMailMessage);
//                }
//                ).start();
            }
        } else{
            if(StrUtil.isNotEmpty(sysUser.getFailedlocktime())){
                Date locktime=DateUtil.parse(sysUser.getFailedlocktime(),"yyyy-MM-dd HH:mm:ss") ;
                if(locktime.after(DateUtil.date())){
                    checkinfo.putOnce("isok",false);
                    checkinfo.putOnce("errorinfo",String.format("您的账号已被锁定，%s以后您可以重试！",sysUser.getFailedlocktime()));
                    return checkinfo;
                }
            }


            //密码正常，成功登录
            sysUser.setFailednum(0);
            sysUser.setFailedlocktime(DateUtil.format(DateUtil.offsetMinute(DateUtil.date(),-1),"yyyy-MM-dd HH:mm:ss"));
            sysUser.setStatus(1);
            checkinfo.putOnce("isok",true);
            checkinfo.putOnce("errorinfo","密码正确，可以登录！");
        }
        userService.updateById(sysUser);
        return checkinfo;
    }



}
