package com.reyun.service.impl;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.reyun.dic.RoleEnumType;
import com.reyun.model.*;
import com.reyun.repository.*;
import com.reyun.security.TokenManager;
import com.reyun.service.AuthService;
import com.reyun.util.*;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Transactional
public class AuthServiceImpl implements AuthService {

    protected Logger logger = LoggerFactory.getLogger(AuthServiceImpl.class);

    @Autowired
    private TokenManager tokenManager;

    @Autowired
    private DataAuthRepository dataAuthRepository;

    @Autowired
    private AccountRepository accountRepository;

    @Autowired
    MenuRepository menuRepository;

    @Autowired
    RoleAuthDetailRepository roleAuthDetailRepository;

    @Autowired
    AuthRepository authRepository;


    @Autowired
    AppRepository appRepository;

    @Autowired
    RoleAuthRepository roleAuthRepository;

    @Autowired
    UserViewColumnRepository userViewColumnRepository;

    private static final int MAX_CUSTOM_ROLE_NUM = 5;

    private static final int MAX_MANAGE_NUM = 3;

    /**
     * 获取自定义角色和渠道账号的MENU
     * created by sunhao 20170607
     */
    @Override
    public RoleAuth getMenuAthByRole(Account loginAccount, Long roleId) {
        RoleAuth roleAuth = roleAuthRepository.findOne(roleId);

        //自定义角色,渠道账号
        if (null != roleAuth && (roleAuth.getRoleCategory().equals(RoleEnumType.CUSTOM_AUTH.getKey())
                || roleAuth.getRoleCategory().equals(RoleEnumType.CUSTOM_ROLE.getKey())
                || roleAuth.getRoleCategory().equals(RoleEnumType.CHANNEL_PERSON.getKey()))) {

            List<RoleAuthDetail> roleAuthDetailList = roleAuthDetailRepository.findDetailByRole(roleId);

            roleAuth.setRoleAuthDetails(roleAuthDetailList);
        }

        return roleAuth;
    }

    @Override
    public Account getSubAccountInfo(Long subAccountId) {
        return accountRepository.findOne(subAccountId);
    }


    /**
     * 获取所有的角色
     * created by sunhao 20170607
     */
    @Override
    public List<RoleAuth> getAllCustomRoleList(Account loginAccount) {

        List<RoleAuth> roleAuthList = new ArrayList<>();

        RoleAuth roleAuth = roleAuthRepository.findOne(loginAccount.getRoleCategory());

        //母账号、管理员、子账号管理员
        if (loginAccount.getIsSuperUser() || roleAuth.getRoleCategory().equals(RoleEnumType.MANAGER.getKey())
                || roleAuth.getRoleCategory().equals(RoleEnumType.SUB_APP_MANAGER.getKey())) {

            List<Long> accountList = this.getAllSubAccountList(loginAccount);
            roleAuthList = roleAuthRepository.findAllCustomRoleList(accountList);
        }

        return roleAuthList;
    }

    /**
     * 查询子账户菜单权限信息,用于登陆
     */
    @Override
    public Account getSubAccountAuthById(Long subAccountId) {

        Account account = accountRepository.findOne(subAccountId);

        if (null != account && !account.getIsSuperUser()) {
            //角色
            RoleAuth roleAuth = roleAuthRepository.findOne(account.getRoleCategory());

            //角色为空,跳出
            if (null == roleAuth) {
                return account;
            }

            //构建菜单权限信息
            if (roleAuth.getRoleCategory().equals(RoleEnumType.SUB_APP_MANAGER.getKey())) {

                //2,子应用管理员,只有App权限
                List<Auth> authList = authRepository.findAuthByAccountId(subAccountId);
                account.setAuthStr(this.parseAuthList2Str(authList));

            } else if (roleAuth.getRoleCategory().equals(RoleEnumType.CUSTOM_AUTH.getKey())
                    || roleAuth.getRoleCategory().equals(RoleEnumType.CUSTOM_ROLE.getKey())
                    || roleAuth.getRoleCategory().equals(RoleEnumType.CHANNEL_PERSON.getKey())) {

                //3,自定义权限,4,自定义角色,5,渠道账号,菜单权限来自auth.getControlAuth()
                List<Auth> authList = authRepository.findAuthByAccountId(subAccountId);
                account.setAuthStr(this.parseAuthList2Str(authList));

            }

        }

        return account;
    }

