package com.winsun.item.modular.system.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.winsun.auth.core.base.controller.BaseController;
import com.winsun.auth.core.common.model.ResponseData;
import com.winsun.auth.core.util.DateUtil;
import com.winsun.auth.model.user.User;
import com.winsun.bean.HhrUser;
import com.winsun.bean.School;
import com.winsun.bean.SysUser;
import com.winsun.item.core.shiro.ShiroKit;
import com.winsun.item.core.util.ResponseEntity;
import com.winsun.item.modular.system.service.IUserService;
import com.winsun.item.util.LoginUtils;
import com.winsun.mapper.HhrUserMapper;
import com.winsun.mapper.SchoolMapper;
import com.winsun.mapper.SysUserMapper;
import com.winsun.smsUtils.SendSmsAndMail;
import com.winsun.utils.HttpHelper;
import com.winsun.utils.IDCardUtil;
import com.winsun.utils.MyBatisPlusUpdateUtils;
import com.winsun.utils.PicturesUtil;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author: chancy
 * @Date: 2020/3/27 16:14
 */
@Slf4j
@RequestMapping("/forgerpw")
@RestController
public class LoginPwdController extends BaseController {

    private static SysUserMapper sysUserMapper;

    private static IUserService userService;

    private static StringRedisTemplate stringRedisTemplate;

    private static HhrUserMapper hhrUserMapper;

    private static SchoolMapper schoolMapper;

    private static String PATHTYPE="idCard";

    private static String CODE = "verificationCode";

    private static String ERRCODENAME = "ForgeERRCODENAME";

    private static long CODETIME = 1000 * 60 * 5;

    private static int ERRACCOUNT = 10;

    private static String APPID = "wxfc18f5186b729d15";
    private static String APPSECRET = "122278f3fb555468848ff040620505ad";
    //登录验证码标识
    private static String GETPHONECODE = "getPhoneCode";



    @Autowired
    public LoginPwdController(SysUserMapper sysUserMapper, IUserService userService, StringRedisTemplate stringRedisTemplate,
                              HhrUserMapper hhrUserMapper,SchoolMapper schoolMapper) {
        LoginPwdController.sysUserMapper = sysUserMapper;
        LoginPwdController.userService = userService;
        LoginPwdController.hhrUserMapper = hhrUserMapper;
        LoginPwdController.stringRedisTemplate = stringRedisTemplate;
        LoginPwdController.schoolMapper=schoolMapper;
    }

    @RequestMapping(value = "/defaultLogin")
    public ResponseData<Map<String, Object>> defaultLogin(String code) throws Exception {
        if (StringUtils.isBlank(code)) {
            return ResponseData.error("微信默认授权失效，请退出重新进入授权！");
        }
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?";
        url += "appid=";
        url += APPID;
        url += "&secret=";
        url += APPSECRET;
        url += "&code=" + code + "&grant_type=authorization_code";
        String jsonObject = null;
        try {
            jsonObject = HttpHelper.sendGet(url);
        } catch (Exception e) {
            log.error("微信登录获取用户信息失败"+ e.getMessage(),e);
            return ResponseData.error("微信默认授权失效，请退出重新进入授权！");
        }
        if (StringUtils.isBlank(jsonObject)) {
            return ResponseData.error("微信默认授权失效，请退出重新进入授权！");
        }
        if(!jsonObject.contains("openid")){
            return ResponseData.error("微信默认授权失效，请退出重新进入授权！");
        }
         /*jsonObject = HttpHelper.doGet(url);*/
        Map<String, Object> hashMap = new HashMap<>();
        log.info(jsonObject);
      /*  Map<String,Object> map = JSON.toJavaObject(jsonObject,Map.class);*/
        Map<String,Object> map = JSON.parseObject(jsonObject, Map.class);
        String openId = map.get("openid").toString();
        Wrapper<HhrUser> wrapper = new EntityWrapper<>();
        wrapper.eq("open_id", openId);
        log.info("openId:"+openId);
        List<HhrUser> hhrUsers = hhrUserMapper.selectList(wrapper);
        if (hhrUsers.size() == 0) {
            hashMap.put("info",JSONObject.parseObject(jsonObject));
            return ResponseData.error(hashMap,"当前微信未绑定账号，请先登录绑定账号！");
        }
        HhrUser hhrUser = hhrUsers.get(0);
        SysUser sysUser = sysUserMapper.selectById(hhrUser.getId());
        if (StringUtils.isBlank(sysUser.getAccount())) {
            hashMap.put("info",JSONObject.parseObject(jsonObject));
            return ResponseData.error(hashMap,"当前账号异常！");
        }

        hashMap.put("username", sysUser.getAccount());
        hashMap.put("openId", openId);
        return ResponseData.success(hashMap);
    }


