package org.dromara.system.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.constant.SystemConstants;
import org.dromara.common.core.constant.TenantConstants;
import org.dromara.common.core.enums.TenantSignStatus;
import org.dromara.common.core.enums.TenantType;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.WorkflowService;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.enums.DataScopeType;
import org.dromara.common.redis.utils.CacheUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.tenant.core.TenantEntity;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.system.domain.*;
import org.dromara.system.domain.bo.SysReferenceBo;
import org.dromara.system.domain.bo.SysTenantBo;
import org.dromara.system.domain.bo.SysTenantExtendBo;
import org.dromara.system.domain.bo.SysTenantReviewBo;
import org.dromara.system.domain.dto.TenantDTO;
import org.dromara.system.domain.vo.SysReferenceVO;
import org.dromara.system.domain.vo.SysTenantVo;
import org.dromara.system.mapper.*;
import org.dromara.system.service.ISysTenantService;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 租户Service业务层处理
 *
 * @author Michelle.Chung
 */
@RequiredArgsConstructor
@Service
public class SysTenantServiceImpl implements ISysTenantService {

    private final SysTenantMapper baseMapper;
    private final SysTenantExtendMapper tenantExtendMapper;
    private final SysTenantPackageMapper tenantPackageMapper;
    private final SysTenantAccountMapper tenantAccountMapper;
    private final SysUserMapper userMapper;
    private final SysDeptMapper deptMapper;
    private final SysRoleMapper roleMapper;
    private final SysRoleMenuMapper roleMenuMapper;
    private final SysRoleDeptMapper roleDeptMapper;
    private final SysUserRoleMapper userRoleMapper;
    private final SysDictTypeMapper dictTypeMapper;
    private final SysDictDataMapper dictDataMapper;
    private final SysConfigMapper configMapper;
    private final SysUserMapper sysUserMapper;

    /**
     * 查询租户
     */
    @Override
    public SysTenantVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 基于租户ID查询租户
     */
    @Cacheable(cacheNames = CacheNames.SYS_TENANT, key = "#tenantId")
    @Override
    public SysTenantVo queryByTenantId(String tenantId) {
        return baseMapper.getTenantInfoByTenantId(tenantId);
    }