    /**
     * 获取单个子账号信息,权限信息为全量信息
     * created bu sunhao 20170606
     */
    @Override
    public Account getSubAccountById(Account loginAccount, Long subAccountId) {

        List<Auth> authList = new ArrayList<>();

        Account account = accountRepository.findOne(subAccountId);

        if (null != account) {

            //查询角色
            RoleAuth roleAuth = roleAuthRepository.findOne(account.getRoleCategory());

            //角色为空,跳出
            if (null == roleAuth) {
                return account;
            }

            //设置母账号的角色
            Account parentAccount = accountRepository.findOne(account.getParent());
            account.setParentRole(null != parentAccount ? parentAccount.getRoleCategory() : 0L);

            //查询权限
            if (roleAuth.getRoleCategory().equals(RoleEnumType.SUB_APP_MANAGER.getKey())) {

                //2,子应用管理员
                authList = authRepository.findAuthByAccountId(subAccountId);

            } else if (roleAuth.getRoleCategory().equals(RoleEnumType.CUSTOM_AUTH.getKey())) {

                //3,自定义角色,
                authList = authRepository.findAuthByAccountId(subAccountId);
                List<DataAuth> dataAuthList = dataAuthRepository.findDataAuthByAccount(subAccountId);

                authList = this.buildAuthListWithDataAuth(authList, dataAuthList, true, false);

            } else if (roleAuth.getRoleCategory().equals(RoleEnumType.CUSTOM_ROLE.getKey())) {

                //4,选择的保存自定义角色,无需填充菜单权限
                authList = authRepository.findAuthByAccountId(subAccountId);
                List<DataAuth> dataAuthList = dataAuthRepository.findDataAuthByAccount(subAccountId);

                authList = this.buildAuthListWithDataAuth(authList, dataAuthList, false, false);

            } else if (roleAuth.getRoleCategory().equals(RoleEnumType.CHANNEL_PERSON.getKey())) {

                //5,渠道账号
                List<Long> accountList = this.getAllSubAccountList(loginAccount);
                authList = authRepository.findAuthByCreateIds(subAccountId, accountList);
                List<DataAuth> dataAuthList = dataAuthRepository.findDataAuthByAccount(subAccountId);

                authList = this.buildAuthListWithDataAuth(authList, dataAuthList, true, true);
            }

            //设置权限LIST
            account.setAuthList(authList);
        }

        return account;
    }

    /**
     * 构建AuthList,包含数据权限,参数addMenuAuth 控制是否加入menu权限
     * created by sunhao
     */
    private List<Auth> buildAuthListWithDataAuth(List<Auth> authList, List<DataAuth> dataAuthList, boolean addMenuAuth, boolean isChannelPerson) {

        //数据权限
        Map<Long, Map<Long, DataAuth>> appDataAuthMap = this.getAppChannelCampaignMap(dataAuthList);

        //APP权限
        for (Auth auth : authList) {

            if (addMenuAuth) {

                //全部的菜单权限
                Map<String, RoleAuthDetail> roleAuthDetailMap = isChannelPerson ? this.getChannelAccountRoleAuthMap() : this.getAllRoleAuthMap();

                //拥有的菜单权限
                JSONArray jsonArray = JSONArray.fromObject(auth.getControlAuth());

                //聚合权限到列表中
                for (int i = 0; i < jsonArray.size(); i++) {

                    JSONObject authObject = jsonArray.getJSONObject(i);
                    RoleAuthDetail roleAuthDetail = roleAuthDetailMap.get(authObject.getString("auth"));

                    if (null != roleAuthDetail) {

                        roleAuthDetail.setEdit(authObject.getBoolean("edit"));
                        roleAuthDetail.setView(authObject.getBoolean("view"));
                    }
                }

                auth.setRoleAuthDetailList(new ArrayList<>(roleAuthDetailMap.values()));
            }

            //设置数据权限
            Map<Long, DataAuth> channelDataAuth = appDataAuthMap.get(auth.getApp());
            auth.setDataAuth(null != channelDataAuth ? new ArrayList<>(channelDataAuth.values()) : new ArrayList<DataAuth>());
        }

        return authList;
    }

    /**
     * 获取APP-渠道-活动MAP
     */
    private Map<Long, Map<Long, DataAuth>> getAppChannelCampaignMap(List<DataAuth> dataAuthList) {

        Map<Long, Map<Long, DataAuth>> appDataAuthMap = new HashMap<>();

        if (!CollectionUtils.isEmpty(dataAuthList)) {

            for (DataAuth dataAuth : dataAuthList) {

                Long channelId = dataAuth.getChannel();
                Long campaignId = dataAuth.getCampaign();

                //是否包含此渠道
                Map<Long, DataAuth> dataAuthMap = appDataAuthMap.get(dataAuth.getApp());
                dataAuthMap = null != dataAuthMap ? dataAuthMap : new HashMap<Long, DataAuth>();

                //是否包含此推广活动
                DataAuth dataAuthTemp = dataAuthMap.get(channelId);
                dataAuthTemp = null != dataAuthTemp ? dataAuthTemp : new DataAuth();
                dataAuthTemp.setChannel(channelId);

                //写入推广活动ID
                if (dataAuth.getAllCampaign()) {

                    dataAuthTemp.setAllCampaign(true);

                } else {

                    List<Long> campaignList = dataAuthTemp.getCampaignList();
                    campaignList = null != campaignList ? campaignList : new ArrayList<Long>();

                    if (!campaignList.contains(campaignId) && 0!= campaignId) {
                        campaignList.add(campaignId);
                    }

                    dataAuthTemp.setCampaignList(campaignList);
                    dataAuthTemp.setAllCampaign(false);

                    if(dataAuth.getChannelPermit()== null){
                        if (dataAuthTemp.getChannelPermit()==null || dataAuthTemp.getChannelPermit() == false) {
                            dataAuthTemp.setChannelPermit(false);
                        }
                    }else{
                        if (dataAuthTemp.getChannelPermit()==null || dataAuthTemp.getChannelPermit() == false) {
                            dataAuthTemp.setChannelPermit(dataAuth.getChannelPermit());
                        }
                    }

                }

                //写入渠道
                dataAuthMap.put(channelId, dataAuthTemp);
                appDataAuthMap.put(dataAuth.getApp(), dataAuthMap);
            }
        }

        return appDataAuthMap;
    }

