package com.vctgo.system.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibm.icu.util.ULocale;
import com.vctgo.common.core.constant.CacheConstants;
import com.vctgo.common.core.constant.Constants;
import com.vctgo.common.core.constant.RoleConstants;
import com.vctgo.common.core.constant.ServiceNameConstants;
import com.vctgo.common.core.exception.ServiceException;
import com.vctgo.common.core.text.Convert;
import com.vctgo.common.core.utils.DateUtils;
import com.vctgo.common.core.utils.ServletUtils;
import com.vctgo.common.core.utils.StrUtils;
import com.vctgo.common.core.web.domain.AjaxResult;
import com.vctgo.common.core.web.domain.TenantEntity;
import com.vctgo.common.message.mail.EmailUtil;
import com.vctgo.common.message.sms.SmsUtil;
import com.vctgo.common.mybatisplus.constant.MybatisPageConstants;
import com.vctgo.common.mybatisplus.util.TenantUtils;
import com.vctgo.common.redis.service.RedisService;
import com.vctgo.common.security.utils.SecurityUtils;
import com.vctgo.system.api.RemoteFileService;
import com.vctgo.system.api.domain.*;
import com.vctgo.system.api.model.LoginUser;
import com.vctgo.system.domain.SysPost;
import com.vctgo.system.domain.*;
import com.vctgo.system.mapper.*;
import com.vctgo.system.service.ISysMenuService;
import com.vctgo.system.service.ISysTenantService;
import com.vctgo.system.util.ConstantUtils;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.Collator;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


/**
 * 租户管理Service业务层处理
 *
 * @author vctgo
 * @date 2022-04-11
 */