    /**
     * 微信登录
     *
     * @param openid
     * @return
     */
    @RequestMapping(value = "/weixinLogin")
    public ResponseData<Map<String, Object>> weixinLogin(String openid) {
        if (StringUtils.isBlank(openid)) {
            return ResponseData.error("微信授权失效，请重新授权！");
        }
        Wrapper<HhrUser> wrapper = new EntityWrapper<>();
        wrapper.eq("open_id", openid);
        log.info("openId:"+openid);
        List<HhrUser> hhrUsers = hhrUserMapper.selectList(wrapper);
        if (hhrUsers.size() == 0) {
            return ResponseData.error("当前微信未绑定账号，请先绑定账号！");
        }
        HhrUser hhrUser = hhrUsers.get(0);
        SysUser sysUser = sysUserMapper.selectById(hhrUser.getId());
        if (StringUtils.isBlank(sysUser.getAccount())) {
            return ResponseData.error("当前账号异常！");
        }
        Map<String, Object> hashMap = new HashMap<>();
        hashMap.put("username", sysUser.getAccount());
        hashMap.put("openId", openid);
        return ResponseData.success(hashMap);
    }

    /**
     * 微信解绑
     *
     * @param openid
     * @param username
     * @param verificationCode
     * @return
     */
    @RequestMapping(value = "/weixinUnbundling")
    public ResponseData<String> weixinUnbundling(String openid, String username, String verificationCode) {
        if (StringUtils.isBlank(openid) || StringUtils.isBlank(username) || StringUtils.isBlank(verificationCode)) {
            return ResponseData.error("解绑失败,微信授权失效或账号验证码为空！");
        }
        String str = stringRedisTemplate.opsForValue().get(username + GETPHONECODE);
        if (StringUtils.isBlank(str)) {
            return ResponseData.error("验证码已失效！");
        }
        if (!str.equals(verificationCode)) {
            return ResponseData.error("验证码错误！");
        }
        Wrapper<SysUser> wrapperU = new EntityWrapper<>();
        wrapperU.eq("account", username);
        List<SysUser> users = sysUserMapper.selectList(wrapperU);
        if (users.size() == 0) {
            return ResponseData.error("当前账号不存在！");
        }
        log.info("openId:"+openid);
        SysUser sysUser = users.get(0);
        Wrapper<HhrUser> wrapper = new EntityWrapper<>();
        wrapper.eq("id", sysUser.getId());
        wrapper.eq("open_id", openid);
        List<HhrUser> hhrUsers = hhrUserMapper.selectList(wrapper);
        if (hhrUsers.size() == 0) {
            return ResponseData.error("当前微信和当前账号不匹配！");
        }
        Map<String, Object> dataMapping = new HashMap<>();
        dataMapping.put("open_id", null);
        Integer integer = hhrUserMapper.updateForSet(MyBatisPlusUpdateUtils.toUpdateSet(dataMapping), wrapper);
        if (integer == 1) {
            return ResponseData.success("解绑成功！");
        }
        return ResponseData.error("绑定失败！");
    }