    /**
     * 获取母账号及下面所有子账号列表
     * created bu sunhao 20170606
     */
    private List<Long> getAllSubAccountList(Account loginAccount) {

        Long rootAccount;

        if (loginAccount.getIsSuperUser()) {
            rootAccount = loginAccount.getId();
        } else {
            rootAccount = this.findRootParentAccount(loginAccount.getId()).getId();
        }

        return accountRepository.findAllAccountList(rootAccount);
    }

    /**
     * 获取子账号的菜单权限。仅仅输出已授权的信息
     * created by sunhao 20170612
     */
    private String parseAuthList2Str(List<Auth> authList) {

        JSONObject resultObject = new JSONObject();

        for (Auth auth : authList) {

            JSONObject authJsonObject = new JSONObject();

            //菜单权限
            JSONArray menuAuthArray = JSONArray.fromObject(auth.getControlAuth());

            authJsonObject.put("payAuth", auth.isPayAuth());
            authJsonObject.put("retentionAuth", auth.isRetentionAuth());
            authJsonObject.put("isNatureOpen", auth.getIsNatureOpen());
            authJsonObject.put("topAuth",auth.getTopAuth());
            authJsonObject.put("roleAuthDetailList", menuAuthArray);

            resultObject.put(auth.getApp(), authJsonObject);
        }

        return resultObject.toString();
    }

    /**
     * 获取有次APP权限的所有有效的子账号和渠道账号
     *
     * @param loginAccount
     * @return
     */
    @Override
    public List<Account> getAuthorizedSubAndChannelAccount(Account loginAccount, Long appId) {

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

        return accountRepository.findAuthorizedSubAndChannelAccount(appId, simpleDateFormat.format(new Date()));
    }

    /**
     * 获取所属生效的子账号
     * created by sunhao 20170606
     */
    @Override
    public List<Account> getAllActiveSubAccount(Account loginAccount) {

        List<Account> activeSubAccountList;

        RoleAuth roleAuth = roleAuthRepository.findByRoleCategory(loginAccount.getRoleCategory());

        if (null != roleAuth && roleAuth.getRoleCategory().equals(RoleEnumType.MANAGER.getKey())) {
            //管理员,需要看到同级别的管理员
            activeSubAccountList = accountRepository.findActiveByRootExcludeSelf(loginAccount.getRootParent(), loginAccount.getId());

        } else if (null != roleAuth && roleAuth.getRoleCategory().equals(RoleEnumType.SUB_APP_MANAGER.getKey())) {
            //子应用管理员
            activeSubAccountList = accountRepository.findActiveByParent(loginAccount.getId());

        } else {
            //母账号
            activeSubAccountList = accountRepository.findActiveByRoot(loginAccount.getId());
        }

        activeSubAccountList = this.dealWithOriginalAccount(loginAccount, activeSubAccountList);

        return activeSubAccountList;
    }

    /**
     * 查询所属失效的子账号
     * created by sunhao 20170606
     */
    @Override
    public List<Account> getAllDisableSubAccount(Account loginAccount) {

        List<Account> disableSubAccountList;

        RoleAuth roleAuth = roleAuthRepository.findByRoleCategory(loginAccount.getRoleCategory());

        if (null != roleAuth && roleAuth.getRoleCategory().equals(RoleEnumType.MANAGER.getKey())) {
            //管理员,需要看到同级别的管理员
            disableSubAccountList = accountRepository.findDisableByRootExcludeSelf(loginAccount.getRootParent(), loginAccount.getId());

        } else if (null != roleAuth && roleAuth.getRoleCategory().equals(RoleEnumType.SUB_APP_MANAGER.getKey())) {
            //子应用管理员
            disableSubAccountList = accountRepository.findDisableByParent(loginAccount.getId());

        } else {
            //母账号
            disableSubAccountList = accountRepository.findDisableByRoot(loginAccount.getId());
        }

        disableSubAccountList = this.dealWithOriginalAccount(loginAccount, disableSubAccountList);

        return disableSubAccountList;
    }



    /**
     * 填充角色名字,修改人名字,检验账户是否过期,
     */
    private List<Account> dealWithOriginalAccount(Account loginAccount, List<Account> subAccountList) {

        //设置角色名字
        if (!CollectionUtils.isEmpty(subAccountList)) {

            //账号列表
            List<Long> accountIdList = Lists.transform(subAccountList, new Function<Account, Long>() {
                @Override
                public Long apply(Account account) {
                    return account.getId();
                }
            });

            //角色列表
            List<Long> roleCategoryList = Lists.transform(subAccountList, new Function<Account, Long>() {
                @Override
                public Long apply(Account account) {
                    return account.getRoleCategory();
                }
            });

            //所有角色MAP
            List<RoleAuth> roleAuthList = roleAuthRepository.findCustomRoleList(roleCategoryList);
            Map<Long, RoleAuth> roleAuthMap = Maps.uniqueIndex(roleAuthList, new Function<RoleAuth, Long>() {
                @Override
                public Long apply(RoleAuth roleAuth) {
                    return roleAuth.getId();
                }
            });

            //所有管理账户MAP
            List<Account> accountList = accountRepository.findCreateAndModifyAccount(accountIdList);
            Map<Long, Account> accountMap = Maps.uniqueIndex(accountList, new Function<Account, Long>() {
                @Override
                public Long apply(Account account) {
                    return account.getId();
                }
            });


            //当前时间
            String nowDate = DateUtil.format(new Date(), DateUtil.C_DATE_PATTON_DEFAULT);

            //设置名字
            for (Account account : subAccountList) {

                RoleAuth roleAuth = roleAuthMap.get(account.getRoleCategory());
                account.setRoleName(null != roleAuth ? roleAuth.getRoleName() : null);

                //创建和修改人
                Account modifyAccount = accountMap.get(account.getModifyAccount());
                Account createAccount = accountMap.get(account.getCreateAccount());
                account.setModifyAccountName(null != modifyAccount ? modifyAccount.getEmail() : null);
                account.setCreateAccountName(null != createAccount ? createAccount.getEmail() : null);

                //账户是否过期 true 有效,  false 过期
                account.setValid(true);

            }
        }

        return subAccountList;
    }