@Slf4j
@Service
public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant> implements ISysTenantService
{
    @Autowired
    private SysTenantMapper sysTenantMapper;

    @Autowired
    private SysTenantPackageMapper sysTenantPackageMapper;

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private SysPostMapper sysPostMapper;

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Autowired
    private SysRoleDeptMapper sysRoleDeptMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Autowired
    private SysUserPostMapper userPostMapper;

    @Autowired
    private SysGardenManageMapper sysGardenManageMapper;

    @Autowired
    private SysReGardenBranchMapper sysReGardenBranchMapper;

    @Autowired
    private SysReServiceTenantMapper sysReServiceTenantMapper;

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private ISysMenuService sysMenuService;

    @Autowired
    private RemoteFileService remoteFileService;

    @Autowired
    private SysReServiceTenantServiceImpl sysReServiceTenantServiceImpl;

    @Autowired
    private RedisService redisService;

    @Autowired
    EmailUtil emailUtil;

    @Autowired
    SmsUtil smsUtil;

    /**
     * 新增租户管理
     *
     * @param sysTenant 租户管理
     * @return 结果
     */
    @Override
    @Synchronized
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertSysTenant(SysTenant sysTenant)
    {
        AjaxResult res = new AjaxResult();
        Long maxTenantId = sysTenantMapper.getMaxTenantId();
        sysTenant.setId(maxTenantId == null ? 100L : maxTenantId+1);
        //新增租户开始
//        if (StrUtils.isEmpty(sysTenant.getId())){
//            return res.error("租户编码为空,请重新设置!");
//        }
        //先判断租户编码是否存在
//        Long tenantcount = sysTenantMapper.selectCount("id",sysTenant.getId());
//        if (tenantcount > 0)
//        {
//            return res.error("租户编码已存在,请重新设置!");
//        }

        if (StrUtils.isEmpty(sysTenant.getUserName())){
            return AjaxResult.error("管理员账号为空,请重新设置!");
        }
        //先判断租户管理员设置的账号是否存在
        SysUser usercount = userMapper.checkUserNameUnique(sysTenant.getUserName());
        if (usercount != null)
        {
            return AjaxResult.error("账号已存在,请重新设置！");
        }
        String password = sysTenant.getPassword();
        if(StrUtils.isEmpty(password)){
            return AjaxResult.error("密码不能为空！");
        }
//        if(!isValid(password)){
//            return AjaxResult.error("密码至少包含数字、字母、特殊字符，且长度为6~20位");
//        }
        //存在集团的幼儿园租户，上级集团Id和幼儿园Id均需要传值
        if(sysTenant.getTenantType()==2 && (StrUtils.isEmpty(sysTenant.getGardenId())|| StrUtils.isEmpty(sysTenant.getBranchId()))){
            throw new IllegalArgumentException("参数有误，请联系管理员!");
        }
        SysTenant sysTenantx = new SysTenant();
        //默认查询集团的数据列表
        if(sysTenant.getTenantType()==1){
            sysTenantx.setTenantType(Integer.valueOf(ConstantUtils.TENANT_TYPE_1));
            sysTenantx.setGardenId(sysTenant.getGardenId());
        }else if(sysTenant.getTenantType()==2){
            sysTenantx.setTenantType(Integer.valueOf(ConstantUtils.TENANT_TYPE_2));
            sysTenantx.setBranchId(sysTenant.getBranchId());
        }else if(sysTenant.getTenantType()==3){
            sysTenantx.setTenantType(Integer.valueOf(ConstantUtils.TENANT_TYPE_3));
            sysTenantx.setBranchId(sysTenant.getBranchId());
        }
        List<SysTenant> sysTenantList = sysTenantMapper.selectSysTenantList(sysTenantx);
        if(CollectionUtils.isNotEmpty(sysTenantList)){
            return AjaxResult.error("当前租户已存在管理员账号!");
        }
        //根据集团id查询集团的租户id
        SysTenant sysGroupTenant = new SysTenant();
        sysGroupTenant.setTenantType(Integer.valueOf(ConstantUtils.TENANT_TYPE_1));
        sysGroupTenant.setGardenId(sysTenant.getGardenId());
        List<SysTenant> sysGroupTenantList = sysTenantMapper.selectSysTenantList(sysGroupTenant);
        //一个集团只允许有一个租户管理员账号，且必须先建立集团账号，才可以建立幼儿园账号
        if(sysTenant.getTenantType()==2 && CollectionUtils.isEmpty(sysGroupTenantList)){
            return AjaxResult.error("当前租户集团管理员账号未开通，请先开通集团租户账号!");
        }
        //一个集团只允许有一个租户管理员账号
        if(sysTenant.getGardenId() != null && sysGroupTenantList.size()>1){
            return AjaxResult.error("当前租户集团账号有误，请联系管理员!");
        }

        if(sysTenant.getTenantType() == 1){
            //将前端由于切换传入的分园id清空
            sysTenant.setBranchId(null);
        }
        //创建租户
        sysTenantMapper.insert(sysTenant);
        if(sysTenant.getTenantType() == 1){
            createGardenReTenantData(sysTenant);
        }else{
            sysTenant.getParams().put("parentId", sysGroupTenantList.get(0).getId());
            createBranchReTenantData(sysTenant);
        }
//        SysReTenantKindergarten reTenantKindergarten = genReTenantKindergartenData(sysTenant);
//        //关联幼儿园
//        reTenantKindergartenMapper.insert(reTenantKindergarten);

        //租户创建完成后 开始创建相关基础数据
        TenantUtils.execute(sysTenant.getId(), () -> {
            //创建默认部门--部门默认名称以租户名称
//            Long deptid = null;
//            if(sysTenant.getTenantType() == 1){
//                deptid = createGardenDept(sysTenant);
//            }else if(sysTenant.getTenantType() == 2){
//                Long parentTenantId = sysGroupTenantList.get(0).getId();
//                SysDept topSysDept = deptMapper.selectTopDeptByTenantId(parentTenantId);
//                deptid = createKindergartenDept(sysTenant, topSysDept.getDeptId());
//            }else if(sysTenant.getTenantType() == 3){
//                deptid = createGardenDept(sysTenant);
//            }
            //创建默认岗位--岗位默认为主班教师、配班教师、保育员
            if(sysTenant.getTenantType() == 1 || sysTenant.getTenantType() == 3){
                createPost(sysTenant);
            }
            //创建默认角色--角色默认为租户名称+管理员
            Long roleid = createRole(sysTenant);
            //创建默认账号
//          createUser(sysTenant, deptid, roleid);
            createUser(sysTenant, roleid);
        });

        if (redisService.hasKey("tenantList")) {
            redisService.setCacheList("tenantList", sysTenant);
        } else {
            List<SysTenant> tenantList = sysTenantMapper.selectSysTenantList(sysTenant);
            tenantList.add(sysTenant);
            redisService.setCacheList("tenantList", tenantList);
        }

        return AjaxResult.success("租户创建成功!");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertNewSysTenant(SysTenant sysTenant)
    {
        if(sysTenant.getTenantType() == 1){
            //将前端由于切换传入的分园id清空
            sysTenant.setBranchId(null);
            return insertSysGardenTenant(sysTenant);
        }else{
            return insertSysBranchTenant(sysTenant);
        }
    }

    /**
     * 新增租户管理
     *
     * @param sysTenant 租户管理
     * @return 结果
     */
    @Synchronized
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertSysGardenTenant(SysTenant sysTenant) {
        SysGardenManage sysGardenManage = sysGardenManageMapper.selectById(sysTenant.getGardenId());
        if (sysGardenManage == null) {
            return AjaxResult.error("未找到需要添加的集团，请检查!");
        }

        Long maxTenantId = sysTenantMapper.getMaxTenantId();
        sysTenant.setId(maxTenantId == null ? 100L : maxTenantId + 1);
        if (StrUtils.isEmpty(sysTenant.getUserName())) {
            return AjaxResult.error("管理员账号为空,请重新设置!");
        }
        //先判断租户管理员设置的账号是否存在
        SysUser usercount = userMapper.checkUserNameUnique(sysTenant.getUserName());
        if (usercount != null) {
            return AjaxResult.error("账号名已存在,请重新设置！");
        }
        String password = sysTenant.getPassword();
        if (StrUtils.isEmpty(password)) {
            return AjaxResult.error("密码不能为空！");
        }

        //存在集团的幼儿园租户，上级集团Id和幼儿园Id均需要传值
        if (sysTenant.getGardenId() == null || sysTenant.getBranchId() != null) {
            throw new IllegalArgumentException("参数有误，请联系管理员!");
        }
        //根据集团id查询集团的租户id
        SysTenant sysGroupTenant = new SysTenant();
        sysGroupTenant.setTenantType(Integer.valueOf(ConstantUtils.TENANT_TYPE_1));
        sysGroupTenant.setGardenId(sysTenant.getGardenId());
        sysGroupTenant.setDelFlag(ConstantUtils.IS_DELETED_0);
        List<SysTenant> sysGroupTenantList = sysTenantMapper.selectSysTenantList(sysGroupTenant);
        //一个集团只允许有一个租户管理员账号
        if (CollectionUtils.isNotEmpty(sysGroupTenantList)) {
            return AjaxResult.error("当前租户已存在管理员账号!");
        }

        //创建租户
        sysTenantMapper.insert(sysTenant);
        //租户关联表插入数据
        SysReGardenBranch sysReGardenBranch = new SysReGardenBranch();
        sysReGardenBranch.setId(sysTenant.getId());
        sysReGardenBranch.setParentId(0L);
        sysReGardenBranch.setDeptType(String.valueOf(ConstantUtils.TENANT_TYPE_1));
        sysReGardenBranchMapper.insert(sysReGardenBranch);

        //租户创建完成后 开始创建相关基础数据
        //创建默认部门--部门默认名称以租户名称
        createGardenDept(sysTenant);
        //创建默认岗位--岗位默认为主班教师、配班教师、保育员
        if (sysTenant.getTenantType() == 1) {
            createPost(sysTenant);
        }
        //创建默认角色--角色默认为租户名称+管理员
        Long roleid = createRole(sysTenant);
        //创建默认账号
        createUser(sysTenant, roleid);

        if (redisService.hasKey("tenantList")) {
            redisService.setCacheList("tenantList", sysTenant);
        } else {
            List<SysTenant> tenantList = sysTenantMapper.selectSysTenantList(sysTenant);
            tenantList.add(sysTenant);
            redisService.setCacheList("tenantList", tenantList);
        }

        return AjaxResult.success("租户创建成功!");
    }

    /**
     * 新增租户管理
     *
     * @param sysTenant 租户管理
     * @return 结果
     */
    @Synchronized
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertSysBranchTenant(SysTenant sysTenant) {
        Long maxTenantId = sysTenantMapper.getMaxTenantId();
        sysTenant.setId(maxTenantId == null ? 100L : maxTenantId + 1);

        if (StrUtils.isEmpty(sysTenant.getUserName())) {
            return AjaxResult.error("管理员账号为空,请重新设置!");
        }

        //先判断租户管理员设置的账号是否存在
        SysUser usercount = userMapper.checkUserNameUnique(sysTenant.getUserName());
        if (usercount != null) {
            return AjaxResult.error("账号已存在,请重新设置！");
        }
        String password = sysTenant.getPassword();
        if (StrUtils.isEmpty(password)) {
            return AjaxResult.error("密码不能为空！");
        }

        if (sysTenant.getTenantType() == null) {
            throw new IllegalArgumentException("参数有误，请联系管理员!");
        }

        //存在集团的幼儿园租户，上级集团Id和幼儿园Id均需要传值
        if (sysTenant.getTenantType() == 2 && (sysTenant.getGardenId() == null || sysTenant.getBranchId() == null)) {
            throw new IllegalArgumentException("参数有误，请联系管理员!");
        }
        if (sysTenant.getTenantType() == 3 && (sysTenant.getGardenId() != null || sysTenant.getBranchId() == null)) {
            throw new IllegalArgumentException("参数有误，请联系管理员!");
        }
        //默认查询集团的数据列表
        SysTenant sysTenantx = new SysTenant();
        sysTenantx.setTenantType(sysTenant.getTenantType());
        sysTenantx.setBranchId(sysTenant.getBranchId());
        List<SysTenant> sysTenantList = sysTenantMapper.selectSysTenantList(sysTenantx);
        if (CollectionUtils.isNotEmpty(sysTenantList)) {
            return AjaxResult.error("当前租户已存在管理员账号!");
        }
        //根据集团id查询集团的租户id
        SysTenant sysGroupTenant = new SysTenant();
        sysGroupTenant.setTenantType(Integer.valueOf(ConstantUtils.TENANT_TYPE_1));
        sysGroupTenant.setGardenId(sysTenant.getGardenId());
        List<SysTenant> sysGroupTenantList = sysTenantMapper.selectSysTenantList(sysGroupTenant);

        //一个集团只允许有一个租户管理员账号，且必须先建立集团账号，才可以建立幼儿园账号
        if (sysTenant.getTenantType() == 2 && CollectionUtils.isEmpty(sysGroupTenantList)) {
            return AjaxResult.error("当前租户集团管理员账号未开通，请先开通集团租户账号!");
        }

        //一个集团只允许有一个租户管理员账号
        if (sysTenant.getTenantType() == 2 && sysGroupTenantList.size() > 1) {
            return AjaxResult.error("当前租户集团账号有误，请联系管理员!");
        }

        //创建租户
        sysTenantMapper.insert(sysTenant);
        //租户关联表插入数据,首先判断插入的是有集团的幼儿园租户还是无集团的幼儿园租户
        if (sysTenant.getTenantType() == 2) {
            SysReGardenBranch sysReGardenBranch = new SysReGardenBranch();
            sysReGardenBranch.setId(sysTenant.getId());
            sysReGardenBranch.setParentId(sysGroupTenantList.get(0).getId());
            sysReGardenBranch.setDeptType(String.valueOf(ConstantUtils.TENANT_TYPE_2));
            sysReGardenBranchMapper.insert(sysReGardenBranch);
        } else if (sysTenant.getTenantType() == 3) {
            SysReGardenBranch sysReGardenBranch = new SysReGardenBranch();
            sysReGardenBranch.setId(sysTenant.getId());
            sysReGardenBranch.setParentId(0L);
            sysReGardenBranch.setDeptType(String.valueOf(ConstantUtils.TENANT_TYPE_2));
            sysReGardenBranchMapper.insert(sysReGardenBranch);
        }

        //租户创建完成后 开始创建相关基础数据
        //创建默认部门--部门默认名称以租户名称
        if (sysTenant.getTenantType() == 2) {
            createKindergartenDept(sysTenant);
        } else if (sysTenant.getTenantType() == 3) {

            createGardenDept(sysTenant);
            //创建默认岗位--岗位默认为主班教师、配班教师、保育员
            createPost(sysTenant);
        }

        //创建默认角色--角色默认为租户名称+管理员
        Long roleid = createRole(sysTenant);

        //创建默认账号
        createUser(sysTenant, roleid);

        if (redisService.hasKey("tenantList")) {
            redisService.setCacheList("tenantList", sysTenant);
        } else {
            List<SysTenant> tenantList = sysTenantMapper.selectSysTenantList(sysTenant);
            tenantList.add(sysTenant);
            redisService.setCacheList("tenantList", tenantList);
        }
        return AjaxResult.success("租户创建成功!");
    }

    /**
     * 密码由数字和下划线组成，且大于等于8个字符。
     */
    public static boolean isCharacterAndNumber(String password) {
        String pattern = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,}$";
        return Pattern.matches(pattern, password);
    }

    public static boolean isValid(String password) {
        String pattern = "^(?=.*\\d)(?=.*[a-zA-Z])(?=.*[^\\da-zA-Z\\s]).{6,20}$";
        //密码中必须包含字母（不区分大小写）、数字、特称字符  只能使用!@#$^,.
//        String pattern = "^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[!@#$^,\.])[0-9a-zA-Z!@#$^,\.]{6,20}$";
        return Pattern.matches(pattern, password);
    }

    /**
     * 查询租户管理
     *
     * @param id 租户管理主键
     * @return 租户管理
     */
    @Override
    public SysTenant selectSysTenantById(Long id) {
        return sysTenantMapper.selectTenantInfoById(id);
    }

    /**
     * 查询租户管理列表-分页
     *
     * @param sysTenant 租户管理
     * @return 租户管理
     */
    @Override
    public IPage<SysTenant> selectSysTenantPage(SysTenant sysTenant)
    {
        Page mpPage =new Page(Convert.toLong(ServletUtils.getParameterToInt(MybatisPageConstants.PAGE_NUM),1L)
                ,Convert.toLong(ServletUtils.getParameterToInt(MybatisPageConstants.PAGE_SIZE),10L));
        return sysTenantMapper.selectSysTenantList(mpPage,sysTenant);
    }

    /**
     * 查询租户管理列表
     *
     * @param sysTenant 租户管理
     * @return 租户管理
     */
    @Override
    public List<SysTenant> selectSysTenantList(SysTenant sysTenant) {
        return sysTenantMapper.selectSysTenantList(sysTenant);
    }

    /**
     * 全量查询租户管理树结构
     *
     * @param sysTenant 租户管理
     * @return
     */
    @Override
    public List<SysTenant> selectSysTenantTree(SysTenant sysTenant) {
        List<SysTenant> sysTenantList = sysTenantMapper.selectSysTenantTree(sysTenant);
        if (!sysTenantList.isEmpty()) {
            sysTenantList = convertSysTenantListToTree(sysTenantList, 0L);
        }
        return sysTenantList;
    }

    /**
     * 将文件信息列表改成文件信息树状
     *
     * @param list
     * @param parentId
     * @return
     */
    // 递归方法
    private List<SysTenant> convertSysTenantListToTree(List<SysTenant> list, long parentId) {
        return list.stream()
                .filter(sysTenant -> parentId == sysTenant.getParentId())
                .peek(sysTenant -> sysTenant.setSysTenantList(convertSysTenantListToTree(list, sysTenant.getId())))
                .sorted((o1, o2) -> {
                    Collator instance = Collator.getInstance(ULocale.SIMPLIFIED_CHINESE.toLocale());
                    return instance.compare(o1.getTenantName(), o2.getTenantName());
                }).collect(Collectors.toList());
    }

    private void createUser(SysTenant sysTenant, Long roleId) {
        SysUser user = new SysUser();
        user.setUserAccount(sysTenant.getUserName())
                .setUserName(sysTenant.getUserName())
                .setNickName(sysTenant.getTenantName())
                .setUserType("00")//用户类型 00 表示各管理员账号，不允许租户修改删除 其他账号为10
                .setEmail(sysTenant.getUserEmail())
                .setPhonenumber(sysTenant.getUserPhone())
                .setAccountDate(new Date())
                .setRemark(sysTenant.getTenantName() + "管理员")
                .setTenantId(sysTenant.getId());
        //默认密码采用随机生成
//        String randomPassword = SecurityUtils.randomPassword(8);//随机密码8位
//        String password = SecurityUtils.encryptPassword(randomPassword);
        String password = SecurityUtils.encryptPassword(sysTenant.getPassword());
        user.setPassword(password);
        user.setCreateById(SecurityUtils.getUserId());
        userMapper.insert(user);
        userRoleMapper.insert(new SysUserRole().setRoleId(roleId).setUserId(user.getUserId()).setTenantId(sysTenant.getId()));
        String configValue = Convert.toStr(redisService.getCacheObject( CacheConstants.SYS_CONFIG_KEY + "sys.message.type"));
        if ("false".equals(configValue)){
            //短信
//            String content = "尊敬的租户，你好！感谢使用幼儿园教·育·研智慧平台，请牢记登录你的登录账号："+sysTenant.getUserName()+"，初始密码："+sysTenant.getPassword();
//            emailUtil.sendSimpleMail("租户管理员账号注册成功",content,sysTenant.getUserEmail());
        }else {
            try {
                smsUtil.send(sysTenant.getUserPhone(), sysTenant.getPassword());
            }catch (Exception e){
                log.info("短信调用失败:"+e.getMessage());
                //调用邮件通知
                emailUtil.sendSimpleMail("租户管理员账号注册成功","请牢记登录密码:"+sysTenant.getPassword(),sysTenant.getUserEmail());
            }
        }
    }

    public SysReTenantKindergarten genReTenantKindergartenData(SysTenant sysTenant){
        SysReTenantKindergarten ReTenantKindergarten = new SysReTenantKindergarten();
        ReTenantKindergarten.setTenantId(sysTenant.getId());
        ReTenantKindergarten.setBranchId(sysTenant.getGardenId());
        ReTenantKindergarten.setCreateBy(SecurityUtils.getUsername());
        ReTenantKindergarten.setCreateTime(new Date());
        return ReTenantKindergarten;
    }

    private Long createRole(SysTenant sysTenant) {
        // 创建角色
        SysRole role = new SysRole();
        role.setRoleName(sysTenant.getTenantName()+"管理员").setRoleKey("admin")
                .setRoleSort("1").setDataScope("1").setMenuCheckStrictly(true).setDeptCheckStrictly(true);
        role.setCreateBy(sysTenant.getUserName());
        role.setRemark("租户管理员");
        role.setAdminRole(true);
        role.setIsDefault("1");
        role.setTenantId(sysTenant.getId());
        sysRoleMapper.insert(role);
        //根据租户套餐ids查出套餐编码塞入角色-菜单表
//        createRoleMenu(sysTenant,role);
        return role.getRoleId();
    }

    //目前为单套餐,跟租户绑定,解耦防止套餐变动影响多个租户
    private void createRoleMenu(SysTenant sysTenant,SysRole role)
    {
        SysTenantPackage sysTenantPackage = sysTenantPackageMapper.selectById(sysTenant.getTenantPackage());
        List<String> subMeuns = Arrays.asList(sysTenantPackage.getMenuIds().split(","));

        List<SysRoleMenu> roleMenuList = subMeuns.stream().map(menuid -> {
            SysRoleMenu entity = new SysRoleMenu();
            entity.setRoleId(role.getRoleId());
            entity.setMenuId(Convert.toLong(menuid));
            return entity;
        }).collect(Collectors.toList());
        sysRoleMenuMapper.batchRoleMenu(roleMenuList);
    }

    private void createPost(SysTenant sysTenant) {
        Long tenantId = sysTenant.getId();
        List<SysPost> postList = new ArrayList<>(3);
        SysPost zbjsPost = new SysPost();
        SysPost pbjsPost = new SysPost();
        SysPost byyPost = new SysPost();
        zbjsPost.setPostCode("zbjs").setPostName("主班教师").setIsSysPost("Y").setPostSort("0");
        zbjsPost.setTenantId(tenantId);
        pbjsPost.setPostCode("pbjs").setPostName("配班教师").setIsSysPost("Y").setPostSort("0");
        pbjsPost.setTenantId(tenantId);
        byyPost.setPostCode("byy").setPostName("保育员").setIsSysPost("Y").setPostSort("0");
        byyPost.setTenantId(tenantId);
        postList.add(zbjsPost);
        postList.add(pbjsPost);
        postList.add(byyPost);
        sysPostMapper.insertBatch(postList);
    }

    private Long createDept(SysTenant sysTenant) {
        // 创建部门
        SysDept dept = new SysDept();
        dept.setParentId(0L).setAncestors("0").setDeptName(sysTenant.getTenantName()).setOrderNum(0)
                .setLeader(sysTenant.getTenantName()+"管理员").setPhone(sysTenant.getUserPhone()).setEmail(sysTenant.getUserEmail());
        deptMapper.insert(dept);
        return dept.getDeptId();
    }

    private Long createGardenDept(SysTenant sysTenant) {
        // 创建部门
        SysDept dept = new SysDept();
        dept.setParentId(0L);
        dept.setAncestors("0");
        dept.setDeptName(sysTenant.getTenantName());
        if(sysTenant.getTenantType() == 1){
            dept.setDeptType(ConstantUtils.DEPT_TYPE_1);
        }else if(sysTenant.getTenantType() == 2 || sysTenant.getTenantType() == 3){
            dept.setDeptType(ConstantUtils.DEPT_TYPE_2);
        }
        dept.setOrderNum(0);
        dept.setPhone(sysTenant.getUserPhone());
        dept.setEmail(sysTenant.getUserEmail());
        dept.setTenantId(sysTenant.getId());
        deptMapper.insert(dept);
        return dept.getDeptId();
    }

    private Long createKindergartenDept(SysTenant sysTenant) {
        //根据租户id查询上级集团（如果没有，则为独立幼儿园；如果有，则为集团幼儿园）
        // 创建部门
        SysDept dept = new SysDept();
        dept.setParentId(0L);
        dept.setAncestors("0");
        dept.setDeptName(sysTenant.getTenantName());
        dept.setDeptType(ConstantUtils.DEPT_TYPE_2);
        dept.setOrderNum(1);
        dept.setPhone(sysTenant.getUserPhone());
        dept.setEmail(sysTenant.getUserEmail());
        dept.setTenantId(sysTenant.getId());
        deptMapper.insert(dept);
        SysDept updateSysDept = new SysDept();
        updateSysDept.setDeptId(dept.getDeptId());
        updateSysDept.setAncestors("0");
        deptMapper.updateById(updateSysDept);
        return dept.getDeptId();
    }

    private int createGardenReTenantData(SysTenant sysTenant) {
        SysReGardenBranch sysReGardenBranch = new SysReGardenBranch();
        sysReGardenBranch.setId(sysTenant.getId());
        sysReGardenBranch.setParentId(0L);
        sysReGardenBranch.setDeptType(ConstantUtils.DEPT_TYPE_1);
        return sysReGardenBranchMapper.insert(sysReGardenBranch);
    }

    private int createBranchReTenantData(SysTenant sysTenant) {
        SysReGardenBranch sysReGardenBranch = new SysReGardenBranch();
        sysReGardenBranch.setId(sysTenant.getId());
        if(sysTenant.getTenantType() == 2){
            sysReGardenBranch.setParentId((Long)sysTenant.getParams().get("parentId"));
        }else{
            sysReGardenBranch.setParentId(0L);
        }
        sysReGardenBranch.setDeptType(ConstantUtils.DEPT_TYPE_2);
        return sysReGardenBranchMapper.insert(sysReGardenBranch);
    }

    /**
     * 修改租户管理
     *
     * @param sysTenant 租户管理
     * @return 结果
     */
    @Override
    public int updateSysTenantRelaData(SysTenant sysTenant) {
        return sysTenantMapper.updateSysTenantRelaData(sysTenant);
    }

    /**
     * 修改租户管理
     *
     * @param sysTenant 租户管理
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateSysTenant(SysTenant sysTenant) {
        //判断最新的租户套餐是否改变 重新授权 租户二级管理员账号需重新分配三级账号权限
        SysTenant t_sysTenant = sysTenantMapper.selectById(sysTenant.getId());
        if (sysTenant.getTenantType() == 1 && sysTenant.getStatus() == 1) {
            //查询当前集团租户下是否存在未禁用的幼儿园租户
            List<SysTenant> branchTenantList = sysTenantMapper.selectBranchTenantList(sysTenant.getGardenId());
            if (CollectionUtils.isNotEmpty(branchTenantList)) {
                throw new ServiceException("该集团下幼儿园租户未被禁用，该集团租户不能被禁用");
            }
        }
        //根据变更后的账号查询租户账号是否已存在
        SysUser repeatSysTenant = userMapper.checkTenantNameUnique(sysTenant.getUserName(), sysTenant.getId());
        if (repeatSysTenant != null) {
            throw new ServiceException("账号名已存在，请重新设置！");
        }
        //根据变更前的账号查询用户表的信息，已作用户表变更的查询条件
        SysUser beforeSysUser = userMapper.selectUserByUserAccount(t_sysTenant.getId(), t_sysTenant.getUserName());
        if (sysTenant.getTenantPackage() != null && !sysTenant.getTenantPackage().equals(t_sysTenant.getTenantPackage())) {
            if (sysTenant.getTenantPackage() != null && !sysTenant.getTenantPackage().equals(t_sysTenant.getTenantPackage())) {
                List<SysRole> roleList = sysRoleMapper.queryAdminRole(sysTenant.getId());
                SysRole t_role = roleList.get(0);//正常逻辑下每个租户只有一个二级管理员账号
                if (t_role != null) {
                    //删除原租户下所有的角色-菜单信息
                    sysRoleMenuMapper.deleteRoleMenuByTenantId(sysTenant.getId());
                    //新增默认角色-菜单信息
                    TenantUtils.execute(sysTenant.getId(), () -> createRoleMenu(sysTenant, t_role));
                    // TODO  此处需要优化,如果当前同时在线人数较多,会出现卡顿
                    //原登租户录账号退出重登 租户二级管理员账号需重新分配三级账号权限
                    Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
                    for (String key : keys) {
                        LoginUser onlineUser = redisService.getCacheObject(key);
                        if (onlineUser.getSysUser().getTenantId() != null && onlineUser.getSysUser().getTenantId().equals(sysTenant.getId())) {
                            redisService.deleteObject(key);
                        }
                    }
                }
            }
        }
        int count = sysTenantMapper.updateById(sysTenant);
        if (count > 0) {
            SysUser updateSysUser = new SysUser();
            updateSysUser.setTenantId(beforeSysUser.getTenantId());
            updateSysUser.setPhonenumber(sysTenant.getUserPhone());
            updateSysUser.setUserName(sysTenant.getUserName());
            updateSysUser.setUserAccount(sysTenant.getUserName());
            userMapper.updateTenantAccount(updateSysUser);

            if (1 == sysTenant.getStatus() || !sysTenant.getUserName().equals(beforeSysUser.getUserAccount())) {
                Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");

                // 平台修改租户超管的账号
                if (!sysTenant.getUserName().equals(beforeSysUser.getUserAccount())) {
                    for (String key : keys) {
                        LoginUser onlineUser = redisService.getCacheObject(key);
                        if (onlineUser.getSysUser() != null
                                && (onlineUser.getSysUser().getTenantId() != null
                                && onlineUser.getSysUser().getTenantId().equals(sysTenant.getId())
                                && onlineUser.getUsername().equals(beforeSysUser.getUserName()))) {
                            redisService.deleteObject(key);
                            break;
                        }
                    }
                }

                // 平台设置租户状态为禁用
                if (1 == sysTenant.getStatus() ) {
                    for (String key : keys) {
                        LoginUser onlineUser = redisService.getCacheObject(key);
                        if (onlineUser.getSysUser() != null && (onlineUser.getSysUser().getTenantId() != null
                                && onlineUser.getSysUser().getTenantId().equals(sysTenant.getId()))) {
                            redisService.deleteObject(key);
                        }
                    }
                }
            }
        }

        return count;
    }

    /**
     * 新增权限管理
     *
     * @param sysTenant 租户管理
     * @return 结果
     */
    @Override
    public int addConfigPermission(SysTenant sysTenant) {

        // 保存租户对应的业务服务
        List<SysReServiceTenant> sysReServiceTenantList = new ArrayList<>();
        sysTenant.getSysServiceList().forEach(sysService -> {
            SysReServiceTenant sysReServiceTenant = new SysReServiceTenant();
            sysReServiceTenant.setTenantId(sysTenant.getId());
            sysReServiceTenant.setServiceId(sysService.getId());
            sysReServiceTenantList.add(sysReServiceTenant);
        });
        sysReServiceTenantMapper.insertBatch(sysReServiceTenantList);
        return 1;
    }

    /**
     * 修改权限管理
     *
     * @param sysTenant 租户管理
     * @return 结果
     */
    @Override
    public int editConfigPermission(SysTenant sysTenant) {
        List<SysReServiceTenant> sysReServiceTenantList = sysReServiceTenantMapper.selectSysReServiceTenantListByTenantId(sysTenant.getId().toString());
        List<String> serviceIdListFromDb = sysReServiceTenantList.stream().map(SysReServiceTenant::getServiceId).map(String::valueOf).collect(Collectors.toList());
        // 修改开通业务
        List<SysService> sysServiceList = sysTenant.getSysServiceList();
        List<String> serviceIdListFromFront = sysServiceList.stream().map(SysService::getId).map(String::valueOf).collect(Collectors.toList());
        List<String> publicServiceIdList = new ArrayList<>(serviceIdListFromDb);

        // 业务处理
        List<SysReServiceTenant> sysReServiceTenantListTmp = new ArrayList<>();

        // 需要删除的
        serviceIdListFromDb.removeIf(serviceIdListFromFront::contains);
        serviceIdListFromDb.forEach(serviceId -> {
            Optional<SysReServiceTenant> sysReServiceTenantOptional = sysReServiceTenantList.stream().filter(serviceTenantTmp -> serviceTenantTmp.getServiceId().toString().equals(serviceId)).findAny();
            if (sysReServiceTenantOptional.isPresent()) {
                SysReServiceTenant sysReServiceTenant = sysReServiceTenantOptional.get();
                sysReServiceTenant.setIsDeleted(ConstantUtils.IS_DELETED_1);
                sysReServiceTenant.setUpdateById(SecurityUtils.getUserId());
                sysReServiceTenant.setUpdateTime(new Date());
                sysReServiceTenantListTmp.add(sysReServiceTenant);
            }
        });

        // 需要新增的
        sysServiceList.removeIf(sysService -> publicServiceIdList.contains(sysService.getId().toString()));
        sysServiceList.forEach(service -> {
            SysReServiceTenant sysReServiceTenant = new SysReServiceTenant();
            sysReServiceTenant.setTenantId(sysTenant.getId());
            sysReServiceTenant.setServiceId(service.getId());
            sysReServiceTenant.setCreateById(SecurityUtils.getUserId());
            sysReServiceTenant.setCreateTime(new Date());
            sysReServiceTenant.setServiceName(service.getServiceName());
            sysReServiceTenant.setIsDeleted(ConstantUtils.IS_DELETED_0);
            sysReServiceTenantListTmp.add(sysReServiceTenant);
        });
        sysReServiceTenantServiceImpl.saveOrUpdateBatch(sysReServiceTenantListTmp);

        // TODO  此处需要优化,如果当前同时在线人数较多,会出现卡顿
        Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
        keys.forEach(key -> {
            LoginUser onlineUser = redisService.getCacheObject(key);
            if (Objects.nonNull(onlineUser)
                    && Objects.nonNull(onlineUser.getSysUser())
                    && onlineUser.getSysUser().getTenantId() != null
                    && onlineUser.getSysUser().getTenantId().equals(sysTenant.getId())) {
                redisService.deleteObject(key);
            }
        });

        if ("0".equals(sysTenant.getLongTerm())) {
            sysTenant.setTenantStartTime(sysTenant.getCreateTime());
            sysTenant.setTenantEndTime(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", "2099-12-31 23:59:59"));
        }

        SecurityUtils.setTemporaryIgnoreTables(Arrays.asList("sys_role", "sys_role_menu"));
        // 新增文件服务
        Optional<SysReServiceTenant> fileServiceOptional = sysReServiceTenantListTmp.stream()
                .filter(sysReServiceTenant -> "文件服务".equals(sysReServiceTenant.getServiceName()))
                .findAny();
        if (fileServiceOptional.isPresent()
                && ConstantUtils.IS_DELETED_0.equals(fileServiceOptional.get().getIsDeleted())) {

            // 如果开通了文件服务，那么需要创建一个新的角色---文件资源管理员   出来，而且不能被删除
            LambdaQueryWrapper<SysRole> sysRoleWrapper = new LambdaQueryWrapper<>();
            sysRoleWrapper.eq(TenantEntity::getTenantId, sysTenant.getId());
            List<SysRole> sysRoles = sysRoleMapper.selectList(sysRoleWrapper);
            Optional<SysRole> sysRoleOptional = sysRoles.stream()
                    .filter(sysRole -> Objects.equals(RoleConstants.ROLE_KEY_FILE_RESOURCE_USER, sysRole.getRoleKey())).findFirst();
            if (!sysRoleOptional.isPresent()) {
                SysRole sysRole = new SysRole();
                sysRole.setRoleName("文件资源管理员");
                sysRole.setRoleKey(RoleConstants.ROLE_KEY_FILE_RESOURCE_USER);
                sysRole.setAdminRole(false);
                sysRole.setDelFlag(ConstantUtils.IS_DELETED_0);
                sysRole.setRoleSort("1");
                sysRole.setDataScope("1");
                sysRole.setIsDefault("1");
                sysRole.setRemark("文件资源管理员");
                sysRole.setTenantId(sysTenant.getId());
                sysRole.setCreateById(SecurityUtils.getUserId());
                sysRole.setCreateBy(SecurityUtils.getUsername());
                sysRoleMapper.insertRole(sysRole);

                extractSysTenantRole(sysTenant, sysRole);
            } else {
                // 更新角色id
                SysRole sysRole = sysRoleOptional.get();
                sysRole.setDelFlag(ConstantUtils.IS_DELETED_0);
                sysRole.setStatus(ConstantUtils.IS_DELETED_0);
                sysRoleMapper.updateRole(sysRole);

                extractSysTenantRole(sysTenant, sysRole);
            }
        } else if (fileServiceOptional.isPresent()
                && ConstantUtils.IS_DELETED_1.equals(fileServiceOptional.get().getIsDeleted())) {
            LambdaQueryWrapper<SysRole> sysRoleWrapper = new LambdaQueryWrapper<>();
            sysRoleWrapper.eq(TenantEntity::getTenantId, sysTenant.getId());
            List<SysRole> sysRoles = sysRoleMapper.selectList(sysRoleWrapper);
            Optional<SysRole> sysRoleOptional = sysRoles.stream()
                    .filter(sysRole -> Objects.equals(RoleConstants.ROLE_KEY_FILE_RESOURCE_USER, sysRole.getRoleKey())).findAny();
            if (sysRoleOptional.isPresent()) {
                SysRole sysRole = sysRoleOptional.get();
                sysRole.setDelFlag(ConstantUtils.IS_DELETED_1);
                sysRole.setStatus(ConstantUtils.IS_DELETED_1);
                sysRoleMapper.updateRole(sysRole);

                // 删除角色和文件动态权限关系
                sysRoleMenuMapper.deleteRoleMenuByRoleIdAndTenantId(sysRole.getRoleId().toString(), sysRole.getTenantId().toString());
            }
        }

        SecurityUtils.removeTemporaryIgnoreTables(Arrays.asList("sys_role", "sys_role_menu"));
        // 去掉角色和文件动态权限关系的理由，"角色不会再新增"，选择硬编码
        //        功能设计方向：约定优于配置，配置优于代码
        //        配置 ----> 灵活配置 ---->  mysql  + redis      -----> 相对难实现，易扩展，覆盖场景多
        //        代码 ----> 硬编码   ----> 修改bug + 变更业务     -----> 相对容易实现

        // 创建文件夹
        remoteFileService.initMkdirByTenantId(sysTenant.getId(), ServiceNameConstants.FILE_SERVICE, sysTenant.getTenantName());

        return sysTenantMapper.updateById(sysTenant);
    }

    private void extractSysTenantRole(SysTenant sysTenant, SysRole sysRole) {
        LambdaQueryWrapper<SysMenu> sysMenuWrapper = new LambdaQueryWrapper<>();
        sysMenuWrapper.eq(SysMenu::getVisible, ConstantUtils.IS_DELETED_0);
        sysMenuWrapper.eq(SysMenu::getStatus, ConstantUtils.IS_DELETED_0);
        List<SysMenu> sysMenuList = sysMenuMapper.selectList(sysMenuWrapper);
        Optional<SysMenu> sysMenuOptional = sysMenuList.stream().filter(sysMenu -> sysMenu.getPerms().startsWith("file:")).findFirst();
        if (sysMenuOptional.isPresent()) {
            List<SysMenu> sysMenusTmp = sysMenuService.buildMenuTree(sysMenuList);
            Long menuParentId = getMenuRootId(sysMenuOptional.get().getMenuId(), sysMenuList);
            List<SysMenu> sysMenuListTmp = new ArrayList<>();
            recursionTreeToList(sysMenuListTmp, sysMenusTmp.stream().filter(sysMenu -> sysMenu.getMenuId().longValue() == menuParentId).collect(Collectors.toList()).stream().findFirst().get());
            List<SysRoleMenu> sysRoleMenuList = new ArrayList<>();
            sysMenuListTmp.stream().distinct().forEach(sysMenu -> {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setMenuId(sysMenu.getMenuId());
                sysRoleMenu.setRoleId(sysRole.getRoleId());
                sysRoleMenu.setTenantId(sysTenant.getId());
                sysRoleMenuList.add(sysRoleMenu);
            });
            sysRoleMenuMapper.batchRoleMenuByPackage(sysRoleMenuList);
        }
    }

    /**
     * 通过某一个子菜单id，获取根节点id
     *
     * @param menuId
     * @param sysMenuList
     * @return
     */
    public Long getMenuRootId(Long menuId, List<SysMenu> sysMenuList) {
        SysMenu sysMenuTmp = sysMenuList.stream().filter(sysMenu -> sysMenu.getMenuId().longValue() == menuId.longValue()).findFirst().get();
        if (sysMenuTmp.getParentId() != 0L) {
            getMenuRootId(sysMenuTmp.getParentId(), sysMenuList);
        }
        return sysMenuTmp.getMenuId();
    }

    /**
     * 树结构转列表结构
     */
    public void recursionTreeToList(List<SysMenu> sysMenuList, SysMenu sysMenu) {
        if (CollectionUtils.isEmpty(sysMenu.getChildren())) {
            return;
        }
        sysMenuList.add(sysMenu);
        for (SysMenu sysMenuTmp : sysMenu.getChildren()) {
            sysMenuList.add(sysMenuTmp);
            this.recursionTreeToList(sysMenuList, sysMenuTmp);
        }
    }

    /**
     * 批量删除租户管理
     *
     * @param ids 需要删除的租户管理主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteSysTenantByIds(Long[] ids)
    {
        //优化删除逻辑
        //1.先删租户
        int tenantres = sysTenantMapper.deleteSysTenantByIds(ids);
        if(tenantres>0){
            //下面才会进行子模块数据的删除
            //部门模块
            deptMapper.deleteDeptByTenantId(ids);
            //职位模块
            sysPostMapper.deletePostByTenantId(ids);
            //权限
            sysRoleMapper.deleteRoleByTenantId(ids);
            sysRoleMenuMapper.deleteRoleMenuByTenantIds(ids);
            sysRoleDeptMapper.deleteRoleDeptByTenantId(ids);
            //账号
            userMapper.deleteUserByTenantId(ids);
            userRoleMapper.deleteUserRoleByTenantId(ids);
            userPostMapper.deleteUserPostByTenantId(ids);
            //删除租户关联表的数据
            for (Long id : ids) {
                sysReGardenBranchMapper.deleteById(id);
            }
            return 1;
        }else {
            throw new ServiceException("当前租户已被删除不存在！");
        }
    }

    /**
     * 删除租户管理信息
     *
     * @param id 租户管理主键
     * @return 结果
     */
    @Override
    public int deleteSysTenantById(Long id)
    {
        return sysTenantMapper.deleteById(id);
    }

    /**
     * 获取指定租户的父级租户信息
     *
     * @param tenantId 租户管理主键
     * @return 结果
     */
    @Override
    public SysTenant getParentTenantInfo(Long tenantId) {
        if(tenantId == null){
            tenantId = SecurityUtils.getTenantId() == null ? SecurityUtils.getTenantId() : 9999L;
        }
        return sysTenantMapper.getParentTenantInfo(tenantId);
    }

    @Override
    public List<SysTenant> selectTenantList(SysTenant sysTenant) {
        return sysTenantMapper.selectTenantList(sysTenant);
    }
}
