package cn.palmte.work.controller.backend;


import cn.palmte.work.bean.ResponseMsg;
import cn.palmte.work.config.Constant;
import cn.palmte.work.model.*;
import cn.palmte.work.pojo.LoginRequest;
import cn.palmte.work.pojo.LoginResponse;
import cn.palmte.work.service.AdminService;
import cn.palmte.work.service.LoginLogService;
import cn.palmte.work.service.ProjectService;
import cn.palmte.work.utils.*;
import net.logstash.logback.encoder.org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import top.jfunc.common.db.bean.Page;
import top.jfunc.common.utils.CollectionUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/admin")
public class AdminController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(AdminController.class);
    @Autowired
    private AdminService adminService;
    @Autowired
    private LoginLogService loginLogService;
    @Autowired
    private SysRoleRepository sysRoleRepository;
    @Autowired
    private ProjectService projectService;

    @PostMapping(value = "/singIn")
    public String singIn(RedirectAttributes attr, LoginRequest loginRequest, HttpServletRequest request) throws Exception {
        String userName = loginRequest.getUserName();
        String password = loginRequest.getPassword();
        //String captchaToken = loginRequest.getCaptchaToken();
        String code;
        String message;
        try{
            /*try{
                code = request.getSession().getAttribute(CaptchaUtils.RANDOM_CODE_KEY).toString();
            }catch(Exception e){
                logger.info(e.getMessage() , e);
                message ="验证码错误";
                attr.addAttribute("errorMessages",message);
                return "redirect:/admin/err";
            }*/
            try {
                String privateKey = request.getSession().getAttribute(Constant.PRIVATEKEY).toString();
                userName = new String(RSAUtils.decryptByPrivateKey(Base64Utils.decode(userName), privateKey));
                password = new String(RSAUtils.decryptByPrivateKey(Base64Utils.decode(password), privateKey));
                //captchaToken = new String(RSAUtils.decryptByPrivateKey(Base64Utils.decode(captchaToken),privateKey));
            } catch (Exception e) {
                logger.error("解密出错", e);
                attr.addAttribute("errorMessages", "用户名密码错误");
                return "redirect:/admin/err";
            }
            attr.addAttribute("userName", userName);
            if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)) {
                message = "用户名或密码错误!";
                attr.addAttribute("errorMessages", message);
                return "redirect:/admin/err";
            }
            /*if(!captchaToken.toUpperCase().equals(code)){
                message ="验证码错误!";
                attr.addAttribute("errorMessages",message);
                return "redirect:/admin/err";
            }*/
            /**
             * 移除验证数据
             */
            //request.getSession().removeAttribute(CaptchaUtils.RANDOM_CODE_KEY);
            Admin admin = adminService.getAdminByUsername(userName);
            if (null == admin) {
                message = "用户名或密码错误~~~";
                attr.addAttribute("errorMessages", message);
                loginLogService.saveLog(userName, LoginLog.FAILED, message);
                return "redirect:/admin/err";
            }
            if (admin.getEnabled() == 0) {
                message = "该用户已禁用~~~";
                attr.addAttribute("errorMessages", message);
                loginLogService.saveLog(userName, LoginLog.FAILED, message);
                return "redirect:/admin/err";
            }
            if (adminService.isLocked(admin)) {
                message = "该用户已被锁定~~~";
                attr.addAttribute("errorMessages", message);
                loginLogService.saveLog(userName, LoginLog.FAILED, message);
                return "redirect:/admin/err";
            }
            int roleId = admin.getRoleId();
            SysRole role = sysRoleRepository.findOne(roleId);

            if (role.getIsEnable() == 0) {
                message = "该用户绑定的角色已禁用~~~";
                attr.addAttribute("errorMessages", message);
                loginLogService.saveLog(userName, LoginLog.FAILED, message);
                return "redirect:/admin/err";
            }

            String salt = admin.getSalt();
            request.getSession().setAttribute("realsName", admin.getRealName());
            //request.getSession().setAttribute("telephone", admin.getTelephone());
            request.getSession().setAttribute("lastLoginTime", admin.getLoginDate());
            String newPassword;
            try {
                newPassword = DESCrypto.encryptPassword(password, salt);
            } catch (Exception e) {
                logger.error("加密出错", e);
                message = "密码出错";
                attr.addAttribute("errorMessages", message);
                loginLogService.saveLog(userName, LoginLog.FAILED, message);
                return "redirect:/admin/err";
            }

            boolean bool = checkUpdatePasswordTime(admin);
            if (bool) {
                request.getSession().setAttribute("message", "您已超过90天未修改密码！");
            } else {
                request.getSession().setAttribute("message", "");
            }

            message = login(userName, newPassword, false, false);
            if (!message.isEmpty()) {
                attr.addAttribute("errorMessages", message);

                //增加登录失败次数
                adminService.addLoginError(admin);
                loginLogService.saveLog(userName, LoginLog.FAILED, message);

                return "redirect:/admin/err";
            }
            adminService.updateLoginInfo(admin, request);
            loginLogService.saveLog(userName, LoginLog.SUCCESS, "登录成功");

            /**
             * admin用户去检查,如果检查job有失败的,显示弹出框[1]
             */
            return "redirect:/admin/center?uid=0";
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            message = "登录发生未知错误，e=" + e.getMessage();
            attr.addAttribute("errorMessages", message);
            loginLogService.saveLog(userName, LoginLog.FAILED, message);
            return "redirect:/admin/err";
        } catch (Throwable t) {
            logger.error(t.getMessage(), t);
            message = "登录发生未知错误，t=" + t.getMessage();
            attr.addAttribute("errorMessages", message);
            loginLogService.saveLog(userName, LoginLog.FAILED, message);
            return "redirect:/admin/err";
        }

    }

    /**
     * 计算当前时间和最后一次修改密码的天数
     * @param admin
     * @return
     * @throws ParseException
     */
    public boolean checkUpdatePasswordTime(Admin admin) throws ParseException {
        if (null != admin.getUpdatedPasswordTime()) {
            int days = DateKit.daysBetween(admin.getUpdatedPasswordTime(), new Date());
            if (days >= 90) {
                return true;
            }
        }
        return false;
    }

    /**
     * 统一的的登录方法
     *
     * @param returnJson 是否返回json格式的数据，否就是返回登录页面
     */
    public String login(String username, String password, boolean rememberMe, boolean returnJson) {
        //TODO:登录验证逻辑（待补充）
        String errorMessage = "";
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        token.setRememberMe(rememberMe);

        try {
            subject.login(token);
        } catch (UnknownAccountException | LockedAccountException ue) {
            token.clear();
            errorMessage = ue.getMessage();
        } catch (IncorrectCredentialsException ie) {
            token.clear();
            errorMessage = "用户名或密码错误~~~";
        } catch (RuntimeException re) {
            re.printStackTrace();
            token.clear();
            errorMessage = "登录失败!";
        }
        return errorMessage;
    }

    @RequestMapping(value = "/login", method = {RequestMethod.GET})
    public String login(HttpServletRequest request) throws Exception {
        //TODO:登录页面初始化代码
        InterfaceUtil.genRSAKeyPair(request);
        return "/admin/admin_login";
    }

    @RequestMapping(value = "/center", method = RequestMethod.GET)
    public String center(@ModelAttribute("userName") String userName, @RequestParam("uid") int uid,
                         @RequestParam(value = "showJobMonitorError", defaultValue = "0") int showJobMonitorError, Map<String, Object> model) {
        logger.info("------------------------------------------重定向到首页信息查询center方法内部-----------------------用户名====" + userName);

        LoginResponse loginResponse = adminService.initMenuList(uid);
        model.put("userName", userName);
        model.put("loginResponse", loginResponse);
        if (uid == 0) {
            uid = (loginResponse.getTopMenuList() != null && loginResponse.getTopMenuList().size() > 0) ? loginResponse.getTopMenuList().get(0).getId() : 0;
        }
        model.put("uid", uid);
        model.put("showJobMonitorError", showJobMonitorError);
        logger.info("------------------------------------------跳转到admin_index-----------------------");
        return "/admin/admin_index";
    }

    @RequestMapping(value = "/topMenu", method = RequestMethod.GET)
    public String topMenu(@RequestParam("uid") int uid, Map<String, Object> model) {
        LoginResponse loginResponse = adminService.initMenuList(uid);
        model.put("loginResponse", loginResponse);
        return "/admin/admin_index";
    }

    @RequestMapping(value = "/console", method = RequestMethod.GET)
    public String console(@RequestParam("uid") int uid, Map<String, Object> model, HttpServletRequest request) {
        logger.info(uid + "");
        model.put("statistic", "");
        return "/admin/console";
    }


    @RequestMapping(value = "/err", method = RequestMethod.GET)
    public String loginErr(HttpServletRequest request, @ModelAttribute("errorMessages") String errorMessages) {
        InterfaceUtil.genRSAKeyPair(request);
        request.setAttribute("base", request.getContextPath());
        return "/admin/admin_login";
    }


    // 管理员退出
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logout(HttpServletRequest request) {
//        ShiroPrincipal principal = (ShiroPrincipal) SecurityUtils.getSubject().getPrincipal();
//        // 如果已经登录，则跳转到管理首页
//        if(principal != null){
//            SecurityUtils.getSubject().logout();
//        }
        return "redirect:/admin/login";
    }

    /**
     * 生成随机验证码图片
     */
    @RequestMapping(value = "/captcha", method = RequestMethod.GET)
    public void captcha(HttpServletRequest request, HttpServletResponse response) throws Exception {
        new CaptchaUtils().getRandCode(request, response);
    }

    /**
     * 查询自己是否有审核任务
     *
     * @return
     */
    @ResponseBody
    @RequestMapping("/approveProjectsMsg")
    public ResponseMsg approveProjectsMsg() {
        Page<Project> myApproveProjects = projectService.findMyApproveProjects(new HashMap<>(), InterfaceUtil.getAdminId(), 1, 1);
        if (myApproveProjects != null && !myApproveProjects.getList().isEmpty()) {
            return ResponseMsg.buildSuccessMsg("您有新的待审核项目，请及时确认。");
        } else {
            return ResponseMsg.buildSuccessMsg("");
        }
    }

}