    /**
     * 启用子账号
     * created by sunhao 20170606
     */
    @Override
    public int enableSubAccountById(Account loginAccount, Long subAccountId) {
        return accountRepository.enableSubAccount(loginAccount.getId(), new Date(), subAccountId);
    }

    /**
     * 停用子账号
     * created by sunhao 20170606
     */
    @Override
    public int disableSubAccountById(Account loginAccount, Long subAccountId) {

        int affectNum = accountRepository.disableSubAccount(loginAccount.getId(), new Date(), subAccountId);

        if (affectNum > 0) {

            //禁用后踢出所有已经登陆的此子账号
            tokenManager.delMultiRelationshipByKey(subAccountId.toString());
        }

        return affectNum;
    }

    @Override
    public RoleAuth getRoleAuthById(Long roleId) {
        return roleAuthRepository.findOne(roleId);
    }


    /**
     * 创建子账号,渠道账号是另外的接口
     * created by sunhao 20170607
     */
    @Override
    public Account createSubAccount(Account loginAccount, Account subAccount, RoleAuth roleAuth) {

        //新建账号 account
        Account saveAccount = this.buildAccount(loginAccount, subAccount, false);
        saveAccount.setAllowBehavior(loginAccount.getAllowBehavior());
        saveAccount = accountRepository.save(saveAccount);

        //构建权限 auth
        this.saveAuthAndDataAuth(subAccount.getAuthList(), roleAuth, saveAccount, loginAccount.getId());

        //发送激活邮件
        this.sendSubAccountActivateEmail(loginAccount, saveAccount);

        return saveAccount;
    }

    /**
     * 构建数据和菜单权限
     */
    private void saveAuthAndDataAuth(List<Auth> authList, RoleAuth roleAuth, Account saveAccount, Long loginAccountId) {

        List<Auth> saveAuthList = new ArrayList<>();

        if (roleAuth.getRoleCategory().equals(RoleEnumType.SUB_APP_MANAGER.getKey())) {

            //2,子应用管理员,创建auth 无需创建data_auth ;无需control_auth字段数据
            for (Auth auth : authList) {
                //默认设置
                auth.setIsNatureOpen(true);
                auth.setRetentionAuth(true);
                auth.setTopAuth(true);
                auth.setCampaign(true);

                Auth saveAuth = this.buildAuth(auth, saveAccount, loginAccountId, null);
                saveAuthList.add(saveAuth);
            }

        }

        //保存 auth
        if (!CollectionUtils.isEmpty(saveAuthList)) {
            authRepository.save(saveAuthList);
        }

    }

    /**
     * 菜单权限转换
     */
    private JSONArray parseAuth2JsonArray(List<RoleAuthDetail> roleAuthDetailList) {

        JSONArray authArray = new JSONArray();

        if (!CollectionUtils.isEmpty(roleAuthDetailList)) {

            for (RoleAuthDetail roleAuthDetail : roleAuthDetailList) {

                JSONObject authObject = new JSONObject();
                authObject.put("auth", roleAuthDetail.getAuth());
                authObject.put("view", roleAuthDetail.getView());
                authObject.put("edit", roleAuthDetail.getEdit());
                authObject.put("sort", roleAuthDetail.getSort());
                authObject.put("parentAuth", roleAuthDetail.getParentAuth());

                authArray.add(authObject);
            }
        }

        return authArray;
    }

    /**
     * 构建Auth
     */
    private Auth buildAuth(Auth auth, Account subAccount, Long createAccount, List<RoleAuthDetail> roleAuthDetailList) {

        Auth saveAuth = new Auth();

        Date operateDate = new Date();

        saveAuth.setApp(auth.getApp());
        saveAuth.setAccount(subAccount.getId());
        saveAuth.setRoleCategory(subAccount.getRoleCategory());
        saveAuth.setControlAuth(this.parseAuth2JsonArray(roleAuthDetailList).toString());
        saveAuth.setModifyTime(operateDate);
        saveAuth.setModifyAccount(createAccount.toString());
        saveAuth.setCreateAccount(null != auth.getCreateAccount() ? auth.getCreateAccount() : createAccount);
        saveAuth.setCreateTime(null != auth.getCreateTime() ? auth.getCreateTime() : operateDate);
        saveAuth.setStatus(true);
        //付费,留存,自然量,Top指标
        saveAuth.setPayAuth(auth.isPayAuth());
        saveAuth.setIsNatureOpen(auth.getIsNatureOpen());
        saveAuth.setRetentionAuth(auth.isRetentionAuth());
        saveAuth.setTopAuth(auth.getTopAuth());

        return saveAuth;
    }