    /**
     * 查询租户列表
     */
    @Override
    public TableDataInfo<SysTenantVo> queryPageList(SysTenantBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysTenant> lqw = buildQueryWrapper(bo);
        Page<SysTenantVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询租户列表
     */
    @Override
    public List<SysTenantVo> queryList(SysTenantBo bo) {
        LambdaQueryWrapper<SysTenant> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<SysTenant> buildQueryWrapper(SysTenantBo bo) {
        LambdaQueryWrapper<SysTenant> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getTenantId()), SysTenant::getTenantId, bo.getTenantId());
        lqw.like(bo.getOneParentId() != null, SysTenant::getParentIds, String.valueOf(bo.getOneParentId()));
        lqw.like(StringUtils.isNotBlank(bo.getContactUserName()), SysTenant::getContactUserName, bo.getContactUserName());
        lqw.eq(StringUtils.isNotBlank(bo.getContactPhone()), SysTenant::getContactPhone, bo.getContactPhone());
        lqw.like(StringUtils.isNotBlank(bo.getCompanyName()), SysTenant::getCompanyName, bo.getCompanyName());
        lqw.eq(StringUtils.isNotBlank(bo.getLicenseNumber()), SysTenant::getLicenseNumber, bo.getLicenseNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getAddress()), SysTenant::getAddress, bo.getAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getIntro()), SysTenant::getIntro, bo.getIntro());
        lqw.like(StringUtils.isNotBlank(bo.getDomain()), SysTenant::getDomain, bo.getDomain());
        lqw.eq(bo.getPackageId() != null, SysTenant::getPackageId, bo.getPackageId());
        lqw.eq(bo.getExpireTime() != null, SysTenant::getExpireTime, bo.getExpireTime());
        lqw.eq(bo.getAccountCount() != null, SysTenant::getAccountCount, bo.getAccountCount());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysTenant::getStatus, bo.getStatus());
        lqw.orderByAsc(SysTenant::getType);
        lqw.orderByDesc(SysTenant::getCreateTime);
        return lqw;
    }

    /**
     * 新增租户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(SysTenantExtendBo bo) {

        // 处理sys_tenant表数据
        SysTenant tenant = new SysTenant();
        String currentTenantId = TenantHelper.getTenantId();
        SysTenantVo currentTenant = this.queryByTenantId(currentTenantId);
        Assert.isTrue(TenantType.allowCreateByType(currentTenant.getType(), bo.getType()), () -> new ServiceException("您无权限创建此类型的租户"));

        // 生成租户ID
        List<String> tenantIds = baseMapper.selectObjs(
            new LambdaQueryWrapper<SysTenant>().select(SysTenant::getTenantId),
            (Object x) -> Convert.toStr(x)
        );
        String tenantId = generateTenantId(tenantIds);

        String tenantName = bo.getCompanyName();
        String nickName = bo.getEmergencyContact();
        String phoneNumber = bo.getEmergencyContactPhone();
        tenant.setAgencyTenantId(currentTenantId);
        if (bo.getType() == TenantType.AGENT.getType()) {
            tenantName = bo.getAgencyName();
        } else if (bo.getType() == TenantType.MERCHANT.getType()){
            tenant.setPromoterTenantId(LoginHelper.getUserIdStr());
            tenantName = bo.getStoreName();
            nickName = bo.getContactUserName();
            phoneNumber = bo.getContactPhone();
        } else if (bo.getType() == TenantType.REFERENCE.getType()){
            tenant.setPromoterTenantId(LoginHelper.getUserIdStr());
            tenantName = bo.getPersonName();
            nickName = bo.getPersonName();
            phoneNumber = bo.getPersonPhone();
        }
        // 设置sys_tenant表字段
        tenant.setTenantId(tenantId);
        String parentIds = StrUtil.isBlank(currentTenant.getParentIds()) ? String.valueOf(currentTenant.getId()) : StrBuilder.create(currentTenant.getParentIds()).append(",").append(currentTenant.getId()).toString();
        tenant.setParentIds(parentIds);
        tenant.setCompanyName(StrUtil.isBlank(bo.getCompanyName()) ? tenantName : bo.getCompanyName());
        tenant.setLicenseNumber(bo.getLicenseNumber());
        tenant.setAddress(bo.getAddress());
        tenant.setDomain(bo.getDomain());
        tenant.setIntro(bo.getIntro());
        tenant.setPackageId(bo.getPackageId());
        tenant.setAccountCount(10L);
        tenant.setStatus(bo.getStatus());
        tenant.setDelFlag("0");
        tenant.setBusinessLicense(bo.getBusinessLicense());
        tenant.setJoinTime(LocalDateTime.now());
        tenant.setAttachment(bo.getAttachment());
        tenant.setPromoteList(bo.getPromoteList());
        tenant.setExpireTime(bo.getExpireTime());
        tenant.setStoreName(bo.getStoreName());
        tenant.setCompanyType(bo.getCompanyType());
        tenant.setBusinessTypes(bo.getBusinessTypes());
        tenant.setRelated(bo.getRelated());
        tenant.setContactUserName(bo.getContactUserName());
        tenant.setContactPhone(bo.getContactPhone());
        tenant.setAgencyName(bo.getAgencyName());
        tenant.setCounty(bo.getCounty());
        tenant.setBirthday(bo.getBirthday());
        tenant.setQualification(bo.getQualification());
        tenant.setType(bo.getType());

        // 插入sys_tenant表
        boolean tenantInserted = baseMapper.insert(tenant) > 0;
        if (!tenantInserted) {
            throw new ServiceException("创建租户失败");
        }
        bo.setId(tenant.getId());

        // 处理sys_tenant_extend表数据
        SysTenantExtend tenantExtend = new SysTenantExtend();
        // 设置租户ID关联
        tenantExtend.setTenantId(tenantId);
        // 设置扩展表字段
        tenantExtend.setStoreId(tenant.getId());
        tenantExtend.setIdCard(bo.getIdCard());
        tenantExtend.setIdCardType(bo.getIdCardType());
        tenantExtend.setCertificate(bo.getCertificate());
        tenantExtend.setPersonName(bo.getPersonName());
        tenantExtend.setPersonPhone(bo.getPersonPhone());
        tenantExtend.setBankType(bo.getBankType());
        tenantExtend.setBankName(bo.getBankName());
        tenantExtend.setBankCard(bo.getBankCard());
        tenantExtend.setBankPhone(bo.getBankPhone());
        tenantExtend.setRemark(bo.getRemark());
        // 检查用户名是否已存在
        String username = bo.getUsername();
        if (StringUtils.isNotBlank(username)) {
            Long count1 = tenantExtendMapper.selectCount(Wrappers.lambdaQuery(SysTenantExtend.class).eq(SysTenantExtend::getUsername, username));
            Long count2 = sysUserMapper.selectCount(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUserName, username));
            Assert.isTrue(count1 == 0 && count2 == 0, () -> new ServiceException("用户名已存在，请更换其他用户名"));
            tenantExtend.setUsername(username);
        }
        tenantExtend.setPassword(bo.getPassword());
        tenantExtend.setPackageId(bo.getPackageId());
        tenantExtend.setInviteUserId(bo.getInviteUserId());
        tenantExtend.setSignDate(bo.getSignDate());
        tenantExtend.setSplitRatio(bo.getSplitRatio());
        tenantExtend.setSigner(bo.getSigner());
        tenantExtend.setContractYear(bo.getContractYear());
        tenantExtend.setContractAttachment(bo.getContractAttachment());
        tenantExtend.setSignStatus(TenantSignStatus.TO_BE_SUBMITTED.getStatus());
        tenantExtend.setPayeeName(bo.getPayeeName());
        tenantExtend.setEmergencyContact(bo.getEmergencyContact());
        tenantExtend.setEmergencyContactPhone(bo.getEmergencyContactPhone());
        tenantExtend.setDepositAmount(bo.getDepositAmount());
        tenantExtend.setAgencyYear(bo.getAgencyYear());
        tenantExtend.setAgreement(bo.getAgreement());
        tenantExtend.setOtherAttachment(bo.getOtherAttachment());
        tenantExtend.setEntryTime(bo.getEntryTime());
        tenantExtend.setExpiryDate(bo.getExpiryDate());
        tenantExtend.setPromoterStatus(bo.getPromoterStatus());
        tenantExtend.setMchtCode(bo.getMchtCode());


        boolean extendInserted = tenantExtendMapper.insert(tenantExtend) > 0;
        if (!extendInserted) {
            throw new ServiceException("创建租户扩展信息失败");
        }

        // 创建角色
        Long roleId = createTenantRole(tenantId, bo.getPackageId());

//        创建店铺账号
        SysTenantAccount tenantAccount = new SysTenantAccount();
        tenantAccount.setTenantId(tenantId);
        tenantAccount.setType(bo.getType());
        tenantAccount.setMoneyBalance(BigDecimal.ZERO);
        tenantAccount.setWallet(BigDecimal.ZERO);
        tenantAccount.setRevenue(BigDecimal.ZERO);
        tenantAccountMapper.insert(tenantAccount);


        // 创建部门
        SysDept dept = new SysDept();
        dept.setTenantId(tenantId);
        dept.setDeptName(tenantName);
        dept.setParentId(Constants.TOP_PARENT_ID);
        dept.setAncestors(Constants.TOP_PARENT_ID.toString());
        deptMapper.insert(dept);
        Long deptId = dept.getDeptId();

        // 关联角色和部门
        SysRoleDept roleDept = new SysRoleDept();
        roleDept.setRoleId(roleId);
        roleDept.setDeptId(deptId);
        roleDeptMapper.insert(roleDept);

        // 创建用户
        SysUser user = new SysUser();
        user.setTenantId(tenantId);
        user.setUserName(bo.getUsername());
        user.setNickName(nickName);
        user.setPassword(BCrypt.hashpw(bo.getPassword()));
        user.setDeptId(deptId);
        user.setPhonenumber(phoneNumber);
        userMapper.insert(user);

        // 设置部门负责人
        SysDept sd = new SysDept();
        sd.setLeader(user.getUserId());
        sd.setDeptId(deptId);
        deptMapper.updateById(sd);

        // 关联用户和角色
        SysUserRole userRole = new SysUserRole();
        userRole.setUserId(user.getUserId());
        userRole.setRoleId(roleId);
        userRoleMapper.insert(userRole);


        String defaultTenantId = TenantConstants.DEFAULT_TENANT_ID;

        // 复制字典类型
        List<SysDictType> dictTypeList = dictTypeMapper.selectList(
            new LambdaQueryWrapper<SysDictType>().eq(SysDictType::getTenantId, defaultTenantId));
        for (SysDictType dictType : dictTypeList) {
            dictType.setDictId(null);
            dictType.setTenantId(tenantId);
            dictType.setCreateBy(null);
            dictType.setCreateTime(null);
            dictType.setUpdateBy(null);
            dictType.setUpdateTime(null);
        }
        dictTypeMapper.insertBatch(dictTypeList);

        // 复制字典数据
        List<SysDictData> dictDataList = dictDataMapper.selectList(
            new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getTenantId, defaultTenantId));
        for (SysDictData dictData : dictDataList) {
            dictData.setDictCode(null);
            dictData.setTenantId(tenantId);
            dictData.setCreateBy(null);
            dictData.setCreateTime(null);
            dictData.setUpdateBy(null);
            dictData.setUpdateTime(null);
        }
        dictDataMapper.insertBatch(dictDataList);

        // 复制系统配置
        List<SysConfig> sysConfigList = configMapper.selectList(
            new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getTenantId, defaultTenantId));
        for (SysConfig config : sysConfigList) {
            config.setConfigId(null);
            config.setTenantId(tenantId);
            config.setCreateBy(null);
            config.setCreateTime(null);
            config.setUpdateBy(null);
            config.setUpdateTime(null);
        }
        configMapper.insertBatch(sysConfigList);

        // 工作流处理
        if (SpringUtils.getProperty("warm-flow.enabled", Boolean.class, false)) {
            SpringUtils.getBean(WorkflowService.class).syncDef(tenantId);
        }

        return true;
    }

    /**
     * 生成租户id
     *
     * @param tenantIds 已有租户id列表
     * @return 租户id
     */
    private String generateTenantId(List<String> tenantIds) {
        // 随机生成6位
        String numbers = RandomUtil.randomNumbers(6);
        // 判断是否存在，如果存在则重新生成
        if (tenantIds.contains(numbers)) {
            return generateTenantId(tenantIds);
        }
        return numbers;
    }

    /**
     * 根据租户菜单创建租户角色
     *
     * @param tenantId  租户编号
     * @param packageId 租户套餐id
     * @return 角色id
     */
    private Long createTenantRole(String tenantId, Long packageId) {
        // 获取租户套餐
        SysTenantPackage tenantPackage = tenantPackageMapper.selectById(packageId);
        if (ObjectUtil.isNull(tenantPackage)) {
            throw new ServiceException("套餐不存在");
        }
        // 获取套餐菜单id
        List<Long> menuIds = StringUtils.splitTo(tenantPackage.getMenuIds(), Convert::toLong);

        // 创建角色
        SysRole role = new SysRole();
        role.setTenantId(tenantId);
        role.setRoleName(TenantConstants.TENANT_ADMIN_ROLE_NAME);
        role.setRoleKey(TenantConstants.TENANT_ADMIN_ROLE_KEY);
        role.setRoleSort(1);
        role.setStatus(SystemConstants.NORMAL);
        role.setDataScope(DataScopeType.DEPT_AND_CHILD_OR_SELF.getCode());
        roleMapper.insert(role);
        Long roleId = role.getRoleId();

        // 创建角色菜单
        List<SysRoleMenu> roleMenus = new ArrayList<>(menuIds.size());
        menuIds.forEach(menuId -> {
            SysRoleMenu roleMenu = new SysRoleMenu();
            roleMenu.setRoleId(roleId);
            roleMenu.setMenuId(menuId);
            roleMenus.add(roleMenu);
        });
        roleMenuMapper.insertBatch(roleMenus);

        return roleId;
    }

    /**
     * 修改租户信息
     */
    @CacheEvict(cacheNames = CacheNames.SYS_TENANT, key = "#bo.tenantId")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(SysTenantExtendBo bo) {
        if (bo.getId() == null || bo.getTenantId() == null) {
            throw new ServiceException("租户ID不能为空");
        }

        SysTenant existingTenant = baseMapper.selectById(bo.getId());
        if (existingTenant == null) {
            throw new ServiceException("租户不存在");
        }

        // 3. 更新主表
        existingTenant.setCompanyName(bo.getCompanyName());
        existingTenant.setLicenseNumber(bo.getLicenseNumber());
        existingTenant.setAddress(bo.getAddress());
        existingTenant.setDomain(bo.getDomain());
        existingTenant.setIntro(bo.getIntro());
        existingTenant.setPackageId(bo.getPackageId());
        existingTenant.setAccountCount(bo.getAccountCount());
        existingTenant.setBusinessLicense(bo.getBusinessLicense());
        existingTenant.setAttachment(bo.getAttachment());
        existingTenant.setPromoteList(bo.getPromoteList());
        existingTenant.setExpireTime(bo.getExpireTime());
        existingTenant.setStoreName(bo.getStoreName());
        existingTenant.setCompanyType(bo.getCompanyType());
        existingTenant.setBusinessTypes(bo.getBusinessTypes());
        existingTenant.setRelated(bo.getRelated());
        existingTenant.setContactUserName(bo.getContactUserName());
        existingTenant.setContactPhone(bo.getContactPhone());
        existingTenant.setAgencyName(bo.getAgencyName());
        existingTenant.setCounty(bo.getCounty());
        existingTenant.setBirthday(bo.getBirthday());
        existingTenant.setQualification(bo.getQualification());

        // 4. 查询扩展表现有数据
        LambdaQueryWrapper<SysTenantExtend> extendQuery = new LambdaQueryWrapper<>();
        extendQuery.eq(SysTenantExtend::getStoreId, bo.getId());
        SysTenantExtend existingExtend = tenantExtendMapper.selectOne(extendQuery);
        if (existingExtend == null) {
            throw new ServiceException("租户扩展信息不存在");
        }

        // 5. 更新扩展表
        existingExtend.setStoreId(bo.getId());
        existingExtend.setIdCard(bo.getIdCard());
        existingExtend.setIdCardType(bo.getIdCardType());
        existingExtend.setCertificate(bo.getCertificate());
        existingExtend.setPersonName(bo.getPersonName());
        existingExtend.setPersonPhone(bo.getPersonPhone());
        existingExtend.setBankType(bo.getBankType());
        existingExtend.setBankName(bo.getBankName());
        existingExtend.setBankCard(bo.getBankCard());
        existingExtend.setBankPhone(bo.getBankPhone());
        existingExtend.setRemark(bo.getRemark());
        // 检查用户名是否已存在
        String username = bo.getUsername();
        if (StringUtils.isNotBlank(username)) {
            LambdaQueryWrapper<SysTenantExtend> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysTenantExtend::getUsername, username);

            if (existingExtend.getId() != null) {
                queryWrapper.ne(SysTenantExtend::getId, existingExtend.getId());
            }

            Long count = tenantExtendMapper.selectCount(queryWrapper);

            if (count > 0) {
                throw new ServiceException("用户名已存在，请更换其他用户名");
            } else {
                existingExtend.setUsername(username);
            }
        }

        existingExtend.setPassword(bo.getPassword());
        existingExtend.setPackageId(bo.getPackageId());
        existingExtend.setInviteUserId(bo.getInviteUserId());
        existingExtend.setSignDate(bo.getSignDate());
        existingExtend.setSplitRatio(bo.getSplitRatio());
        existingExtend.setSigner(bo.getSigner());
        existingExtend.setContractYear(bo.getContractYear());
        existingExtend.setContractAttachment(bo.getContractAttachment());
        existingExtend.setSignStatus(bo.getSignStatus()==null?"0":bo.getSignStatus());
        existingExtend.setPayeeName(bo.getPayeeName());
        existingExtend.setEmergencyContact(bo.getEmergencyContact());
        existingExtend.setEmergencyContactPhone(bo.getEmergencyContactPhone());
        existingExtend.setDepositAmount(bo.getDepositAmount());
        existingExtend.setAgencyYear(bo.getAgencyYear());
        existingExtend.setAgreement(bo.getAgreement());
        existingExtend.setOtherAttachment(bo.getOtherAttachment());
        existingExtend.setEntryTime(bo.getEntryTime());
        existingExtend.setExpiryDate(bo.getExpiryDate());
        existingExtend.setPromoterStatus(bo.getPromoterStatus());
        existingExtend.setMchtCode(bo.getMchtCode());

        // 执行更新
        boolean success = baseMapper.updateById(existingTenant) > 0
            && tenantExtendMapper.updateById(existingExtend) > 0;
        if (!success) {
            throw new ServiceException("更新租户失败");
        }

        return true;
    }

    /**
     * 修改租户状态
     *
     * @param bo 租户信息
     * @return 结果
     */
    @CacheEvict(cacheNames = CacheNames.SYS_TENANT, key = "#bo.tenantId")
    @Override
    public int updateTenantStatus(SysTenantBo bo) {
        SysTenant tenant = new SysTenant();
        tenant.setId(bo.getId());
        tenant.setStatus(bo.getStatus());
        return baseMapper.updateById(tenant);
    }

    /**
     * 校验租户是否允许操作
     *
     * @param tenantId 租户ID
     */
    @Override
    public void checkTenantAllowed(String tenantId) {
        if (ObjectUtil.isNotNull(tenantId) && TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) {
            throw new ServiceException("不允许操作管理租户");
        }
    }

    /**
     * 批量删除租户
     */
    @CacheEvict(cacheNames = CacheNames.SYS_TENANT, allEntries = true)
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // 做一些业务上的校验,判断是否需要校验
            if (ids.contains(TenantConstants.SUPER_ADMIN_ID)) {
                throw new ServiceException("超管租户不能删除");
            }
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 校验企业名称是否唯一
     */
    @Override
    public boolean checkCompanyNameUnique(String tenantId, String companyName) {
        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysTenant>()
            .eq(SysTenant::getCompanyName, companyName)
            .ne(ObjectUtil.isNotNull(tenantId), SysTenant::getTenantId, tenantId));
        return !exist;
    }

    /**
     * 校验账号余额
     */
    @Override
    public boolean checkAccountBalance(String tenantId) {
        SysTenantVo tenant = SpringUtils.getAopProxy(this).queryByTenantId(tenantId);
        // 如果余额为-1代表不限制
        if (tenant.getAccountCount() == -1) {
            return true;
        }
        Long userNumber = userMapper.selectCount(new LambdaQueryWrapper<>());
        // 如果余额大于0代表还有可用名额
        return tenant.getAccountCount() - userNumber > 0;
    }

    /**
     * 校验有效期
     */
    @Override
    public boolean checkExpireTime(String tenantId) {
        SysTenantVo tenant = SpringUtils.getAopProxy(this).queryByTenantId(tenantId);
        // 如果未设置过期时间代表不限制
        if (ObjectUtil.isNull(tenant.getExpireTime())) {
            return true;
        }
        // 如果当前时间在过期时间之前则通过
        return tenant.getExpireTime().isAfter(LocalDateTime.now());
    }

    /**
     * 同步租户套餐
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean syncTenantPackage(String tenantId, Long packageId) {
        SysTenantPackage tenantPackage = tenantPackageMapper.selectById(packageId);
        List<SysRole> roles = roleMapper.selectList(
            new LambdaQueryWrapper<SysRole>().eq(SysRole::getTenantId, tenantId));
        List<Long> roleIds = new ArrayList<>(roles.size() - 1);
        List<Long> menuIds = StringUtils.splitTo(tenantPackage.getMenuIds(), Convert::toLong);
        roles.forEach(item -> {
            if (TenantConstants.TENANT_ADMIN_ROLE_KEY.equals(item.getRoleKey())) {
                List<SysRoleMenu> roleMenus = new ArrayList<>(menuIds.size());
                menuIds.forEach(menuId -> {
                    SysRoleMenu roleMenu = new SysRoleMenu();
                    roleMenu.setRoleId(item.getRoleId());
                    roleMenu.setMenuId(menuId);
                    roleMenus.add(roleMenu);
                });
                roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, item.getRoleId()));
                roleMenuMapper.insertBatch(roleMenus);
            } else {
                roleIds.add(item.getRoleId());
            }
        });
        if (!roleIds.isEmpty()) {
            roleMenuMapper.delete(
                new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getRoleId, roleIds).notIn(!menuIds.isEmpty(), SysRoleMenu::getMenuId, menuIds));
        }
        return true;
    }

    /**
     * 同步租户字典
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void syncTenantDict() {
        // 查询超管 所有字典数据
        List<SysDictType> dictTypeList = new ArrayList<>();
        List<SysDictData> dictDataList = new ArrayList<>();
        TenantHelper.ignore(() -> {
            dictTypeList.addAll(dictTypeMapper.selectList());
            dictDataList.addAll(dictDataMapper.selectList());
        });
        Map<String, List<SysDictType>> typeMap = StreamUtils.groupByKey(dictTypeList, TenantEntity::getTenantId);
        Map<String, Map<String, List<SysDictData>>> typeDataMap = StreamUtils.groupBy2Key(
            dictDataList, TenantEntity::getTenantId, SysDictData::getDictType);
        // 管理租户字典数据
        List<SysDictType> defaultTypeMap = typeMap.get(TenantConstants.DEFAULT_TENANT_ID);
        Map<String, List<SysDictData>> defaultTypeDataMap = typeDataMap.get(TenantConstants.DEFAULT_TENANT_ID);

        // 获取所有租户编号
        List<String> tenantIds = baseMapper.selectObjs(
            new LambdaQueryWrapper<SysTenant>().select(SysTenant::getTenantId)
                .eq(SysTenant::getStatus, SystemConstants.NORMAL), x -> {
                return Convert.toStr(x);
            });
        List<SysDictType> saveTypeList = new ArrayList<>();
        List<SysDictData> saveDataList = new ArrayList<>();
        Set<String> set = new HashSet<>();
        for (String tenantId : tenantIds) {
            if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) {
                continue;
            }
            for (SysDictType dictType : defaultTypeMap) {
                List<String> typeList = StreamUtils.toList(typeMap.get(tenantId), SysDictType::getDictType);
                List<SysDictData> dataList = defaultTypeDataMap.get(dictType.getDictType());
                if (typeList.contains(dictType.getDictType())) {
                    List<SysDictData> dataListTenant = typeDataMap.get(tenantId).get(dictType.getDictType());
                    Map<String, SysDictData> map = StreamUtils.toIdentityMap(dataListTenant, SysDictData::getDictValue);
                    for (SysDictData dictData : dataList) {
                        if (!map.containsKey(dictData.getDictValue())) {
                            SysDictData data = BeanUtil.toBean(dictData, SysDictData.class);
                            // 设置字典编码为 null
                            data.setDictCode(null);
                            data.setTenantId(tenantId);
                            data.setCreateTime(null);
                            data.setUpdateTime(null);
//                            data.setCreateDept(null);
                            data.setCreateBy(null);
                            data.setUpdateBy(null);
                            set.add(tenantId);
                            saveDataList.add(data);
                        }
                    }
                } else {
                    SysDictType type = BeanUtil.toBean(dictType, SysDictType.class);
                    type.setDictId(null);
                    type.setTenantId(tenantId);
                    type.setCreateTime(null);
                    type.setUpdateTime(null);
                    set.add(tenantId);
                    saveTypeList.add(type);
                    if (CollUtil.isNotEmpty(dataList)) {
                        // 筛选出 dictType 对应的 data
                        for (SysDictData dictData : dataList) {
                            SysDictData data = BeanUtil.toBean(dictData, SysDictData.class);
                            // 设置字典编码为 null
                            data.setDictCode(null);
                            data.setTenantId(tenantId);
                            data.setCreateTime(null);
                            data.setUpdateTime(null);
//                            data.setCreateDept(null);
                            data.setCreateBy(null);
                            data.setUpdateBy(null);
                            set.add(tenantId);
                            saveDataList.add(data);
                        }
                    }
                }
            }
        }
        TenantHelper.ignore(() -> {
            if (CollUtil.isNotEmpty(saveTypeList)) {
                dictTypeMapper.insertBatch(saveTypeList);
            }
            if (CollUtil.isNotEmpty(saveDataList)) {
                dictDataMapper.insertBatch(saveDataList);
            }
        });
        for (String tenantId : set) {
            TenantHelper.dynamic(tenantId, () -> CacheUtils.clear(CacheNames.SYS_DICT));
        }
    }

    @Override
    public IPage<TenantDTO> getlist(Page<SysTenant> page, SysTenantExtendBo query) {
        SysTenantVo sysTenantVo = queryByTenantId(TenantHelper.getTenantId());
        query.setOneParentId(sysTenantVo.getId());
        IPage<TenantDTO> resultPage = baseMapper.getlist(page,query);
        return  resultPage;
    }

    @Override
    public List<TenantDTO> getAll(SysTenantBo bo) {
        return baseMapper.getAll(bo);
    }

    @Override
    public TenantDTO getById(Long id) {
        return baseMapper.getById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchRemoveByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new ServiceException("删除ID列表不能为空");
        }

        // 查询所有待删除租户的tenant_id
        List<SysTenant> tenants = baseMapper.selectBatchIds(ids);
        if (CollectionUtils.isEmpty(tenants)) {
            throw new ServiceException("未找到对应的租户信息");
        }

        // 检查是否存在不允许删除的租户
        for (SysTenant tenant : tenants) {
            if (TenantConstants.DEFAULT_TENANT_ID.equals(tenant.getTenantId())) {
                throw new ServiceException("超级管理员租户(" + tenant.getTenantId() + ")不能删除");
            }
            if (TenantConstants.SUPER_ADMIN_ROLE_KEY.equals(tenant.getId().toString())) {
                throw new ServiceException("超级管理员租户(" + tenant.getId() + ")不能删除");
            }
        }

        int extendDeleteCount = baseMapper.batchDeleteTenantExtendByStoreIds(ids);
        int tenantDeleteCount = baseMapper.batchDeleteTenantByIds(ids);

        return extendDeleteCount >= 0 && tenantDeleteCount >= 0;
    }

    @Override
    public int submitSign(String tenantId) {
        SysTenantExtend tenantExtend = tenantExtendMapper.selectByTenantId(tenantId);
        Assert.notNull(tenantExtend, () -> new ServiceException("无效的租户信息"));
        Assert.isTrue(TenantSignStatus.TO_BE_SUBMITTED.getStatus().equals(tenantExtend.getSignStatus()), () -> new ServiceException("当前状态不可提交签约"));
        SysTenantExtend updateTenantExtend = new SysTenantExtend();
        updateTenantExtend.setId(tenantExtend.getId());
        updateTenantExtend.setSignStatus(TenantSignStatus.TO_BE_REVIEWED.getStatus());
        updateTenantExtend.setFailureReason("");
        return tenantExtendMapper.updateById(updateTenantExtend);
    }

    @Override
    public void reviewSubmitted(SysTenantReviewBo bo) {
        SysTenantExtend tenantExtend = tenantExtendMapper.selectByTenantId(bo.getTenantId());
        Assert.notNull(tenantExtend, () -> new ServiceException("无效的租户信息"));
        Assert.isTrue(TenantSignStatus.TO_BE_REVIEWED.getStatus().equals(tenantExtend.getSignStatus()), () -> new ServiceException("当前状态不可审核"));
        Boolean isPass = bo.getIsPass();
        Assert.isTrue(isPass || StrUtil.isNotBlank(bo.getFailureReason()), () -> new ServiceException("请填写审核未通过原因"));
        SysTenantExtend updateTenantExtend = new SysTenantExtend();
        updateTenantExtend.setId(tenantExtend.getId());
        if (isPass) {
            updateTenantExtend.setSignStatus(TenantSignStatus.TO_BE_CONFIRMED.getStatus());
        }else{
            updateTenantExtend.setSignStatus(TenantSignStatus.TO_BE_SUBMITTED.getStatus());
            updateTenantExtend.setFailureReason(bo.getFailureReason());
        }
        tenantExtendMapper.updateById(updateTenantExtend);
    }

    @Override
    public void confirmedSign(String tenantId) {
        SysTenantExtend tenantExtend = tenantExtendMapper.selectByTenantId(tenantId);
        Assert.notNull(tenantExtend, () -> new ServiceException("无效的租户信息"));
        Assert.isTrue(TenantSignStatus.TO_BE_CONFIRMED.getStatus().equals(tenantExtend.getSignStatus()), () -> new ServiceException("未审核通过的签约不可确认"));
        SysTenantExtend updateTenantExtend = new SysTenantExtend();
        updateTenantExtend.setId(tenantExtend.getId());
        updateTenantExtend.setSignStatus(TenantSignStatus.IN_EFFECT.getStatus());
        tenantExtendMapper.updateById(updateTenantExtend);
    }

    @Override
    public SysTenant queryByDeptId(Long deptId) {
        return baseMapper.queryByDeptId(deptId);
    }

    @Override
    public List<SysTenantVo> getByParentId(Long id) {
        return this.queryList(SysTenantBo.builder().oneParentId(id).status("0").build());
    }

    @Override
    public SysTenantExtendBo convert(SysReferenceBo sysReferenceBo) {
        SysTenantExtendBo sysTenantExtendBo = BeanUtil.copyProperties(sysReferenceBo, SysTenantExtendBo.class);
        sysTenantExtendBo.setType(TenantType.REFERENCE.getType());
        return sysTenantExtendBo;
    }

    @Override
    public IPage<SysReferenceVO> getReferenceList(SysReferenceBo query) {
        SysTenantVo sysTenantVo = queryByTenantId(TenantHelper.getTenantId());
        query.setOneParentId(sysTenantVo.getId());
        IPage<SysReferenceVO> resultPage = baseMapper.getReferenceList(Page.of(query.getCurrent(), query.getSize()),query);
        return  resultPage;
    }

}