    /**
     * 绑定微信
     *
     * @param accessToken
     * @param username
     * @return
     */
    @RequestMapping("bindingAccount")
    public ResponseData<String> bindingAccount(String openid,String accessToken, String username, String verificationCode) {
        log.info(accessToken+":"+openid+":"+":"+username+":"+verificationCode);
        if (StringUtils.isBlank(accessToken) || StringUtils.isBlank(openid) || StringUtils.isBlank(username) || StringUtils.isBlank(verificationCode)) {
            return ResponseData.error("绑定失败，授权失效或账号验证码为空！");
        }
        String str = stringRedisTemplate.opsForValue().get(username + GETPHONECODE);
        if (StringUtils.isBlank(str)) {
            return ResponseData.error("验证码已失效！");
        }
        if (!str.equals(verificationCode)) {
            return ResponseData.error("验证码错误！");
        }
        Wrapper<SysUser> wrapperU = new EntityWrapper<>();
        wrapperU.eq("account", username);
        List<SysUser> users = sysUserMapper.selectList(wrapperU);
        if (users.size() == 0) {
            return ResponseData.error("当前账号有误！");
        }
        log.info("openId:"+openid);
        String url1 = "https://api.weixin.qq.com/sns/userinfo?access_token="+accessToken+"&openid="+openid+"&lang=zh_CN";
        String jsonObject1 = null;
        try {
            jsonObject1 = HttpHelper.sendGet(url1);
        } catch (Exception e) {
            log.error("微信登录获取用户信息失败"+ e.getMessage(),e);
        }
        if (StringUtils.isBlank(jsonObject1)) {
            return ResponseData.error("微信授权失效，请重新授权！");
        }
        if(!jsonObject1.contains("openid")){
            return ResponseData.error("微信授权失效，请重新授权！");
        }
        log.info(jsonObject1);
        Map<String,Object> map1 = JSON.parseObject(jsonObject1, Map.class);
        String headimgurl = map1.get("headimgurl").toString();
        String nickname = map1.get("nickname").toString();
        SysUser sysUser = users.get(0);
        Wrapper wrapper = new EntityWrapper<>();
        wrapper.eq("id", sysUser.getId());
        Map<String, Object> dataMapping = new HashMap<>();
        dataMapping.put("open_id", openid);
        dataMapping.put("wx_head_img_url",headimgurl);
        dataMapping.put("wx_nick_name",nickname);
        Integer integer = hhrUserMapper.updateForSet(MyBatisPlusUpdateUtils.toUpdateSet(dataMapping), wrapper);
        if (integer == 1) {
            return ResponseData.success(openid);
        }
        return ResponseData.error("绑定失败！");
    }

    /**
     * 忘记密码发送验证码
     *
     * @param username
     * @param
     * @return
     */
    @RequestMapping(value = "verificationCode", method = RequestMethod.POST)
    public Object phoneLoginCode(@RequestParam("username") String username) {
        EntityWrapper<User> userwrapper = new EntityWrapper<>();
        userwrapper.eq("account", username);
        List<User> users = userService.selectList(userwrapper);
        if (CollectionUtils.isEmpty(users)) {
            return ResponseEntity.newJSON("code", 400, "message", "密码或者账号错误！");
        }
        User user = users.get(0);
        //5分钟内有效
        String code = username + CODE;
        String verificationCode = null;
        if (username.equals("admin")) {
            //只有admin验证码有后门 验证码规则：当前月份日期小时例如 011415
            verificationCode = DateUtil.formatDate(new Date(), "MMddHH");
        } else {
            verificationCode = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        }

        Long expire = stringRedisTemplate.getExpire(code);
        //验证码 有效时间是五分钟倒计时
        if (expire > (60 * 4)) {
            return ResponseEntity.newJSON("code", 400, "message", "请勿频繁发送手机验证码操作！");
        }
        stringRedisTemplate.opsForValue().set(code, verificationCode, CODETIME, TimeUnit.MILLISECONDS);
        Map<String, Object> sent = new HashMap<>();
        sent.put("code", 400);
        try {
            if (username.equals("admin")) {
                sent.put("message", "发送成功");
                sent.put("code", 200);
            } else {
                if (user.getPhone().length() == 11) {
                    SendSmsAndMail.sendSms(user.getPhone(), verificationCode, "7");
                    sent.put("message", "发送成功");
                    sent.put("code", 200);
                } else {
                    sent.put("message", "当前用户手机号码不合法！");
                }
            }
        } catch (Exception e) {
            log.info("错误信息：{}"+ e.getMessage(),e);
            sent.put("message", "手机短信发送失败");
        }

        return sent;
    }