    /**
     * 构建Account
     */
    private Account buildAccount(Account loginAccount, Account subAccount, Boolean isChannelPerson) {

        Account account = new Account();

        account.setName(subAccount.getName());
        account.setCompany(loginAccount.getCompany());
        account.setCreateTime(new Date());
        account.setDelFlag(false);
        account.setCreateAccount(loginAccount.getId());
        account.setModifyAccount(loginAccount.getId());
        account.setModifyTime(new Date());
        account.setEmail(subAccount.getEmail());
        account.setIsChannelPerson(false);
        account.setIsSuperUser(false);
        account.setIsChannelPerson(isChannelPerson);
        //未激活,需要发送邮件后激活
        account.setStatus(-3);
        account.setPricelevel(loginAccount.getPricelevel());
        account.setParent(loginAccount.getId());
        //根节点账号,取登陆账号的rootParent
        account.setRootParent(loginAccount.getRootParent());
        account.setPastDate(loginAccount.getPastDate());
        account.setRoleCategory(subAccount.getRoleCategory());
        account.setRemark(subAccount.getRemark());

        return account;
    }

    /**
     * 构建数据权限data_auth
     */
    private List<DataAuth> getDataAuthByAuth(Long subAccountId, Auth auth) {

        List<DataAuth> result = new ArrayList<>();

        //渠道和活动列表
        List<DataAuth> dataAuthList = auth.getDataAuth();

        for (DataAuth dataAuthTemp : dataAuthList) {

            //校验channel和campaign
            Long channelId = dataAuthTemp.getChannel();
            List<Long> campaignList = dataAuthTemp.getCampaignList();

            //构建data_auth
            if(null != channelId){
                if (dataAuthTemp.getAllCampaign()) {
                    //按渠道授权
                    DataAuth dataAuth = this.buildDataAuth(subAccountId, auth.getApp(), channelId, null);
                    result.add(dataAuth);

                } else{
                    Boolean flag = dataAuthTemp.getChannelPermit(); //授权渠道(新加的状态标识，可单独授权渠道。和活动分开)
                    if (!CollectionUtils.isEmpty(campaignList)){
                        //按照渠道和推广活动授权
                        for (Long campaignId : campaignList) {
                            DataAuth dataAuth = this.buildDataAuth(subAccountId, auth.getApp(), channelId, campaignId);
                            dataAuth.setChannelPermit(flag);

                            result.add(dataAuth);
                        }
                    }else{
                        if(flag){//改成新版的只按渠道授权
                            DataAuth dataAuth = this.buildDataAuth(subAccountId, auth.getApp(), channelId, null);

                            dataAuth.setChannelPermit(flag);
                            dataAuth.setAllCampaign(false);//非第一种全选按渠道授权
                            result.add(dataAuth);
                        }
                    }
                }
            }
        }

        return result;
    }

    /**
     * 构建Data_Auth
     */
    private DataAuth buildDataAuth(Long accountId, Long appId, Long channelId, Long campaignId) {

        DataAuth dataAuth = new DataAuth();

        dataAuth.setAccount(accountId);
        dataAuth.setApp(appId);
        dataAuth.setChannel(channelId);
        dataAuth.setCampaign(null == campaignId ? 0L : campaignId);
        dataAuth.setModifyTime(new Date());
        dataAuth.setAllCampaign(null == campaignId);
        dataAuth.setDelFlag(false);

        return dataAuth;
    }

    /**
     * 修改子账户信息
     * create by sunhao 20170609
     */
    @Override
    public Account modifySubAccount(Account loginAccount, Account subAccount, RoleAuth roleAuth) {

        Account account = accountRepository.findOne(subAccount.getId());

        //1,删除旧权限
        List<Auth> authList = authRepository.findAuthByAccountId(subAccount.getId());
        List<DataAuth> dataAuthList = dataAuthRepository.findDataAuthByAccount(subAccount.getId());

        if (!CollectionUtils.isEmpty(authList)) {
            authRepository.delete(authList);
        }

        if (!CollectionUtils.isEmpty(authList)) {
            dataAuthRepository.delete(dataAuthList);
        }

        //2,保存新权限
        this.saveAuthAndDataAuth(subAccount.getAuthList(), roleAuth, subAccount, loginAccount.getId());

        //3,更新基本信息
        account.setName(subAccount.getName());
        account.setRoleCategory(subAccount.getRoleCategory());
        account.setRemark(subAccount.getRemark());

        account.setModifyTime(new Date());
        account.setModifyAccount(loginAccount.getId());
        accountRepository.save(account);

        //删除来源分析显示的列数据
        UserViewColumn userViewColumn = userViewColumnRepository.findByAccount(account.getId());
        if (null != userViewColumn) {
            userViewColumnRepository.delete(userViewColumn);
        }

        return account;
    }

