package com.hfkj.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.hfkj.common.exception.ErrorCode;
import com.hfkj.common.exception.ErrorHelp;
import com.hfkj.common.exception.SysCode;
import com.hfkj.common.security.AESEncodeUtil;
import com.hfkj.common.security.SessionObject;
import com.hfkj.common.security.UserCenter;
import com.hfkj.common.utils.MD5Util;
import com.hfkj.common.utils.RequestUtils;
import com.hfkj.dao.SecUserMapper;
import com.hfkj.entity.*;
import com.hfkj.model.MenuTreeModel;
import com.hfkj.model.SecUserSessionObject;
import com.hfkj.service.SecMenuService;
import com.hfkj.service.SecRoleService;
import com.hfkj.service.SecUserLoginLogService;
import com.hfkj.service.SecUserService;
import com.hfkj.sysenum.SecMenuTypeEnum;
import com.hfkj.sysenum.SecUserLoginLogStatusEnum;
import com.hfkj.sysenum.SecUserObjectTypeEnum;
import com.hfkj.sysenum.SecUserStatusEnum;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @className: SecUserServiceImpl
 * @author: HuRui
 * @date: 2024/3/26
 **/
@Service("secUserService")
public class SecUserServiceImpl implements SecUserService {

    @Resource
    private SecUserMapper secUserMapper;
    @Resource
    private UserCenter userCenter;
    @Resource
    private SecUserLoginLogService secUserLoginLogService;
    @Resource
    private SecRoleService secRoleService;
    @Resource
    private SecMenuService secMenuService;

    @Override
    public void editUser(SecUser data) {
        data.setUpdateTime(new Date());
        if (data.getId() == null) {
            data.setCreateTime(new Date());
            secUserMapper.insert(data);
        } else {
            secUserMapper.updateByPrimaryKey(data);
        }
    }

    @Override
    public void resetPwd(Long userId) throws Exception {
        // 查询账户
        SecUser secUser = getDetail(userId);
        if (secUser == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的账户");
        }
        secUser.setPassword(MD5Util.encode("123456".getBytes()));
        editUser(secUser);
    }

    @Override
    public SecUser getDetail(Long id) {
        return secUserMapper.selectByPrimaryKey(id);
    }

    @Override
    public SecUser getDetail(SecUserObjectTypeEnum objectType, Long objectId) {
        SecUserExample example = new SecUserExample();
        example.createCriteria()
                .andObjectTypeEqualTo(objectType.getCode())
                .andObjectIdEqualTo(objectId)
                .andStatusNotEqualTo(SecUserStatusEnum.status0.getCode());
        List<SecUser> list = secUserMapper.selectByExample(example);
        if (!list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public SecUser getDetailByLoginName(String loginName) {
        SecUserExample example = new SecUserExample();
        example.createCriteria().andLoginNameEqualTo(loginName).andStatusNotEqualTo(SecUserStatusEnum.status0.getCode());
        List<SecUser> list = secUserMapper.selectByExample(example);
        if (!list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public List<SecUser> getList(Map<String, Object> param) {
        SecUserExample example = new SecUserExample();
        SecUserExample.Criteria criteria = example.createCriteria().andStatusNotEqualTo(SecUserStatusEnum.status0.getCode());

        if (StringUtils.isNotBlank(MapUtils.getString(param, "userName"))) {
            criteria.andUserNameLike("%"+MapUtils.getString(param, "userName")+"%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "loginName"))) {
            criteria.andLoginNameLike("%"+MapUtils.getString(param, "loginName")+"%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "telephone"))) {
            criteria.andTelephoneLike("%"+MapUtils.getString(param, "telephone")+"%");
        }

        if (MapUtils.getInteger(param, "objectType") != null) {
            criteria.andObjectTypeEqualTo(MapUtils.getInteger(param, "objectType"));
        }

        if (MapUtils.getInteger(param, "status") != null) {
            criteria.andStatusEqualTo(MapUtils.getInteger(param, "status"));
        }

        example.setOrderByClause("create_time desc");
        List<SecUser> list = secUserMapper.selectByExample(example);
        for (SecUser user : list) {
            user.setPassword(null);
        }
        return list;
    }

    @Override
    public SessionObject login(String loginName, String password) throws Exception {
        // 查询用户
        SecUser user = getDetailByLoginName(loginName);
        if (user == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "登录账户不存在");
        }
        if (!user.getStatus().equals(SecUserStatusEnum.status1.getCode())) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "登录失败！当前账户已被禁用");
        }
        if (!user.getPassword().equals(MD5Util.encode(password.getBytes()))) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "登录密码错误");
        }
        user.setPassword(null);

        // 查询账户角色
        SecRole role = secRoleService.getDetail(user.getRoleId());
        if (role == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "登录账户角色不存在，请联系管理员进行分配");
        }
        // 角色菜单
        List<MenuTreeModel> menuTree = secMenuService.queryMenuTree(role.getId());
        // 角色按钮
        List<SecMenu> button = secMenuService.queryRoleMenu(role.getId(), SecMenuTypeEnum.type2);

        // token 生成格式：账户id + 时间戳
        String token = AESEncodeUtil.aesEncrypt(user.getId()+"_"+System.currentTimeMillis(), "O8gTZ6wIovDPjhsaz0zAoqZmm3jtjIcO");

        SessionObject sessionObject = new SessionObject(token, new SecUserSessionObject(user, role, menuTree, button));
        userCenter.save(sessionObject);

        // 异步记录登录信息
        secUserLoginLogService.asyncCreateLog(user, (HttpServletRequest) RequestContextHolder.getRequestAttributes().resolveReference(RequestAttributes.REFERENCE_REQUEST));

        return sessionObject;
    }


}