    /**
     * 忘记密码
     *
     * @param account
     * @param newPwd
     * @param rePwd
     * @param
     * @return
     */
    @RequestMapping(value = "changePwd", method = RequestMethod.POST)
    @ResponseBody
    public Object ChangePassword(@RequestParam(value = "account") String account, @RequestParam(value = "verificationCode") String verificationCode,
                                 @RequestParam(value = "newPwd") String newPwd, @RequestParam(value = "rePwd") String rePwd) {
        String code = stringRedisTemplate.opsForValue().get(account + CODE);
        if (StringUtils.isBlank(code)) {
            return ResponseEntity.newJSON("code", 400, "data", "验证码错误！");
        }
        String errcount = stringRedisTemplate.opsForValue().get(ERRCODENAME + account);
        if (StringUtils.isNotBlank(errcount)) {
            if (Integer.valueOf(errcount) == ERRACCOUNT) {
                Long expire = stringRedisTemplate.getExpire(account + CODE);
                if (expire > (60 * 4)) {
                    return ResponseEntity.newJSON("code", 500, "data", "频繁操作");
                } else {
                    stringRedisTemplate.delete(account + CODE);
                    stringRedisTemplate.delete(ERRCODENAME + account);
                    return ResponseEntity.newJSON("code", 500, "data", "重新获取验证码");
                }
            }
        }
        if (!code.equals(verificationCode)) {
            if (StringUtils.isBlank(errcount)) {
                errcount = "1";
                stringRedisTemplate.opsForValue().set(ERRCODENAME + account, errcount);
            } else if (Integer.valueOf(errcount) < ERRACCOUNT) {
                errcount = String.valueOf(Integer.valueOf(errcount) + 1);
                stringRedisTemplate.opsForValue().set(ERRCODENAME + account, errcount);
            }
            return ResponseEntity.newJSON("code", 300, "data", "手机验证码第" + errcount + "次不正确");
        } else if (StringUtils.isNotBlank(errcount)) {
            stringRedisTemplate.delete(ERRCODENAME + account);
        }
        // 对加密的密码进行解密处理
        ResponseData<String> pwdDecrypt = LoginUtils.pwdDecrypt(newPwd);
        if (!pwdDecrypt.isSuccess()) {
            return ResponseEntity.newJSON("code", 400, "data", "密码或者账号错误！");
        }
        newPwd = pwdDecrypt.getData();
        String pattern = "^(?![A-Za-z]+$)(?![A-Z\\d]+$)(?![A-Z\\W]+$)(?![a-z\\d]+$)(?![a-z\\W]+$)(?![\\d\\W]+$)\\S{8,}$";
        if (!newPwd.matches(pattern)) {
            return ResponseEntity.newJSON("code", 400, "data", "密码强制等级低，必须要数字、小写英文字母、大写英文字母或特殊字符混合组成，长度至少8位！");
        }
        if (newPwd.contains(account)) {
            return ResponseEntity.newJSON("code", 400, "data", "新密码与账号信息吻合，禁止使用！");
        }
        ResponseData<String> pwdDecryptre = LoginUtils.pwdDecrypt(rePwd);
        if (!pwdDecryptre.isSuccess()) {
            return ResponseEntity.newJSON("code", 400, "data", "密码或者账号错误！");
        }
        rePwd = pwdDecryptre.getData();
        if (!newPwd.equals(rePwd)) {
            return ResponseEntity.newJSON("code", 400, "data", "两次密码不一致！");
        }
        Wrapper<SysUser> wrapper = new EntityWrapper<>();
        wrapper.eq("account", account).eq("status", "1");
        List<SysUser> sysUsers = sysUserMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(sysUsers)) {
            return ResponseEntity.newJSON("code", 400, "data", "账号不存在,请重新输入！");
        }
        SysUser sysUser = sysUsers.get(0);
        String[] split = null;
        if (StringUtils.isNotBlank(sysUser.getOldPassward())) {
            split = sysUser.getOldPassward().split(",");
        } else {
            String oldMd5 = sysUser.getPassword();
            split = new String[]{oldMd5};
        }
        String newMd5 = ShiroKit.md5(newPwd, sysUser.getSalt());
        for (String pwd : split) {
            if (newMd5.equals(pwd)) {
                return ResponseEntity.newJSON("code", 400, "data", "新密码不得与最近两次密码相同！");
            }
        }
        Map<String, Object> dataMapping = new HashMap<>();
        dataMapping.put("password", newMd5);
        dataMapping.put("updateTime", new Date());
        if (split.length == 2) {
            dataMapping.put("old_passward", split[1] + "," + newMd5);
        } else {
            dataMapping.put("old_passward", split[0] + "," + newMd5);
        }
        Integer integer = sysUserMapper.updateForSet(com.winsun.auth.core.util.MyBatisPlusUpdateUtils.toUpdateSet(dataMapping), wrapper);
        if (integer > 0) {
            return ResponseEntity.newJSON("code", 200, "data", "修改成功！");
        }
        return ResponseEntity.newJSON("code", 300, "data", "修改失败！");
    }

    @RequestMapping(value = "selectAddress", method = RequestMethod.POST)
    public ResponseData<List<String>> selectAddress(){
        return ResponseData.success(schoolMapper.selectAdress());
    }

    @RequestMapping(value = "selectSchool", method = RequestMethod.POST)
    public ResponseData<List<Map<String, Object>>> selectSchool(String subName){
        Wrapper<School> wrapper = new EntityWrapper<>();
        wrapper.eq("sub_name",subName);
        wrapper.setSqlSelect("id","school_name");
        List<Map<String, Object>> list = schoolMapper.selectMaps(wrapper);
        return ResponseData.success(list);
    }
    @RequestMapping(value = "registeredAccount", method = RequestMethod.POST)
    public ResponseData<String> registeredAccount(@RequestParam("gender") String gender,@RequestParam("username") String username, @RequestParam("phone") String  phone,
                                                  @RequestParam("idCard") String idCard, @RequestParam(value = "stuCard") String stuCard, @RequestParam("idcardZ") String idcardZ,
                                                  @RequestParam("password") String password, @RequestParam("cpassword") String cpassword, @RequestParam("school") String school,
                                                  @RequestParam(value = "classZ") String classZ, @RequestParam("substName") String substName, @RequestParam("account") String account) throws NoSuchAlgorithmException, NoSuchAlgorithmException {
       if(StringUtils.isBlank(gender)){
          return ResponseData.error("性别不能为空！");
       }
        if(StringUtils.isBlank(username)){
            return ResponseData.error("姓名不能为空！");
        }
        if(StringUtils.isBlank(phone)){
            return ResponseData.error("电话不能为空！");
        }
        if(phone.length() != 11){
            return ResponseData.error("手机号码有误！");
        }
        if(StringUtils.isBlank(idCard)){
            return ResponseData.error("身份证号码不能为空！");
        }
        if(!IDCardUtil.IDCardValidate(idCard)){
            return ResponseData.error("身份证号码有误！");
        }
        if(StringUtils.isBlank(stuCard)){
            return ResponseData.error("请上传学生证！");
        }
        if(StringUtils.isBlank(idcardZ)){
            return ResponseData.error("请上传身份证！");
        }
        if(StringUtils.isBlank(password)){
            return ResponseData.error("密码不能为空！");
        }
        if(StringUtils.isBlank(cpassword)){
            return ResponseData.error("原密码不能为空！");
        }
        if(StringUtils.isBlank(school)){
            return ResponseData.error("学校不能为空！");
        }
        if(StringUtils.isBlank(substName)){
            return ResponseData.error("县分不能为空！");
        }
        if(StringUtils.isBlank(classZ)){
            return ResponseData.error("年级不能为空！");
        }
        if(StringUtils.isBlank(account)){
            return ResponseData.error("账号不能为空！");
        }
        String pattern = "^(?![A-Za-z]+$)(?![A-Z\\d]+$)(?![A-Z\\W]+$)(?![a-z\\d]+$)(?![a-z\\W]+$)(?![\\d\\W]+$)\\S{8,}$";
        if (!password.matches(pattern)) {
            return ResponseData.error( "密码强制等级低，必须要数字、小写英文字母、大写英文字母或特殊字符混合组成，长度至少8位！");
        }
        if (password.contains(account)) {
            return  ResponseData.error("密码与账号信息吻合，禁止使用！");
        }
        // 对加密的密码进行解密处理
        /*ResponseData<String> pwdDecrypt = LoginUtils.pwdDecrypt(password);
        if (!pwdDecrypt.isSuccess()) {
            return  ResponseData.error("密码错误！");
        }
        password = pwdDecrypt.getData();
        ResponseData<String> pwdDecryptc = LoginUtils.pwdDecrypt(cpassword);
        if (!pwdDecryptc.isSuccess()) {
            return  ResponseData.error("密码错误！");
        }
        cpassword = pwdDecryptc.getData();*/
        if(!password.equals(cpassword)){
            return ResponseData.error("密码和原密码不同！");
        }
        Wrapper<SysUser> wrapper = new EntityWrapper<>();
        wrapper.eq("account",account);
        List<SysUser> users = sysUserMapper.selectList(wrapper);
        if(users.size() != 0){
            return ResponseData.error("账号已被使用，请换一个账号！");
        }

        Wrapper<HhrUser> wrapper1 = new EntityWrapper<>();
        wrapper1.eq("id_card",account);
        List<HhrUser> hhrUsers = hhrUserMapper.selectList(wrapper1);
        if(hhrUsers.size() != 0){
            return ResponseData.error("一个身份证只能创建一个账号，请换一个身份证！");
        }

        int insert = 0;
        SysUser sysUser = new SysUser();
        sysUser.setSex(gender);
        sysUser.setAccount(account);
        sysUser.setName(username);
        sysUser.setPhone(phone);
        sysUser.setSalt(ShiroKit.getRandomSalt(5));
        sysUser.setSubstName(substName);
        sysUser.setCreatetime(new Date());
        sysUser.setStatus("2");
        sysUser.setPassword(ShiroKit.md5(password, sysUser.getSalt()));
        sysUser.setOldPassward(ShiroKit.md5(password, sysUser.getSalt()));
        insert += sysUserMapper.insert(sysUser);
        insert += sysUserMapper.insertUserSchool(sysUser.getId(), school);
        HhrUser hhrUser = new HhrUser();
        hhrUser.setId(sysUser.getId());
        hhrUser.setIdCard(idCard);
        hhrUser.setIdcardImgUrl(PicturesUtil.uploadPictures(idcardZ, sysUser.getId(),PATHTYPE));
        hhrUser.setStudentImgUrl(PicturesUtil.uploadPictures(stuCard, sysUser.getId(),PATHTYPE));
        hhrUser.setGrade(classZ);
        hhrUser.setUploadState(1);
        insert += hhrUserMapper.insert(hhrUser);
        if (insert == 3){
            return ResponseData.success("账号创建成功，待管理员审核！");
        }
        if (insert == 0){
            return ResponseData.error("账号创建失败！");
        }
        return ResponseData.error("账号创建异常，请联系管理员！");
    }

}