    /**
     * 创建自定义角色
     * create by sunhao 20170607
     */
    @Override
    public RoleAuth createCustomRole(Account loginAccount, RoleAuth roleAuth) {

        RoleAuth saveRoleAuth = new RoleAuth();

        //创建并保存 ROLE_AUTH
        saveRoleAuth.setCreateAccount(loginAccount.getId());
        saveRoleAuth.setRoleName(roleAuth.getRoleName());
        saveRoleAuth.setCreateTime(new Date());
        saveRoleAuth.setRoleCategory(RoleEnumType.CUSTOM_ROLE.getKey());
        saveRoleAuth.setDelFlag(false);
        saveRoleAuth.setPayAuth(roleAuth.getPayAuth());
        saveRoleAuth.setRetentionAuth(roleAuth.getRetentionAuth());
        saveRoleAuth.setIsNatureOpen(roleAuth.getIsNatureOpen());
        saveRoleAuth.setTopAuth(roleAuth.getTopAuth());

        saveRoleAuth = roleAuthRepository.save(saveRoleAuth);

        //构建 ROLE_AUTH_DETAIL,全量detail
        List<RoleAuthDetail> roleAuthDetailList = this.getInitRoleAuthList();

        Map<String, RoleAuthDetail> roleAuthDetailMap = Maps.uniqueIndex(roleAuth.getRoleAuthDetails(), new Function<RoleAuthDetail, String>() {
            @Override
            public String apply(RoleAuthDetail roleAuthDetail) {
                return roleAuthDetail.getAuth();
            }
        });

        //构建选中信息
        for (RoleAuthDetail roleAuthDetail : roleAuthDetailList) {
            RoleAuthDetail newRoleAuthDetail = roleAuthDetailMap.get(roleAuthDetail.getAuth());

            if (null != newRoleAuthDetail) {
                roleAuthDetail.setEdit(newRoleAuthDetail.getEdit());
                roleAuthDetail.setView(newRoleAuthDetail.getView());
            }

            roleAuthDetail.setRoleId(saveRoleAuth.getId());
        }

        //保存 ROLE_AUTH_DETAIL
        roleAuthDetailRepository.save(roleAuthDetailList);

        return saveRoleAuth;
    }

    /**
     * 获取全部未选中的所有的菜单权限MAP,
     */
    private Map<String, RoleAuthDetail> getAllRoleAuthMap() {
        return getRoleAuthMapByRoleType(RoleEnumType.CUSTOM_AUTH.getKey());
    }

    /**
     * 获取渠道账号全部的菜单权限MAP,
     */
    private Map<String, RoleAuthDetail> getChannelAccountRoleAuthMap() {
        return getRoleAuthMapByRoleType(RoleEnumType.CHANNEL_PERSON.getKey());
    }

    /**
     * 获取全部未选中的所有的菜单权限MAP,
     */
    private Map<String, RoleAuthDetail> getRoleAuthMapByRoleType(Long roleType) {

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

        List<RoleAuthDetail> roleAuthDetailList = roleAuthDetailRepository.findDetailByRole(roleType);

        for (RoleAuthDetail roleAuthDetail : roleAuthDetailList) {
            result.put(roleAuthDetail.getAuth(), new RoleAuthDetail(roleAuthDetail));
        }

        return result;
    }

    /**
     * 获取全部未选中的所有的菜单权限LIST,
     */
    private List<RoleAuthDetail> getInitRoleAuthList() {

        List<RoleAuthDetail> result = new ArrayList<>();

        List<RoleAuthDetail> roleAuthDetailList = roleAuthDetailRepository.findDetailByRole(RoleEnumType.CUSTOM_AUTH.getKey());

        for (RoleAuthDetail roleAuthDetail : roleAuthDetailList) {
            result.add(new RoleAuthDetail(roleAuthDetail));
        }

        return result;
    }


    /**
     * 修改自定义角色,参数只传了选中的权限
     * created by sunhao 20170609
     */
    @Override
    public RoleAuth modifyCustomRole(Account loginAccount, RoleAuth roleAuth) {

        //修改保存基础信息
        RoleAuth customRoleAuth = roleAuthRepository.findOne(roleAuth.getId());
        customRoleAuth.setRoleName(!StringUtils.isEmpty(roleAuth.getRoleName()) ? roleAuth.getRoleName() : customRoleAuth.getRoleName());
        customRoleAuth.setPayAuth(null != roleAuth.getPayAuth() ? roleAuth.getPayAuth() : customRoleAuth.getPayAuth());
        customRoleAuth.setRetentionAuth(null != roleAuth.getRetentionAuth() ? roleAuth.getRetentionAuth() : customRoleAuth.getRetentionAuth());
        customRoleAuth.setIsNatureOpen(null != roleAuth.getIsNatureOpen() ? roleAuth.getIsNatureOpen() : customRoleAuth.getIsNatureOpen());
        customRoleAuth.setTopAuth(null != roleAuth.getTopAuth() ? roleAuth.getTopAuth() : customRoleAuth.getTopAuth());
        customRoleAuth.setModifyTime(new Date());
        customRoleAuth.setModifyAccount(loginAccount.getId());

        customRoleAuth = roleAuthRepository.save(customRoleAuth);

        //原始权限
        List<RoleAuthDetail> customRoleAuthDetailList = roleAuthDetailRepository.findDetailByRole(roleAuth.getId());

        //新权限
        List<RoleAuthDetail> sourceRoleAuthDetailList = roleAuth.getRoleAuthDetails();
        Map<String, RoleAuthDetail> sourceRoleAuthDetailMap = Maps.uniqueIndex(sourceRoleAuthDetailList, new Function<RoleAuthDetail, String>() {
            @Override
            public String apply(RoleAuthDetail roleAuthDetail) {
                return roleAuthDetail.getAuth();
            }
        });

        for (RoleAuthDetail oldRoleAuthDetail : customRoleAuthDetailList) {

            RoleAuthDetail newRoleAuthDetail = sourceRoleAuthDetailMap.get(oldRoleAuthDetail.getAuth());

            if (null != newRoleAuthDetail) {
                //修改
                oldRoleAuthDetail.setView(newRoleAuthDetail.getView());
                oldRoleAuthDetail.setEdit(newRoleAuthDetail.getEdit());

            } else {
                //初始化
                oldRoleAuthDetail.setEdit(false);
                oldRoleAuthDetail.setView(false);
            }
        }

        //保存
        roleAuthDetailRepository.save(customRoleAuthDetailList);

        //修改相应自定义角色的权限
        this.updateCustomRoleAuthByRoleId(roleAuth.getRoleAuthDetails(), customRoleAuth);

        return customRoleAuth;
    }

