package cn.palmte.work.service;

import cn.palmte.work.model.*;
import cn.palmte.work.pojo.LoginResponse;
import cn.palmte.work.pojo.Menu;
import cn.palmte.work.shiro.ShiroUtils;
import cn.palmte.work.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author: zhangming
 * @date: 2019/9/18 0018
 */
@Service
public class AdminService {
    private static final Pattern PSW_PATTERN = Pattern.compile("^[\\@A-Za-z0-9\\!\\#\\$\\%\\^\\&\\*\\.\\~]{8,20}$");

    @Autowired
    public AdminRepositoryCustom adminRepositoryCustom;
    @Autowired
    public AdminRepositoryImpl adminRepositoryImpl;
    @Autowired
    public AdminRepository adminRepository;
    @Autowired
    public SysPermissionRepository sysPermissionRepository;

    public Admin getAdminByUsername(String userName) {
        List<Admin> admins = adminRepository.getAdminByUsernameListNoEnabled(userName);
        if (admins != null && !admins.isEmpty()) {
            Admin admin = admins.get(0);
            //查询角色ID和TYPE
            Admin adminRoleInfo = adminRepositoryImpl.findAdminByUserName(userName);
            admin.setRoleType(adminRoleInfo.getRoleType());
            admin.setRoleId(adminRoleInfo.getRoleId());
            admin.setRoleLevel(adminRoleInfo.getRoleLevel());
            return admin;
        }
        return null;
    }

    public List<String> getAuthoritiesName(String adminId) {
        return adminRepositoryCustom.getAuthoritiesName(adminId);
    }

    public List<String> getAuthoritieUrls(String adminId) {
        return adminRepositoryCustom.getAuthoritieUrls(adminId);
    }

    public List<SysPermission> getAuthoritieUrlsByParentPermission(String adminId, String permission) {
        return adminRepositoryCustom.getAuthoritieUrlsByParentPermission(adminId, permission);
    }

    public List<String> getRolesName(String adminId) {
        return adminRepositoryCustom.getRolesName(adminId);
    }

    public LoginResponse initMenuList(int uId) {
        LoginResponse loginResponse = new LoginResponse();

        List<Menu> topMenuList = getMenuByLevelID(2);

        loginResponse.setTopMenuList(topMenuList);

        List<Menu> menuList = new ArrayList<>();
        if (uId > 0) {
            menuList = getMenuByParentId(uId);
        } else {
            if (null != topMenuList && topMenuList.size() > 0) {
                Integer topMenuId = topMenuList.get(0).getId();
                menuList = getMenuByParentId(topMenuId);
            }
        }
        loginResponse.setSideBarList(menuList);

        return loginResponse;
    }

    public List<Menu> getMenuByLevelID(int levelId) {
        List<SysPermission> list = sysPermissionRepository.findSysPermissionByLevel(levelId);
        List<Menu> nodeList = new ArrayList<>();
        for (SysPermission sysPermission : list) {
            //TODO:需补充shiro权限相关逻辑
            if (ShiroUtils.hasPermission(sysPermission.getPermission())) {
                // remark字段，用于返回前端TOP菜单css样式的class ID
                String url[] = sysPermission.getUrl().split("/");
                sysPermission.setRemark(url[url.length - 1]);
                Menu menu = new Menu();
                menu.setId(sysPermission.getId());
                menu.setName(sysPermission.getName());
                menu.setIcon(sysPermission.getIcon());
                menu.setRemark(sysPermission.getRemark());
                menu.setUrl(sysPermission.getUrl());
                menu.setIcon(sysPermission.getIcon());
                menu.setParentId(sysPermission.getParentId());
                menu.setPermossion(sysPermission.getPermission());
                nodeList.add(menu);
            }
        }
        return nodeList;
    }

