package com.starry.admin.modules.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
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.starry.admin.common.domain.LoginUser;
import com.starry.admin.common.exception.CustomException;
import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService;
import com.starry.admin.modules.custom.service.IPlayCustomLevelInfoService;
import com.starry.admin.modules.shop.service.IPlayCommodityInfoService;
import com.starry.admin.modules.system.mapper.*;
import com.starry.admin.modules.system.module.entity.*;
import com.starry.admin.modules.system.service.ISysTenantService;
import com.starry.admin.modules.system.service.SysRoleMenuService;
import com.starry.admin.modules.system.vo.SysTenantQueryVo;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.constant.CacheConstants;
import com.starry.common.redis.RedisCache;
import com.starry.common.result.R;
import com.starry.common.utils.IdUtils;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.dnspod.v20210323.DnspodClient;
import com.tencentcloudapi.dnspod.v20210323.models.CreateRecordRequest;
import com.tencentcloudapi.dnspod.v20210323.models.CreateRecordResponse;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 租户表Service业务层处理
 *
 * @author admin
 * @since 2023-03-03
 */
@Slf4j
@Service
public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenantEntity> implements ISysTenantService {
    @Resource
    private SysTenantMapper sysTenantMapper;
    @Resource
    private SysTenantPackageMapper tenantPackageMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private SysDeptMapper deptMapper;
    @Resource
    private SysRoleMapper roleMapper;
    @Resource
    private SysRoleMenuService roleMenuService;
    @Resource
    private SysUserRoleMapper userRoleMapper;
    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;
    @Resource
    private RedisCache redisCache;

    @Resource
    private IPlayCustomLevelInfoService playCustomLevelInfoService;

    @Resource
    private IPlayClerkLevelInfoService playClerkLevelInfoService;

    @Resource
    private IPlayCommodityInfoService playCommodityInfoService;

    @Override
    public List<SysTenantEntity> listAll() {
        return this.baseMapper.selectList(new LambdaQueryWrapper<>());
    }

    @Override
    public SysTenantEntity selectByTenantKey(String tenantKey) {
        LambdaQueryWrapper<SysTenantEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysTenantEntity::getTenantKey, tenantKey);
        SysTenantEntity tenant = this.baseMapper.selectOne(lambdaQueryWrapper);
        if (Objects.isNull(tenant)) {
            throw new RuntimeException("租户信息异常");
        }
        if (DateUtil.compare(tenant.getTenantTime(), new Date()) < 0) {
            throw new RuntimeException("当前租户已过期，无法继续使用");
        }
        if ("1".equals(tenant.getTenantStatus())) {
            throw new RuntimeException("当前租户已被禁用");
        }
        return tenant;
    }

    /**
     * 查询租户表
     *
     * @param tenantId
     *            租户表主键
     * @return 租户表
     */
    @Override
    public SysTenantEntity selectSysTenantByTenantId(String tenantId) {
        SysTenantEntity entity = this.baseMapper.selectById(tenantId);
        if (entity == null) {
            throw new CustomException("租户对象为空");
        }
        return entity;
    }

    /**
     * 查询租户表列表
     *
     * @param vo
     *            租户表
     * @return 租户表
     */
    @Override
    public IPage<SysTenantEntity> selectSysTenantList(SysTenantQueryVo vo) {
        LambdaQueryWrapper<SysTenantEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(SysTenantEntity::getCreatedTime);

        if (StrUtil.isNotBlank(vo.getTenantName())) {
            wrapper.like(SysTenantEntity::getTenantName, vo.getTenantName());
        }
        // if (StrUtil.isNotBlank(vo.getBeginTime())) {
        // wrapper.ge(SysTenantEntity::getTenantTime, vo.getBeginTime());
        // }
        // if (StrUtil.isNotBlank(vo.getEndTime())) {
        // wrapper.le(SysTenantEntity::getTenantTime, vo.getEndTime());
        // }
        return this.baseMapper.selectPage(new Page<>(vo.getPageNum(), vo.getPageSize()), wrapper);
    }

    /**
     * 新增租户表
     *
     * @param sysTenantEntity
     *            租户表
     * @return 结果
     */
    @Override
    public boolean create(SysTenantEntity sysTenantEntity) {
        return save(sysTenantEntity);
    }

    /**
     * 修改租户表
     *
     * @param sysTenantEntity
     *            租户表
     * @return 结果
     */
    @Override
    public boolean update(SysTenantEntity sysTenantEntity) {
        return updateById(sysTenantEntity);
    }

    /**
     * 批量删除租户表
     *
     * @param tenantIds
     *            需要删除的租户表主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteSysTenantByTenantIds(String[] tenantIds) {
        int num = sysTenantMapper.deleteTenantByIds(tenantIds);
        if (num > 0) {
            // 下面才会进行子模块数据的删除
            // 部门模块
            deptMapper.deleteDeptByTenantId(tenantIds);
            // 权限
            roleMapper.deleteRoleByTenantId(tenantIds);
            sysRoleMenuMapper.deleteRoleMenuByTenantIds(tenantIds);
            // 账号
            sysUserMapper.deleteUserByTenantId(tenantIds);
            userRoleMapper.deleteUserRoleByTenantId(tenantIds);
        } else {
            throw new RuntimeException("当前租户已被删除不存在！");
        }
        return 1;
    }

    /**
     * 删除租户表信息
     *
     * @param tenantId
     *            租户表主键
     * @return 结果
     */
    @Override
    public int deleteSysTenantByTenantId(Long tenantId) {
        return sysTenantMapper.deleteById(tenantId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public R addTenant(SysTenantEntity sysTenantEntity) {
        // 判断账号是否存在
        if (sysUserMapper.checkUserNameUnique(sysTenantEntity.getUserName()) > 0) {
            return R.error("管理员账号已存在,请重新设置!");
        }
        if (sysTenantEntity.getProfitsharingRate() < 0 || sysTenantEntity.getProfitsharingRate() > 30) {
            throw new RuntimeException("分账抽成参数不得小于0，不得大于30");
        }
        if (StrUtil.isBlankIfStr(sysTenantEntity.getTenantId())) {
            sysTenantEntity.setTenantId(IdUtils.getUuid());
        }
        if (StrUtil.isBlankIfStr(sysTenantEntity.getTenantCode())) {
            sysTenantEntity.setTenantCode(IdUtils.getUuid());
        }
        // 生成随机key，用来生成域名，关键！
        sysTenantEntity.setTenantKey(RandomUtil.randomString(8).toLowerCase());
        // 创建租户
        sysTenantEntity.setCreatedTime(new Date());
        sysTenantMapper.insert(sysTenantEntity);
        // 创建默认账号
        createUser(sysTenantEntity);
        // 创建域名
        this.createDomainAndDns(sysTenantEntity.getTenantKey());
        this.initRole(sysTenantEntity);
        // 初始化店铺等级数据和用户等级数据
        playCustomLevelInfoService.initDefaultLevel(sysTenantEntity);
        playClerkLevelInfoService.initDefaultLevel(sysTenantEntity);
        // 初始化店铺服务信息
        playCommodityInfoService.initPlayCommodityInfo(sysTenantEntity.getTenantId());
        return R.ok("租户创建成功!");
    }

    /**
     * 目前为单套餐,跟租户绑定,解耦防止套餐变动影响多个租户
     **/
    private void createRoleMenu(SysTenantEntity sysTenantEntity, SysRoleEntity role) {
        SysTenantPackageEntity sysTenantPackage = tenantPackageMapper.selectById(sysTenantEntity.getPackageId());
        List<String> subMeuns = Arrays.asList(sysTenantPackage.getMenuIds().split(","));

        List<SysRoleMenuEntity> roleMenuList = subMeuns.stream().map(menuid -> {
            SysRoleMenuEntity entity = new SysRoleMenuEntity();
            entity.setRoleId(role.getRoleId());
            entity.setMenuId(Long.valueOf(menuid));
            entity.setTenantId(sysTenantEntity.getTenantId());
            return entity;
        }).collect(Collectors.toList());
        roleMenuService.saveBatch(roleMenuList);
    }

    private void createUser(SysTenantEntity sysTenant) {
        SysUserEntity user = new SysUserEntity();
        user.setUserCode(sysTenant.getUserName());
        user.setRealName(sysTenant.getTenantName());
        user.setUserNickname(sysTenant.getTenantName());
        user.setUserType(1);
        user.setUserEmail(sysTenant.getEmail());
        user.setMobile(sysTenant.getPhone());
        user.setCreatedTime(new Date());
        String password = SecurityUtils.encryptPassword(sysTenant.getUserPwd());
        user.setPassWord(password);
        user.setTenantId(sysTenant.getTenantId());
        user.setUserId(IdUtils.getUuid());
        user.setSuperAdmin(true);
        sysUserMapper.insert(user);

        SysUserEntity superUser = new SysUserEntity();
        superUser.setUserCode("sysadmin");
        superUser.setRealName("超级管理员");
        superUser.setUserNickname("超级管理员");
        superUser.setUserType(1);
        superUser.setMobile("0000");
        superUser.setCreatedTime(new Date());
        superUser.setPassWord(SecurityUtils.encryptPassword("123456"));
        superUser.setTenantId(sysTenant.getTenantId());
        superUser.setUserId(IdUtils.getUuid());
        superUser.setSuperAdmin(true);
        sysUserMapper.insert(superUser);
        // createUserRole(sysTenant.getTenantId(), user.getUserId(), roleId);
    }

    @Override
    public R updateTenant(SysTenantEntity sysTenantEntity) {
        // 判断最新的租户套餐是否改变 重新授权 租户二级管理员账号需重新分配三级账号权限
        SysTenantEntity newTenant = sysTenantMapper.selectById(sysTenantEntity.getTenantId());
        if (sysTenantEntity.getPackageId() != null
                && !sysTenantEntity.getPackageId().equals(newTenant.getPackageId())) {
            List<SysRoleEntity> roleList = roleMapper.queryAdminRole(sysTenantEntity.getTenantId());
            // 正常逻辑下每个租户只有一个二级管理员账号
            SysRoleEntity tRole = roleList.get(0);
            if (tRole != null) {
                // 删除原租户下所有的角色-菜单信息
                sysRoleMenuMapper.deleteRoleMenuByTenantId(sysTenantEntity.getTenantId());
                // 新增默认角色-菜单信息
                createRoleMenu(sysTenantEntity, tRole);
                // 原登录租户账号退出重登
                Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
                if (CollectionUtil.isNotEmpty(keys)) {
                    for (String key : keys) {
                        LoginUser onlineUser = redisCache.getCacheObject(key);
                        if (onlineUser.getUser().getTenantId() != null
                                && onlineUser.getUser().getTenantId().equals(sysTenantEntity.getTenantId())) {
                            redisCache.deleteObject(key);
                        }
                    }
                }
            }
        }
        sysTenantMapper.updateById(sysTenantEntity);
        return R.ok();
    }

    @Override
    public List<SysTenantEntity> queryByPackage(String packageId) {
        LambdaQueryWrapper<SysTenantEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysTenantEntity::getTenantId, packageId);
        return this.baseMapper.selectList(queryWrapper);
    }

    public void createDomainAndDns(String tenentKey) {
        Credential cred = new Credential("AKIDxypW8arxqY5ThleNyTtAFUYWM0ShnjSC", "kMo3RhnjV6XowxqaNN9mCTbYP8iDVdWG");
        DnspodClient dnspodClient = new DnspodClient(cred, "");
        CreateRecordRequest req = new CreateRecordRequest();
        req.setDomain("julyharbor.com");
        req.setRecordType("A");
        req.setRecordLine("默认");
        req.setValue("122.51.20.105");
        req.setSubDomain(tenentKey);
        CreateRecordResponse createRecordResponse;
        try {
            createRecordResponse = dnspodClient.CreateRecord(req);
        } catch (TencentCloudSDKException e) {
            throw new RuntimeException(e);
        }
        log.info("腾讯云域名映射结果：{}", JSONObject.toJSONString(createRecordResponse));
    }

    @Override
    public void initRole(SysTenantEntity sysTenantEntity) {

        SysRoleEntity operator = new SysRoleEntity();
        operator.setRoleName("管理员");
        operator.setRoleKey("operator");
        operator.setDescription("管理员角色系统默认创建");
        operator.setDataScope("1");
        operator.setMenuCheckStrictly(true);
        operator.setDeptCheckStrictly(true);
        operator.setTenantId(sysTenantEntity.getTenantId());
        roleMapper.insert(operator);

        SysTenantPackageEntity sysTenantPackage = tenantPackageMapper.selectById(sysTenantEntity.getPackageId());
        List<String> subMeuns = new ArrayList<>(Arrays.asList(sysTenantPackage.getMenuIds().split(",")));
        if (CollectionUtil.isEmpty(subMeuns)) {
            subMeuns = new ArrayList<>();
        }
        subMeuns.remove("2089");
        subMeuns.remove("2088");
        subMeuns.remove("2093");
        subMeuns.remove("6");
        List<SysRoleMenuEntity> roleMenuEntityList = subMeuns.stream().map(menu -> {
            SysRoleMenuEntity rm = new SysRoleMenuEntity();
            rm.setRoleId(operator.getRoleId());
            rm.setMenuId(Long.valueOf(menu));
            return rm;
        }).collect(Collectors.toList());
        roleMenuService.saveBatch(roleMenuEntityList);

        SysRoleEntity waiter = new SysRoleEntity();
        waiter.setRoleName("客服");
        waiter.setRoleKey("waiter");
        waiter.setDataScope("1");
        waiter.setDescription("客服角色系统默认创建");
        waiter.setMenuCheckStrictly(true);
        waiter.setDeptCheckStrictly(true);
        waiter.setTenantId(sysTenantEntity.getTenantId());
        roleMapper.insert(waiter);

        List<Integer> waiterMenuIdList = Arrays.asList(102, 1100, 1101, 1103, 1104, 1105);
        List<SysRoleMenuEntity> waiterMenuList = waiterMenuIdList.stream().map(menu -> {
            SysRoleMenuEntity rm = new SysRoleMenuEntity();
            rm.setRoleId(waiter.getRoleId());
            rm.setMenuId(Long.valueOf(menu));
            return rm;
        }).collect(Collectors.toList());
        roleMenuService.saveBatch(waiterMenuList);

        SysRoleEntity leader = new SysRoleEntity();
        leader.setRoleName("组长");
        leader.setRoleKey("leader");
        leader.setDescription("组长角色系统默认创建");
        leader.setDataScope("3");
        leader.setMenuCheckStrictly(true);
        leader.setDeptCheckStrictly(true);
        leader.setTenantId(sysTenantEntity.getTenantId());
        roleMapper.insert(leader);

        List<Integer> leaderMenuIdList = Arrays.asList(101, 102, 1000, 2095, 2096, 2097, 2087, 1001, 1100, 1101, 105,
                2094);
        List<SysRoleMenuEntity> leaderMenuList = leaderMenuIdList.stream().map(menu -> {
            SysRoleMenuEntity rm = new SysRoleMenuEntity();
            rm.setRoleId(leader.getRoleId());
            rm.setMenuId(Long.valueOf(menu));
            return rm;
        }).collect(Collectors.toList());
        roleMenuService.saveBatch(leaderMenuList);

    }
}