    /**
     * 批量更新相应自定义角色的权限
     */
    private void updateCustomRoleAuthByRoleId(List<RoleAuthDetail> roleAuthDetailList, RoleAuth customRoleAuth) {

        List<Auth> authList = authRepository.findAuthByRoleCategory(customRoleAuth.getId());

        for (Auth auth : authList) {
            auth.setControlAuth(parseAuth2JsonArray(roleAuthDetailList).toString());
            auth.setPayAuth(customRoleAuth.getPayAuth());
            auth.setRetentionAuth(customRoleAuth.getRetentionAuth());
            auth.setIsNatureOpen(customRoleAuth.getIsNatureOpen());
            auth.setTopAuth(customRoleAuth.getTopAuth());
        }

        authRepository.save(authList);
    }

    /**
     * 删除自定义角色
     * created by sunhao 20170609
     */
    @Override
    public int deleteCustomRole(Account loginAccount, Long roleId) {

        return roleAuthRepository.deleteCustomRole(roleId, loginAccount.getId(), new Date());
    }

    /**
     * 删除未激活的子账号
     * created by sunhao 20170609
     */
    @Override
    public boolean deleteInactivateSubAccount(Long subAccountId) {

        Account account = accountRepository.findOne(subAccountId);

        if (account.getStatus() == -3) {

            //删除账户
            accountRepository.delete(account);

            //删除权限
            authRepository.deleteAuthByAccount(subAccountId);
            dataAuthRepository.deleteAuthByAccount(subAccountId);

            return true;
        }

        return false;
    }

    /**
     * 校验自定义权限名称是否重复,true:重复,false:没重复
     * create by sunhao 20170608
     */
    @Override
    public boolean checkCustomRoleName(Account loginAccount, String roleName, Long roleId) {

        boolean result = false;

        //如果检查编辑角色的名字,查看名字是否和之前一样,不一样就按原逻辑检查,一样就直接返回false
        if (null != roleId) {

            RoleAuth roleAuth = roleAuthRepository.findOne(roleId);
            if (!roleAuth.getRoleName().equals(roleName)) {
                roleId = null;
            }
        }

        //检查名字
        if (null == roleId) {

            List<Long> subAccountList = this.getAllSubAccountList(loginAccount);

            BigInteger number = roleAuthRepository.findByAccountAndName(subAccountList, roleName);

            result = null != number && number.intValue() > 0;

        }

        return result;
    }

    /**
     * 校验自定义权限的数量,true:超过,false:没超过
     * create by sunhao 20170608
     */
    @Override
    public boolean checkCustomRoleNumber(Account loginAccount) {

        List<Long> subAccountList = this.getAllSubAccountList(loginAccount);

        BigInteger number = roleAuthRepository.findCustomNumByAccount(subAccountList);

        return null != number && number.intValue() >= MAX_CUSTOM_ROLE_NUM;
    }

    /**
     * 校验子管理员的数量 true:超过,false:没超过
     * create by sunhao 20170608
     */
    @Override
    public boolean checkSubMangerNumber(Account loginAccount) {

        BigInteger number = accountRepository.findSubMangerNumByParent(loginAccount.getIsSuperUser() ? loginAccount.getId() : loginAccount.getParent());

        return number != null && number.intValue() >= MAX_MANAGE_NUM;
    }

    @Override
    public boolean checkUpdateSubMangerNumber(Account loginAccount, Account updateAccount) {

        Account originalAccount = accountRepository.findOne(updateAccount.getId());

        if (!originalAccount.getRoleCategory().equals(updateAccount.getRoleCategory()) && RoleEnumType.MANAGER.getKey().equals(updateAccount.getRoleCategory())) {

            return this.checkSubMangerNumber(loginAccount);

        } else {
            return false;
        }
    }

    /**
     * 校验Email存在,true:存在,false:不存在
     * create by sunhao 20170616
     */
    @Override
    public boolean checkEmailExists(String email) {

        Account account = accountRepository.findAccountByEmail(email);

        return null != account;
    }

    /**
     * 校验此角色下面有无子账号 true:有,false:没有
     * created by sunhao 20170609
     */
    @Override
    public boolean checkCustomRoleAccount(Long roleId) {

        BigInteger number = accountRepository.findAccountNumByRoleId(roleId);
        return null != number && number.intValue() > 0;
    }