    public List<Menu> getMenuByParentId(int parentId) {
        List<Menu> nodeList = new ArrayList<>();
        List<Menu> returnList = new ArrayList<>();
        List<SysPermission> list = sysPermissionRepository.findSysPermissionByParentId(parentId);
        list.forEach(sysPermission -> {
            Menu menu = new Menu();
            menu.setId(sysPermission.getId());
            menu.setName(sysPermission.getName());
            menu.setIcon(sysPermission.getIcon());
            menu.setRemark(sysPermission.getRemark());
            menu.setUrl(sysPermission.getUrl());
            menu.setIcon(sysPermission.getIcon());
            menu.setParentId(sysPermission.getParentId());
            menu.setPermossion(sysPermission.getPermission());
            nodeList.add(menu);
        });


        for (Menu node1 : nodeList) {
            boolean mark = false;
            for (Menu node2 : nodeList) {
                if (node1.getParentId() > 0L && node1.getParentId() == node2.getId()) {
                    mark = true;
                    if (node2.getChildren() == null) {
                        node2.setChildren(new ArrayList<Menu>());
                    }
                    //TODO:需补充shiro权限相关逻辑
                    if (ShiroUtils.hasPermission(node1.getPermossion())) {
                        node2.getChildren().add(node1);
                    }
                    break;
                }
            }
            //TODO:需补充shiro权限相关逻辑
            if (!mark && ShiroUtils.hasPermission(node1.getPermossion())) {
                returnList.add(node1);
            }
        }

        return returnList;
    }

    /**
     * 更新登录信息
     */
    public void updateLoginInfo(Admin admin, HttpServletRequest request) {
        admin.setLoginDate(new Date());
        admin.setLoginIp(request.getRemoteAddr());
        admin.setLoginErrorCount(0);
        admin.setLocked(Admin.UN_LOCKED);
        admin.setLockedDate(null);
        adminRepository.save(admin);
    }

    public SysRole getRole(String adminId) {
        return adminRepositoryCustom.getRole(adminId);
    }

    /**
     * 通过id查询admin
     */
    public Admin getAdminById(int id) {
        return adminRepository.getAdminById(id);
    }

    public void updatePassword(String id, String password, String newPassword, String privateKey) {
        int adminId = InterfaceUtil.getAdminId();
        if(adminId != Integer.parseInt(id)){
            throw new RuntimeException("密码修改失败，id不合法");
        }
        Admin admin = adminRepository.findOne(Integer.valueOf(id));
        if(null == admin){
            throw new RuntimeException("密码修改失败，不存在 id = " + id + " 这个人");
        }
        String salt = admin.getSalt();

        String desOldPwd = "";
        String desNewPwd = "";
        try{
            /* RSA 解密 */
            String oldPwdByRSA = StrKit.byteToStringWithDefaultEncoding(RSAUtils.decryptByPrivateKey(Base64Utils.decode(password), privateKey));
            desOldPwd = DESCrypto.encryptPassword(oldPwdByRSA, salt);

            String newPwdByRSA = StrKit.byteToStringWithDefaultEncoding(RSAUtils.decryptByPrivateKey(Base64Utils.decode(newPassword), privateKey));
            if(!PSW_PATTERN.matcher(newPwdByRSA).matches()){// 密码不满足正则表达式
                throw new RuntimeException("密码修改失败，密码不满足规则（8-20位非中文字符）");
            }
            desNewPwd = DESCrypto.encryptPassword(newPwdByRSA, salt);
        }
        catch(Exception e){
            throw new RuntimeException("密码修改失败");
        }

        String correct = admin.getPassword();

        if(!desOldPwd.equals(correct)){
            throw new RuntimeException("密码修改失败，原密码错误");
        }
        admin.setPassword(desNewPwd);
        admin.setLastUpdatedBy(InterfaceUtil.getAdminId());
        admin.setLastUpdatedTime(new Date());
        admin.setUpdatedPasswordTime(new Date());
        adminRepository.save(admin);
    }


    public boolean isLocked(Admin admin){
        if(admin.getLocked()==Admin.UN_LOCKED){
            return false;
        }
        Date lockedDate = admin.getLockedDate();
        //15分钟之后就不算锁定了
        return System.currentTimeMillis() - lockedDate.getTime() <= 15 * 60 * 1000;
    }

    public void addLoginError(Admin admin){
        int loginErrorCount = admin.getLoginErrorCount();
        admin.setLoginErrorCount(loginErrorCount+1);
        //5次就锁定
        if(loginErrorCount >= 5-1){
            admin.setLocked(Admin.LOCKED);
            admin.setLockedDate(new Date());
        }
        adminRepository.saveAndFlush(admin);
    }
}
