package com.org.system.service;

import cn.hutool.core.util.ObjectUtil;
import com.org.system.config.async.AsyncFactory;
import com.org.system.config.async.AsyncManager;
import com.org.system.entity.*;
import com.org.system.entity.vo.PersonVo;
import com.org.system.pojo.LoginMenuTreeNode;
import com.org.utils.Constants;
import com.org.utils.MessageUtil;
import com.org.utils.SecurityUtil;
import com.org.utils.exception.CustomException;
import com.org.utils.exception.UserPasswordNotMatchException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/** 登录校验方法 **/
@Slf4j
@Service
public class SysLoginService {
    @Autowired
    private TokenService tokenService;
    @Resource
    private AuthenticationManager authenticationManager;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    private SysMenuService sysMenuService;

    /**
     * 登录验证
     * 
     * @param loginBody 登陆用户实体
     * @return 结果
     */
    public Map<String, String> login(LoginBody loginBody, boolean isCheckState) {

        // todo 这里加验证码
        // todo 这里加验证码
        // todo 这里加验证码

        // 用户验证
        Authentication authentication = null;
        try {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginBody.getUsername(), loginBody.getPassword()));
        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_FAIL, MessageUtil.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            } else {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_FAIL, e.getMessage()));
                throw new CustomException(e.getMessage());
            }
        }

        AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_SUCCESS, "登陆成功"));

        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        loginUser.getUser().setLoginCount(loginUser.getUser().getLoginCount() + 1);
        sysUserService.updateById(loginUser.getUser());

        // 登录时校验是否存在角色
        SysUserRole sysUserRole = sysUserRoleService.getByUserIdAndRoleCode(loginUser.getUser().getId(), loginBody.getRoleCode());
        if(ObjectUtil.isEmpty(sysUserRole)) throw new CustomException("当前用户没有该角色");

        Integer status = loginUser.getUser().getStatus();
        // 登录时是否校验账号状态
        if (isCheckState && status != 1) {
            String msg = status == 2 ?  "审核中，请稍后再试": "已停用";
            throw new CustomException("您的账号" + msg);
        }

        loginUser.setCurrentRoleCode(loginBody.getRoleCode());

        Map<String, String> result = new HashMap<>();

        // 生成token
        String token = tokenService.createToken(loginUser);
        result.put("token", token);
        return result;
    }

    /**
     * 设置登陆用户当前角色信息
     *
     */
    public void setLoginUserRole(){
        log.info("SysLoginService - setLoginUserRole roleCode:{}", SecurityUtil.getLoginUser().getCurrentRoleCode());

        // 获取当前登录账号的所有角色信息
        List<SysRole> sysRoleList = null;
        if(!SecurityUtil.getLoginUser().ifAdmin()) sysRoleList = sysUserRoleService.findRoleListByUserId(SecurityUtil.getUserId());
        else sysRoleList = sysRoleService.findAll();
        SecurityUtil.getLoginUser().setRoleList(sysRoleList);

        // 获取当前登录账号的当前角色信息
        SysRole sysRole = null;
        for (SysRole role : sysRoleList) { if(SecurityUtil.getLoginUser().getCurrentRoleCode().equals(role.getCode())) sysRole = role; }
        if(ObjectUtil.isEmpty(sysRole)) throw new CustomException("用户暂无权限，请联系管理员授权");
        SecurityUtil.getLoginUser().setCurrentRole(sysRole);


        // 获取当前登录账号当前角色的菜单
        List<SysMenu> sysMenuList = null;
        if(!SecurityUtil.getLoginUser().ifAdmin()) sysMenuList = sysRoleMenuService.findMenuListByRoleId(sysRole.getId());
        else sysMenuList = sysMenuService.findAll();
        List<LoginMenuTreeNode> loginMenuTreeNodeList = sysMenuService.convertSysMenuToLoginMenu(sysMenuList);
        SecurityUtil.getLoginUser().setMenus(loginMenuTreeNodeList);

        // 获取当前登录账号当前角色的权限
        Set<String> permissions = new HashSet<>();
        /*if(SecurityUtil.getLoginUser().ifAdmin()){
            permissions.add(PermissionService.ALL_PERMISSION);
        } else {
            for (SysMenu sysMenu : sysMenuList) { if(StringUtils.isNotEmpty(sysMenu.getPermission())) permissions.add(sysMenu.getPermission()); }
        }*/
        // todo 可登录的就能看到所有权限
        permissions.add(PermissionService.ALL_PERMISSION);
        SecurityUtil.getLoginUser().setPermissions(permissions);

        tokenService.refreshToken(SecurityUtil.getLoginUser());

    }

    public PersonVo getUserInfo(Long userId) {
        PersonVo personVo = new PersonVo();
        /*XmPerson person = xmPersonService.getByUserId(userId);
        if (person == null) throw new CustomException("未查询到人员信息");
        PersonVo personVo = new PersonVo();
        BeanUtils.copyProperties(person, personVo);
        SysOrg sysOrg = sysOrgService.getById(person.getOrgId());
        if (sysOrg.getType() == 1) {
            // 如果组织为单位，则直接返回单位名称
            personVo.setUnit(sysOrg.getName());
        } else {
            // 先查询出部门信息，再查询所属单位
            SysOrg parentOrg = sysOrgService.findUnitByOrgId(sysOrg.getPid());
            personVo.setUnit(parentOrg.getName());
            personVo.setDept(sysOrg.getName());
        }
        personVo.setPersonId(person.getId());

        // 学时
        BigDecimal yearClassHour = studyRecordService.getBaseMapper().getYearSumStudyHours(person.getId());
        personVo.setYearClassHour(yearClassHour);
        BigDecimal sumClassHour = studyRecordService.getBaseMapper().getSumStudyHours(person.getId());
        personVo.setSumClassHour(sumClassHour);*/

        return personVo;
    }
}