    /**
     * 根据账户和APP获取权限数据
     */
    @Override
    public Auth findAuth(Long account, Long app) {
        return authRepository.findAuthByAccountAndApp(account, app);
    }

    /**
     * 是否包含自然量
     * modify by sunhao 20170613
     */
    @Override
    public boolean isNature(Long accountId, Long app) {

        boolean isNatureOpen = true;

        Account account = accountRepository.findOne(accountId);
        RoleAuth roleAuth = roleAuthRepository.findOne(account.getRoleCategory());

        //不是管理员且不是应用管理员的时候,通过auth判断
        if (!account.getIsSuperUser() && null != roleAuth && !roleAuth.getRoleCategory().equals(RoleEnumType.MANAGER.getKey())
                && !roleAuth.getRoleCategory().equals(RoleEnumType.SUB_APP_MANAGER.getKey())) {

            Auth auth = this.findAuth(accountId, app);
            isNatureOpen = auth != null && auth.getIsNatureOpen();
        }

        return isNatureOpen;
    }

    /**
     * 查询子账号的根节点母账号
     */
    @Override
    public Account findRootParentAccount(Long childAccountId) {

        Account account = accountRepository.findOne(childAccountId);

        while (null != account.getParent() && 0 != account.getParent()) {

            account = accountRepository.findOne(account.getParent());
        }

        return account;
    }

    /**
     * 校验母账号是否过期
     */
    @Override
    public boolean isOriginAccountPast(Long account) {

        Account accountObject = accountRepository.findOne(account);

        String nowDate = DateUtil.format(new Date(), DateUtil.C_DATE_PATTON_DEFAULT);

        return !StringUtil.isEmpty(accountObject.getPastDate()) && DateUtil.compare_date(nowDate, accountObject.getPastDate()) == 1;
    }

    @Override
    public Account check(String email) {
        return accountRepository.findAccountByEmail(email);
    }



    /**
     * 根据账号查询授权的APP
     */
    @Override
    public List<Long> findAuthAppListByAccount(Long accountId) {

        return authRepository.findAppListByAccount(accountId);
    }

    /**
     * 发送激活邮件,激活链接复用忘记密码方法
     * 亲爱的用户，已为您xxxxx@xxx.com邮箱创建TrackingIO子账号。点击此链接设置密码:http://trackingio.com/resetpwd.html#?
     */
    @Override
    public boolean sendSubAccountActivateEmail(Account loginAccount, Account subAccount) {

        boolean result = true;

        try {
            //修改忘记密码时间
            subAccount.setForgetPwdTime(new Date().getTime());
            subAccount.setForgetPwdStatus(false);
            accountRepository.save(subAccount);

            final String url = Constant.accountCheckUrl + "/resetpwd.html#?message=" + HashAlgorithms.MD5("superuser_" + subAccount.getId() + subAccount.getForgetPwdTime()) + subAccount.getId();

            //邮件主题
            final String subject = "TrackingIO" + (subAccount.getIsChannelPerson() ? "渠道账号" : "子账号") + "激活";
            //邮件内容
            StringBuilder content = new StringBuilder();
            content.append("<!doctype html> <html><head></head><body> ")
                    .append("亲爱的用户：</br>")
                    .append("您好，").append(loginAccount.getEmail())
                    .append("已为您的").append(subAccount.getEmail()).append("邮箱创建TrackingIO").append(subAccount.getIsChannelPerson() ? "渠道账号。" : "子账号。")
                    .append("点击此链接设置密码激活账号: </br>")
                    .append("<a href=\"").append(url).append("\">").append(url).append("</a>")
                    .append("</body></html>");

            //收件人列表
            List<String> mailList = new ArrayList<>();
            mailList.add(subAccount.getEmail());
            MailUtils.sendHtmlEmail(subject, content.toString(), mailList);
        } catch (Exception e) {

            logger.error(e.getMessage(), e);
            result = false;
        }

        return result;
    }


    /**
     * 上线数据处理
     * 临时处理
     */
    @Override
    public boolean dealWithOldAuth() {

        //获取全部的菜单
        Map<String, RoleAuthDetail> roleAuthDetailMap = this.getAllRoleAuthMap();

        //所有的权限
        List<Auth> authList = authRepository.findAll();

        for (Auth auth : authList) {

            if (null != auth.getControlAuth() && auth.getControlAuth().startsWith("[") && auth.getControlAuth().endsWith("]")) {

                JSONArray authArray = JSONArray.fromObject(auth.getControlAuth());
                JSONArray newAuthArray = new JSONArray();

                if (!CollectionUtils.isEmpty(authArray)) {

                    for (int i = 0; i < authArray.size(); i++) {

                        JSONObject authObject = authArray.getJSONObject(i);

                        String authName = authObject.getString("auth");

                        if (roleAuthDetailMap.containsKey(authName)) {

                            RoleAuthDetail roleAuthDetail = roleAuthDetailMap.get(authName);

                            authObject.put("parentAuth", roleAuthDetail.getParentAuth());
                            authObject.put("parentAuth", roleAuthDetail.getParentAuth());
                            authObject.put("sort", roleAuthDetail.getSort());

                            newAuthArray.add(authObject);
                        }

                    }

                    auth.setControlAuth(newAuthArray.toString());
                }
            }
        }

        authRepository.save(authList);

        return true;
    }

}
