package com.tuoheng.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tuoheng.common.CommonConfig;
import com.tuoheng.common.ServiceException;
import com.tuoheng.common.ServiceExceptionEnum;
import com.tuoheng.constant.CommonConstant;
import com.tuoheng.constant.DictConstant;
import com.tuoheng.enums.MarkTypeEnum;
import com.tuoheng.mapper.*;
import com.tuoheng.model.dto.LoginUser;
import com.tuoheng.model.dto.Platform;
import com.tuoheng.model.entity.DictData;
import com.tuoheng.model.entity.TenantEmploy;
import com.tuoheng.model.entity.TenantItem;
import com.tuoheng.model.param.ClientRoleDto;
import com.tuoheng.model.param.CreateClientTenantDto;
import com.tuoheng.model.param.CreateClientUserDto;
import com.tuoheng.model.po.AuthoritiesPo;
import com.tuoheng.model.po.ClientUserRolePo;
import com.tuoheng.model.po.TenantPo;
import com.tuoheng.model.po.UserPo;
import com.tuoheng.model.query.TenantQuery;
import com.tuoheng.model.query.UserQuery;
import com.tuoheng.model.vo.BusinessSystemVo;
import com.tuoheng.model.vo.CreateTenantVo;
import com.tuoheng.model.vo.TenantVo;
import com.tuoheng.model.vo.UserVo;
import com.tuoheng.service.TenantService;
import com.tuoheng.third.service.impl.ThirdServiceImpl;
import com.tuoheng.until.JacksonUtil;
import com.tuoheng.until.JsonResult;
import com.tuoheng.until.MapUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author xiaoying
 * @Date 2023/3/6 11:26
 */
@Service
@Slf4j
public class TenantServiceImpl implements TenantService {

    //默认密码
    private static final String passward = "thjs2023";
    @Autowired
    private ClientUserMapper clientUserMapper;

    @Autowired
    private TenantMapper tenantMapper;

    @Autowired
    private AuthoritiesMapper authoritiesMapper;

    @Autowired
    private ClientUserRoleMapper clientUserRoleMapper;

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private ThirdServiceImpl thirdService;

    @Autowired
    private PlatformMapper platformMapper;

    @Autowired
    private TenantEmployMapper tenantEmployMapper;

    @Autowired
    private TenantItemMapper tenantItemMapper;
    @Autowired
    private DictDataMapper dictDataMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult createClientTenant(CreateClientTenantDto createClientTenantDto, LoginUser loginUser) {
        if (clientUserMapper.judgeCreateByUserName(createClientTenantDto.getUsername()) > 0) {
            return JsonResult.error("该用户账号已存在！");
        }
        //新增校验
        for (ClientRoleDto clientRoleDto : createClientTenantDto.getClientRoleDtoList()) {
            if (ObjectUtil.isEmpty(clientRoleDto.getClientId()) || ObjectUtil.isNull(clientRoleDto.getRoleId())) {
                return JsonResult.error("业务系统关联相关角色id或者标识不能为空");
            }
        }
        createClientTenantDto.setPassword(passward);
        //创建租户创建成功后的返回实体类
        CreateTenantVo vo = new CreateTenantVo();
        vo.setPassword(createClientTenantDto.getPassword());
        vo.setTenantName(createClientTenantDto.getTenantName());
        vo.setUsername(createClientTenantDto.getUsername());
        //code复用username
        createClientTenantDto.setTenantCode(createClientTenantDto.getUsername());
        //用户表
        UserPo userPo = new UserPo()
                .setIsTenant(1)
                .setUsername(createClientTenantDto.getUsername())
                .setPassword("{bcrypt}" + new BCryptPasswordEncoder().encode(createClientTenantDto.getPassword()));
        userPo.setCreateUser(loginUser.getUserId());
        clientUserMapper.insertClientUser(userPo);
        log.info("用户表添加完毕");
        //调用高德将地址转换经纬度
        Map<String, String> lonAndLat = MapUtils.getLonAndLat(createClientTenantDto.getAdress(), CommonConfig.gaodeKey);
        //租户表
        TenantPo tenantPo = new TenantPo();
        BeanUtils.copyProperties(createClientTenantDto, tenantPo);
        tenantPo.setName(createClientTenantDto.getTenantName())
                .setCode(createClientTenantDto.getTenantCode())
                .setUserId(userPo.getId())
                //获取经纬度更新
                .setLat(lonAndLat.get("lat").toString())
                .setLng(lonAndLat.get("lng").toString());
        tenantMapper.insertTenant(tenantPo);
        log.info("租户表添加完毕");
        //添加租户对应项目详细信息表
        TenantItem tenantItem = createClientTenantDto.getTenantItem();
        tenantItem.setTenantId(tenantPo.getId());
        tenantItemMapper.insert(tenantItem);
        //设置系统有效期
        vo.setEffectiveDate(DateUtil.formatDate(tenantItem.getBeginTime()) + CommonConstant.TILDE + DateUtil.formatDate(tenantItem.getEndTime()));
        log.info("租户项目表添加完毕");

        StringBuilder PlatformName = new StringBuilder();
        log.info(JSONUtil.toJsonStr(createClientTenantDto.getClientRoleDtoList()));
        for (ClientRoleDto clientRoleDto : createClientTenantDto.getClientRoleDtoList()) {
            //获取clientId查询对应平台获取平台名称
            Platform platform = platformMapper.selectOne(Wrappers.<Platform>lambdaQuery()
                    .eq(Platform::getPlatformCode, clientRoleDto.getClientId())
                    .eq(Platform::getMark, 1));
            if (ObjectUtil.isNull(platform)) {
                return JsonResult.error("该业务平台不存在");
            }
            //添加相关对应
            PlatformName.append(platform.getPlatformName());
            PlatformName.append(CommonConstant.SIGN);
            //添加租户对应服务的相关表数据
            TenantEmploy tenantEmploy = new TenantEmploy();
            tenantEmploy.setTenantId(tenantPo.getId());
            tenantEmploy.setPlatformCode(platform.getPlatformCode());
            if (ObjectUtil.isNotEmpty(clientRoleDto.getServiceId())) {
                tenantEmploy.setServiceId(clientRoleDto.getServiceId());
            }
            log.info(JSONUtil.toJsonStr(tenantEmploy));
            tenantEmployMapper.insert(tenantEmploy);
        }
        //拼接
        vo.setPlatformName(PlatformName.substring(CommonConstant.ZERO, PlatformName.lastIndexOf(CommonConstant.SIGN)));
        log.info("租户实例表添加完毕");
        //1.开始判断租户对应需要的平台并进行匹对
        List<ClientRoleDto> clientRoleDtoList = getClientRoleDtos(createClientTenantDto.getClientRoleDtoList());
        List<AuthoritiesPo> authoritiesPos = new ArrayList<>();
        List<ClientUserRolePo> clientUserRolePoArrayList = new ArrayList<>();
        //2.添加租户对应相关信息
        log.info("开始创建对应各个业务平台的表");
        for (ClientRoleDto clientRoleDto : clientRoleDtoList) {
            //添加角色权限相关
            AuthoritiesPo authoritiesPo = new AuthoritiesPo()
                    .setUserId(userPo.getId())
                    .setUsername(createClientTenantDto.getUsername())
                    .setAuthority(clientRoleDto.getClientId());
            authoritiesPo.setCreateUser(loginUser.getUserId());
            authoritiesPos.add(authoritiesPo);

            ClientUserRolePo clientUserRolePo = new ClientUserRolePo()
                    .setUserId(userPo.getId())
                    .setClientId(clientRoleDto.getClientId())
                    .setRoleId(clientRoleDto.getRoleId())
                    .setRoleName(clientRoleDto.getRoleName());
            clientUserRolePo.setCreateUser(loginUser.getUserId());
            clientUserRolePoArrayList.add(clientUserRolePo);
        }
        authoritiesMapper.batchInsert(authoritiesPos);
        clientUserRoleMapper.batchInsert(clientUserRolePoArrayList);
        //todo:调用业务系统完成租户创建
        List<ClientRoleDto> list = createClientTenantDto.getClientRoleDtoList();

        list = thirdService.getModelList(list);
        createClientTenantDto.setClientRoleDtoList(list);
        for (ClientRoleDto clientRoleDto : list) {
            try {
                log.info("参数:{}", JacksonUtil.obj2json(clientRoleDto));
                JsonResult result = getResult(createClientTenantDto, clientRoleDto.getClientId(), DictConstant.ADD_TENANT, loginUser);
                if (JsonResult.SUCCESS != result.getCode()) {
                    throw new ServiceException(HttpStatus.BAD_REQUEST.value(), result.getMsg());
                }
            } catch (Exception e) {
                //e.printStackTrace();
                //事务并不会回滚
                log.info("异常信息捕获,平台标识:{}", clientRoleDto.getClientId());
                log.info("异常信息:{}", e.getMessage());
            }
        }
        log.info("业务系统完成创建");
        return JsonResult.success(vo);
    }

    /**
     * 匹配对应业务系统对应的标识,并封装返回方便后续操作
     *
     * @param clientRoleDtoList
     * @return
     */
    private List<ClientRoleDto> getClientRoleDtos(List<ClientRoleDto> clientRoleDtoList) {
        List<ClientRoleDto> list = new ArrayList<>();
        //遍历获取参数进项封装
        for (ClientRoleDto dto : clientRoleDtoList) {

            List<DictData> dictDataList = dictDataMapper.selectList(Wrappers.<DictData>lambdaQuery()
                    .eq(DictData::getMark, MarkTypeEnum.VALID.getCode()).eq(DictData::getCode, DictConstant.CLIENT));
            for (DictData dictData : dictDataList) {
                if (dto.getClientId().equals(dictData.getValue())) {
                    addClientRoleDtoList(getDictData(dictData.getDictType(), DictConstant.MP).getValue(), dto, list);
                    addClientRoleDtoList(getDictData(dictData.getDictType(), DictConstant.ADMIN).getValue(), dto, list);
                }
            }
        }
        return list;
    }

    /**
     * 封装数据到 clientRoleDtoList
     *
     * @param clientId
     * @param dto
     * @param clientRoleDtoList
     */
    private void addClientRoleDtoList(String clientId, ClientRoleDto dto, List<ClientRoleDto> clientRoleDtoList) {
        ClientRoleDto clientRoleDto = new ClientRoleDto();
        clientRoleDto.setClientId(clientId);
        clientRoleDto.setRoleId(dto.getRoleId());
        clientRoleDto.setRoleName(dto.getRoleName());
        clientRoleDtoList.add(clientRoleDto);
    }

    /**
     * 查询对应租户下的所有用户数据
     *
     * @param query
     * @return
     */
    @Override
    public JsonResult findUserList(UserQuery query) {

        //分页参数校验
        query.checkParam();
        //开启分页
        IPage<UserPo> page = new Page<>(query.getPage(), query.getLimit());
        IPage<UserVo> pageData = clientUserMapper.selectByTenantIdAndPage(query, page);
        pageData.convert(x -> {
            String platformCode = x.getPlatformCode();
            //TODO 后期维护各个业务平台
            List<DictData> dictDataList = dictDataMapper.selectList(Wrappers.<DictData>lambdaQuery()
                    .eq(DictData::getMark, MarkTypeEnum.VALID.getCode()).eq(DictData::getCode, DictConstant.CLIENT));
            for (DictData dictData : dictDataList) {
                if (platformCode.contains(dictData.getValue())) {
                    //获取对应平台
                    x.setPlatformName(getDictData(dictData.getDictType(), DictConstant.GET_NAME).getValue());
                }
            }
            return x;
        });
        return JsonResult.success(pageData);
    }

    /**
     * 更新 用户/租户对应关系的系统or角色id
     *
     * @param createClientUserDto
     * @param loginUser
     * @return
     */
    @Override
    public JsonResult updateAuthorities(CreateClientUserDto createClientUserDto, LoginUser loginUser) {

        UserPo userPo = clientUserMapper.getUserByUserName(createClientUserDto.getUsername());
        if (ObjectUtil.isNull(userPo)) {
            return JsonResult.error("此用户不存在");
        }
        List<AuthoritiesPo> authoritiesPos = new ArrayList<>();
        List<ClientUserRolePo> clientUserRolePoArrayList = new ArrayList<>();
        for (ClientRoleDto clientRoleDto : createClientUserDto.getClientRoleDtoList()) {
            AuthoritiesPo authoritiesPo = new AuthoritiesPo()
                    .setUserId(userPo.getId())
                    .setUsername(createClientUserDto.getUsername())
                    .setAuthority(clientRoleDto.getClientId());
            authoritiesPo.setCreateUser(loginUser.getUserId());
            authoritiesPos.add(authoritiesPo);

            ClientUserRolePo clientUserRolePo = new ClientUserRolePo()
                    .setUserId(userPo.getId())
                    .setClientId(clientRoleDto.getClientId())
                    .setRoleId(clientRoleDto.getRoleId());
            clientUserRolePo.setCreateUser(loginUser.getUserId());
            clientUserRolePoArrayList.add(clientUserRolePo);

        }
        authoritiesMapper.batchInsert(authoritiesPos);
        clientUserRoleMapper.batchInsert(clientUserRolePoArrayList);

        return JsonResult.success();
    }

    /**
     * 查询租户以及该租户对应绑定的系统等
     *
     * @return
     */
    @Override
    public JsonResult findTenants(TenantQuery query) {
        //分页参数校验
        query.checkParam();
        //开启分页
        List<TenantVo> tenantVos = tenantMapper.findList(query);
        if (CollectionUtil.isEmpty(tenantVos)) {
            return JsonResult.success(new Page<>(query.getPage(), query.getLimit()));
        }
        List<Platform> platforms = platformMapper.selectList(Wrappers.<Platform>lambdaQuery().eq(Platform::getMark, MarkTypeEnum.VALID.getCode()));
        //公共数据预热 ,避免循环中复杂查询导致接口响应时间过长
        Map<Long, TenantItem> tenantItemMap = getTenantItemMap(tenantVos);
        Map<String, Platform> platformMap = getPlatformMap(platforms);
        Map<Long, List<AuthoritiesPo>> authoritiesPoMap = getAuthoritiesPoMap(tenantVos, query.getClientId());
        List<DictData> dictDataList = dictDataMapper.selectList(Wrappers.<DictData>lambdaQuery()
                .eq(DictData::getMark, MarkTypeEnum.VALID.getCode()).eq(DictData::getCode, DictConstant.CLIENT));


        List<TenantVo> collect = tenantVos.stream().map(x -> {
            TenantVo vo = new TenantVo();
            BeanUtils.copyProperties(x, vo);
            //并不是真正意义上的租户id
            vo.setTenantId(x.getUserId());
            //TenantItem tenantItem = tenantItemMapper.selectOne(Wrappers.<TenantItem>lambdaQuery().eq(TenantItem::getTenantId, x.getId()));
            TenantItem tenantItem = tenantItemMap.get(x.getId());
            if (ObjectUtil.isNotNull(tenantItem)) {
                //获取有效期等
                vo.setEffectiveDate(DateUtil.formatDate(tenantItem.getBeginTime()) + CommonConstant.TILDE + DateUtil.formatDate(tenantItem.getEndTime()));
                Long day = null;
                //超过有效期则为flase
                //截止时间的凌晨
                DateTime endTime = DateUtil.endOfDay(tenantItem.getEndTime());
                DateTime beginTime = DateUtil.beginOfDay(tenantItem.getBeginTime());
                boolean flag = beginTime.after(DateUtil.date());
                boolean flag2 = endTime.after(DateUtil.date());
                if (!flag) {
                    day = getDay(DateUtil.date(), endTime);
                } else {
                    day = getDay(beginTime, endTime);
                }
                if (!flag2) {
                    day = 0L;
                }
                //获取剩余天数
                vo.setRemainDays(day);
            }
            //此处userId = tenantId 效果一致
            //List<AuthoritiesPo> poList = authoritiesMapper.selectListByUserIdAndClientId(x.getUserId(), query);
            List<AuthoritiesPo> poList = authoritiesPoMap.get(x.getUserId());
            if (ObjectUtil.isEmpty(poList)) {
                return null;
            }
            List<Long> userIdList = poList.stream().map(t -> t.getUserId()).distinct().collect(Collectors.toList());
            List<AuthoritiesPo> list = authoritiesMapper.selectByUserIds(userIdList);
            List<BusinessSystemVo> businessSystemVoList = new ArrayList<>();
            for (AuthoritiesPo authoritiesPo : list) {
                //TODO 后期维护各个业务平台
                for (DictData dictData : dictDataList) {
                    if (authoritiesPo.getAuthority().contains(dictData.getValue())) {
                        //获取对应平台
                        Platform platform = platformMap.get(dictData.getDictType());
                        businessSystemVoList.add(getbusinessSystemVo(dictData.getValue(), platform.getPlatformName()));
                    }
                }
            }
            businessSystemVoList = businessSystemVoList.stream().distinct().collect(Collectors.toList());
            vo.setList(businessSystemVoList);
            return vo;
        }).filter(x -> x != null).collect(Collectors.toList());
        //粗暴的分页
        Integer pageNum = query.getPage();
        Integer pageSize = query.getLimit();
        int startIndex = (pageNum - 1) * pageSize;
        int endIndex = Math.min(startIndex + pageSize, collect.size());
        List<TenantVo> subList = collect.subList(startIndex, endIndex);
        IPage<TenantVo> page = new Page<>(pageNum, pageSize);
        page.setTotal(collect.size());
        return JsonResult.success(page.setRecords(subList));
    }

    private Map<String, Platform> getPlatformMap(List<Platform> platforms) {
        return platforms.stream().collect(Collectors.toMap(Platform::getPlatformCode, Function.identity()));
    }

    /**
     * 提前获取数据 放到map，减少循环次数
     *
     * @param tenantVos
     * @return
     */
    private Map<Long, List<AuthoritiesPo>> getAuthoritiesPoMap(List<TenantVo> tenantVos, String clientId) {
        List<Long> collect = tenantVos.stream().map(TenantVo::getUserId).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(clientId)) {
            return authoritiesMapper.selectByUserIdsAndClient(collect, clientId)
                    .parallelStream().collect(Collectors.groupingBy(AuthoritiesPo::getUserId));
        } else {
            return authoritiesMapper.selectByUserIds(collect)
                    .parallelStream().collect(Collectors.groupingBy(AuthoritiesPo::getUserId));
        }
    }

    /**
     * 提前获取数据 放到map，减少循环次数
     *
     * @param tenantVos
     * @return
     */
    private Map<Long, TenantItem> getTenantItemMap(List<TenantVo> tenantVos) {
        List<Long> collect = tenantVos.stream().map(TenantVo::getId).collect(Collectors.toList());
        return tenantItemMapper.selectList(Wrappers.<TenantItem>lambdaQuery().in(TenantItem::getTenantId, collect))
                .stream().collect(Collectors.toMap(TenantItem::getTenantId, Function.identity()));
    }

    /**
     * 根据有效期变更剩余天数逻辑
     *
     * @param beginTime
     * @param endTime
     * @return
     */
    private Long getDay(DateTime beginTime, DateTime endTime) {
        Long day;
        day = DateUtil.between(beginTime, endTime, DateUnit.HOUR);
        BigDecimal divide = BigDecimal.valueOf(day).divide(new BigDecimal(24), CommonConstant.ZERO, RoundingMode.UP);
        day = divide.longValue();
        return day;
    }

    /**
     * 根据id查询出租户详情
     *
     * @param query
     * @return
     */
    @Override
    public JsonResult getDetaile(TenantQuery query) {

        if (ObjectUtil.isNull(query.getId())) {
            return JsonResult.error("租户id不能为空");
        }
        CreateClientTenantDto dto = new CreateClientTenantDto();
        dto.setId(query.getId());
        //默认是否包含机场为false
        //Boolean isAirport = false;
        //查询出租户的相关信息
        Long tenantId = query.getId();
        //项目相关信息
        TenantItem tenantItem = tenantItemMapper.selectOne(Wrappers.<TenantItem>lambdaQuery().eq(TenantItem::getTenantId, tenantId));
        dto.setTenantItem(tenantItem);
        //租户基本信息
        TenantPo tenantPo = tenantMapper.selectById(tenantId);
        BeanUtils.copyProperties(tenantPo, dto);
        dto.setTenantCode(tenantPo.getCode());
        dto.setTenantName(tenantPo.getName());
        UserPo userPo = clientUserMapper.selectByUserId(tenantPo.getUserId());
        dto.setUsername(Optional.ofNullable(userPo.getUsername()).orElseThrow(() -> new ServiceException(ServiceExceptionEnum.GET_NO_DATA)));
        //Optional.ofNullable(userPo.getUsername()).ifPresent(t -> dto.setUsername(t));
        //租户对应的业务平台相关信息
        List<ClientRoleDto> list = new ArrayList<>();
        List<ClientUserRolePo> clientUserRolePos = clientUserRoleMapper.selectListByUserId(tenantPo.getUserId());
        for (ClientUserRolePo clientUserRolePo : clientUserRolePos) {
            //判断是否包含机场
            //if ("tuoheng-airport-admin".equals(clientUserRolePo.getClientId())) {
            //    isAirport = true;
            //}
            ClientRoleDto clientRoleDto = new ClientRoleDto();
            //此处  暂时格式都为 tuoheng-hhz-web 等格式  如后续维护需要变更形式则此处代码需要更改
            clientRoleDto.setRoleId(clientUserRolePo.getRoleId());
            clientRoleDto.setRoleName(clientUserRolePo.getRoleName());
            clientRoleDto.setClientId(clientUserRolePo.getClientId().substring(CommonConstant.ZERO, clientUserRolePo.getClientId().lastIndexOf(CommonConstant.BARS)));
            TenantEmploy tenantEmploy = tenantEmployMapper.selectOne(Wrappers.<TenantEmploy>lambdaQuery()
                    .eq(TenantEmploy::getTenantId, tenantId)
                    .eq(TenantEmploy::getPlatformCode, clientRoleDto.getClientId()));
            if (ObjectUtil.isNotNull(tenantEmploy)) {
                clientRoleDto.setServiceId(tenantEmploy.getServiceId());
            }
            list.add(clientRoleDto);
        }
        dto.setClientRoleDtoList(list.stream().distinct().collect(Collectors.toList()));
        //dto.setIsAirport(isAirport);
        return JsonResult.success(dto);
    }

    /**
     * 重置密码
     *
     * @param dto
     * @param loginUser
     * @return
     */
    @Override
    public JsonResult resetPassward(CreateClientTenantDto dto, LoginUser loginUser) {
        if (ObjectUtil.isNull(dto.getId())) {
            return JsonResult.error("租户id不能为空");
        }
        TenantPo tenantPo = tenantMapper.selectById(dto.getId());
        UserPo userPo = clientUserMapper.selectByUserId(tenantPo.getUserId());
        userPo.setPassword("{bcrypt}" + new BCryptPasswordEncoder().encode(passward));
        clientUserMapper.updatePass(userPo);
        return JsonResult.success();
    }

    /**
     * 更新租户状态(1 启用 0禁用)
     *
     * @param dto
     * @param loginUser
     * @return
     */
    @Override
    public JsonResult updateStatus(CreateClientTenantDto dto, LoginUser loginUser) {

        if (ObjectUtil.isNull(dto.getId())) {
            return JsonResult.error("租户id不能为空");
        }
        TenantPo tenantPo = tenantMapper.selectById(dto.getId());

        if (CommonConstant.ONE.equals(dto.getStatus())) {
            //启用 ->判断当前需要启用的系统是否过了有效期
            TenantItem tenantItem = tenantItemMapper.selectOne(Wrappers.<TenantItem>lambdaQuery().eq(TenantItem::getTenantId, dto.getId()));
            //超过有效期则为flase
            boolean flag = tenantItem.getEndTime().after(DateUtil.date());
            //则不给启用
            if (!flag) {
                //有效期已过
                return JsonResult.error(ServiceExceptionEnum.EXPIRATION_DATE.getMessage());
            }
        }

        tenantPo.setStatus(CommonConstant.ZERO);
        tenantMapper.updateById(tenantPo);
        UserPo userPo = clientUserMapper.selectByUserId(tenantPo.getUserId());
        //1正常 0禁用
        userPo.setIsAble(dto.getStatus());
        clientUserMapper.updatePass(userPo);
        //租户更新完毕 更新对应租户下的用户
        List<UserPo> userPoList = clientUserMapper.selectByTenantId(userPo.getId());
        for (UserPo po : userPoList) {
            po.setIsExpire(dto.getStatus());
            clientUserMapper.updatePass(userPo);
        }
        return JsonResult.success();
    }


    /**
     * 封装返回展示类
     *
     * @param client
     * @param name
     * @return
     */
    private BusinessSystemVo getbusinessSystemVo(String client, String name) {
        BusinessSystemVo businessSystemVo = new BusinessSystemVo();
        businessSystemVo.setClientId(client);
        businessSystemVo.setName(name);
        return businessSystemVo;
    }

    /**
     * 删除租户(逻辑删除)
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult deleteTenant(CreateClientTenantDto dto, LoginUser loginUser) {
        //通知业务系统进行删除
        for (ClientRoleDto clientRoleDto : dto.getClientRoleDtoList()) {
            deleteResult(dto, clientRoleDto.getClientId(), DictConstant.DELETE_TENANT, loginUser);
        }
        return JsonResult.success();
    }

    /**
     * 更新业务平台租户的相关基本信息
     *
     * @param dto
     * @param loginUser
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult editTenant(CreateClientTenantDto dto, LoginUser loginUser) {

        dto.setTenantCode(dto.getUsername());
        //默认密码
        dto.setPassword(passward);
        TenantPo tenant = tenantMapper.selectById(dto.getId());
        if (ObjectUtil.isNull(tenant)) {
            return JsonResult.error(ServiceExceptionEnum.GET_NO_DATA.getMessage());
        }
        //现有list
        List<ClientRoleDto> list = dto.getClientRoleDtoList();
        if (CollectionUtil.isEmpty(list)) {
            return JsonResult.error("租户关联的业务平台系统不能为空");
        }
        //新增校验
        for (ClientRoleDto clientRoleDto : list) {
            if (ObjectUtil.isEmpty(clientRoleDto.getClientId()) || ObjectUtil.isNull(clientRoleDto.getRoleId())) {
                return JsonResult.error("业务系统关联相关角色id或者标识不能为空");
            }
        }

        log.info("现有集合:{}", list.toString());
        //现有集合
        List<ClientRoleDto> clientRoleDtos = getClientRoleDtos(list);
        //租户对应的业务平台相关信息
        //删除这个租户原本存在的所有业务平台下的信息
        List<ClientRoleDto> clientRoleDtoList = new ArrayList<>();
        List<ClientUserRolePo> clientUserRolePos = clientUserRoleMapper.selectListByUserId(tenant.getUserId());
        CreateClientTenantDto clientTenantDto = new CreateClientTenantDto();
        BeanUtils.copyProperties(dto, clientTenantDto);
        log.info(clientTenantDto.toString());
        for (ClientUserRolePo clientUserRolePo : clientUserRolePos) {
            ClientRoleDto clientRoleDto = new ClientRoleDto();
            TenantEmploy tenantEmploy = tenantEmployMapper.selectOne(Wrappers.<TenantEmploy>lambdaQuery()
                    .eq(TenantEmploy::getTenantId, dto.getId())
                    .eq(TenantEmploy::getPlatformCode, clientUserRolePo.getClientId().substring(CommonConstant.ZERO, clientUserRolePo.getClientId().lastIndexOf(CommonConstant.BARS))));
            if (ObjectUtil.isNotNull(tenantEmploy)) {
                clientRoleDto.setServiceId(tenantEmploy.getServiceId());
            }
            //此处  暂时格式都为 tuoheng-hhz-web 等格式  如后续维护需要变更形式则此处代码需要更改
            clientRoleDto.setRoleId(clientUserRolePo.getRoleId());
            clientRoleDto.setRoleName(clientUserRolePo.getRoleName());
            clientRoleDto.setClientId(clientUserRolePo.getClientId().substring(CommonConstant.ZERO, clientUserRolePo.getClientId().lastIndexOf(CommonConstant.BARS)));
            clientRoleDtoList.add(clientRoleDto);
        }
        //原有集合
        clientRoleDtoList = clientRoleDtoList.stream().distinct().collect(Collectors.toList());
        List<ClientRoleDto> deleteList = clientRoleDtoList;
        log.info("原有集合:{}", clientRoleDtoList.toString());
        //现有对比  拿出不需要的数据进行删除
        List<ClientRoleDto> deleteClientRoleDtoList;
        List<ClientRoleDto> insertClientRoleDtoList;
        List<ClientRoleDto> coincideClientRoleDtoList;
        deleteClientRoleDtoList = clientRoleDtoList.stream().filter(t -> !list.contains(t)).collect(Collectors.toList());
        coincideClientRoleDtoList = clientRoleDtoList.stream().filter(t -> list.contains(t)).collect(Collectors.toList());
        log.info("删除集合:{}", deleteClientRoleDtoList.toString());
        log.info("交集集合:{}", coincideClientRoleDtoList.toString());
        //新增集合
        insertClientRoleDtoList = list.stream().filter(t -> !deleteList.contains(t)).collect(Collectors.toList());
        log.info("新增集合:{}", insertClientRoleDtoList.toString());
        //交集集合做更新操作 editTenant
        clientTenantDto.setClientRoleDtoList(thirdService.getModelList(clientTenantDto.getClientRoleDtoList()));
        for (ClientRoleDto clientRoleDto : coincideClientRoleDtoList) {
            try {
                editResult(clientTenantDto, clientRoleDto.getClientId(), DictConstant.EDIT_TENANT, loginUser);
            } catch (Exception e) {
                log.info("异常信息捕获,平台标识:{}", clientRoleDto.getClientId());
                log.info("异常信息:{}", e.getMessage());
            }
        }
        if (CollectionUtil.isNotEmpty(deleteClientRoleDtoList)) {
            clientTenantDto.setClientRoleDtoList(deleteClientRoleDtoList);
            //符合先删后增逻辑 则直接将原有租户已经对应的关联业务数据清除
            JsonResult jsonResult = deleteTenant(clientTenantDto, loginUser);
            if (jsonResult.getCode() != JsonResult.SUCCESS) {
                return jsonResult;
            }
            //原有集合
            List<ClientRoleDto> finalClientRoleDtoList = getClientRoleDtos(deleteClientRoleDtoList);
            //筛选出一样的则不做相关操作
            //删除租户所有原始权限
            for (ClientRoleDto clientRoleDto : finalClientRoleDtoList) {
                clientUserRoleMapper.deleteByUserIdAndClient(tenant.getUserId(), clientRoleDto.getClientId());
                authoritiesMapper.deleteByUserIdAndClient(tenant.getUserId(), clientRoleDto.getClientId());
            }
            log.info("租户原有关联各业务平台不同权限表删除完毕");

        }
        //更新租户创建成功后的返回实体类
        CreateTenantVo vo = new CreateTenantVo();
        vo.setPassword(dto.getPassword());
        vo.setTenantName(dto.getTenantName());
        vo.setUsername(dto.getUsername());
        log.info("租户原始数据删除完毕");
        //删除原本租户关联的业务实例相关表
        List<TenantEmploy> tenantEmploys = tenantEmployMapper.selectList(Wrappers.<TenantEmploy>lambdaQuery()
                .eq(TenantEmploy::getTenantId, dto.getId()));
        tenantEmploys.forEach(t -> tenantEmployMapper.deleteById(t));
        //新增租户关联业务服务实例相关
        StringBuilder platformName = new StringBuilder();
        log.info(dto.getClientRoleDtoList().toString());
        for (ClientRoleDto clientRoleDto : list) {
            //获取clientId查询对应平台获取平台名称
            Platform platform = platformMapper.selectOne(Wrappers.<Platform>lambdaQuery()
                    .eq(Platform::getPlatformCode, clientRoleDto.getClientId())
                    .eq(Platform::getMark, 1));
            if (ObjectUtil.isNull(platform)) {
                return JsonResult.error("该业务平台不存在");
            }
            platformName.append(platform.getPlatformName());
            platformName.append(CommonConstant.SIGN);
            TenantEmploy tenantEmploy = new TenantEmploy();
            tenantEmploy.setTenantId(dto.getId());
            tenantEmploy.setPlatformCode(clientRoleDto.getClientId());
            if (ObjectUtil.isNotEmpty(clientRoleDto.getServiceId())) {
                tenantEmploy.setServiceId(clientRoleDto.getServiceId());
            }
            tenantEmployMapper.insert(tenantEmploy);
        }
        //拼接
        vo.setPlatformName(platformName.substring(CommonConstant.ZERO, platformName.lastIndexOf(CommonConstant.SIGN)));
        log.info("租户更新的业务服务实例表更新完毕");
        //更新租户原有数据基本
        BeanUtils.copyProperties(dto, tenant);
        tenant.setName(dto.getTenantName())
                .setCode(dto.getTenantCode());
        tenantMapper.updateById(tenant);
        log.info("租户基本信息更新完毕");
        TenantItem oldTenantItem = tenantItemMapper.selectOne(Wrappers.<TenantItem>lambdaQuery().eq(TenantItem::getTenantId, dto.getId()));
        TenantItem tenantItem = dto.getTenantItem();
        tenantItem.setId(oldTenantItem.getId());
        tenantItemMapper.updateById(tenantItem);
        vo.setEffectiveDate(DateUtil.formatDate(tenantItem.getBeginTime()) + CommonConstant.TILDE + DateUtil.formatDate(tenantItem.getEndTime()));
        log.info("租户项目相关信息更新完毕");

        if (CollectionUtil.isNotEmpty(insertClientRoleDtoList)) {
            //todo:调用业务系统完成租户创建
            dto.setClientRoleDtoList(thirdService.getModelList(dto.getClientRoleDtoList()));
            for (ClientRoleDto clientRoleDto : insertClientRoleDtoList) {
                try {
                    log.info("参数:{}", JacksonUtil.obj2json(clientRoleDto));
                    JsonResult result = getResult(dto, clientRoleDto.getClientId(), DictConstant.ADD_TENANT, loginUser);
                    if (JsonResult.SUCCESS != result.getCode()) {
                        throw new ServiceException(HttpStatus.BAD_REQUEST.value(), result.getMsg());
                    }
                } catch (Exception e) {
                    //e.printStackTrace();
                    //事务并不会回滚
                    log.info("异常信息捕获,平台标识:{}", clientRoleDto.getClientId());
                    log.info("异常信息:{}", e.getMessage());
                }
            }
            log.info("业务系统新增租户成功");

            //创建新的租户对应权限相关数据
            List<AuthoritiesPo> authoritiesPos = new ArrayList<>();
            List<ClientUserRolePo> clientUserRolePoArrayList = new ArrayList<>();
            insertClientRoleDtoList = getClientRoleDtos(insertClientRoleDtoList);
            for (ClientRoleDto clientRoleDto : insertClientRoleDtoList) {
                //添加角色权限相关
                AuthoritiesPo authoritiesPo = new AuthoritiesPo()
                        .setUserId(tenant.getUserId())
                        .setUsername(dto.getUsername())
                        .setAuthority(clientRoleDto.getClientId());
                authoritiesPo.setCreateUser(loginUser.getUserId());
                authoritiesPos.add(authoritiesPo);

                ClientUserRolePo clientUserRolePo = new ClientUserRolePo()
                        .setUserId(tenant.getUserId())
                        .setClientId(clientRoleDto.getClientId())
                        .setRoleId(clientRoleDto.getRoleId())
                        .setRoleName(clientRoleDto.getRoleName());
                clientUserRolePo.setCreateUser(loginUser.getUserId());
                clientUserRolePoArrayList.add(clientUserRolePo);
            }
            authoritiesMapper.batchInsert(authoritiesPos);
            clientUserRoleMapper.batchInsert(clientUserRolePoArrayList);
            log.info("对应业务系统的权限相关创建成功");
        }
        return JsonResult.success(vo);
    }

    /**
     * 新增请求
     *
     * @param dto
     * @param loginUser
     * @return
     */
    private JsonResult getResult(CreateClientTenantDto dto, String code, String dictCode, LoginUser loginUser) {
        //获取对应平台
        Platform platform = getPlatform(code);
        if (ObjectUtil.isNull(platform)) {
            return JsonResult.error("该业务平台不存在");
        }
        //设置请求头
        HttpHeaders resultRequestHeader = new HttpHeaders();
        resultRequestHeader.add("Authorization", "Bearer " + loginUser.getThToken());
        //设置地址
        String url = platform.getPlatformUrl();
        //根据不同业务平台进行动态匹配  ->并修改对应标识权限
        DictData dictData = getDictData(code, dictCode);
        if (ObjectUtil.isNull(dictData)) {
            return JsonResult.error("该业务平台对应字典表数据不存在");
        }
        url = url + dictData.getValue();
        HttpEntity httpEntity = new HttpEntity(dto, resultRequestHeader);
        log.info("请求url:{}", url);
        log.info("请求参数:{}", JacksonUtil.obj2json(dto));
        ResponseEntity<JsonResult> response;
        try {
            response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, JsonResult.class);
        } catch (Exception e) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "业务平台新增租户失败");
        }
        if (null == response || !response.hasBody()) {
            log.error("业务平台新增租户响应失败");
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "业务平台新增租户失败");
        }
        if (response.getBody().getCode() != JsonResult.SUCCESS) {
            log.error("业务平台新增租户响应失败,数据来源:" + platform.getPlatformName());
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), response.getBody().getMsg());
        }
        return JsonResult.success();
    }

    /**
     * 删除请求
     *
     * @param dto
     * @param code
     * @param loginUser
     * @return
     */
    private JsonResult deleteResult(CreateClientTenantDto dto, String code, String dictCode, LoginUser loginUser) {
        //获取对应平台
        Platform platform = getPlatform(code);
        if (ObjectUtil.isNull(platform)) {
            return JsonResult.error("该业务平台不存在");
        }
        //设置请求头
        HttpHeaders resultRequestHeader = new HttpHeaders();
        resultRequestHeader.add("Authorization", "Bearer " + loginUser.getThToken());
        HttpEntity httpEntity = new HttpEntity(dto, resultRequestHeader);
        //设置地址(hhz平台)
        String url = platform.getPlatformUrl();
        //根据不同业务平台进行动态匹配
        DictData dictData = getDictData(code, dictCode);
        if (ObjectUtil.isNull(dictData)) {
            return JsonResult.error("该业务平台对应字典表数据不存在");
        }
        url = url + dictData.getValue();
        log.info("请求url:{}", url);
        ResponseEntity<JsonResult> response;
        try {
            response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, JsonResult.class);
        } catch (Exception e) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "业务平台删除租户失败");
        }
        if (null == response || !response.hasBody()) {
            log.error("业务平台删除租户响应失败");
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "业务平台删除租户失败");
        }
        if (response.getBody().getCode() != JsonResult.SUCCESS) {
            log.error("业务平台删除租户响应失败,数据来源:" + platform.getPlatformName());
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), response.getBody().getMsg());
        }
        return JsonResult.success();
    }


    /**
     * 更新请求
     *
     * @param dto
     * @param code
     * @param loginUser
     * @return
     */
    private JsonResult editResult(CreateClientTenantDto dto, String code, String dictCode, LoginUser loginUser) {
        Platform platform = getPlatform(code);
        if (ObjectUtil.isNull(platform)) {
            return JsonResult.error("该业务平台不存在");
        }
        //设置请求头
        HttpHeaders resultRequestHeader = new HttpHeaders();
        resultRequestHeader.add("Authorization", "Bearer " + loginUser.getThToken());
        HttpEntity httpEntity = new HttpEntity(dto, resultRequestHeader);
        //设置地址(hhz平台)
        String url = platform.getPlatformUrl();
        DictData dictData = getDictData(code, dictCode);
        if (ObjectUtil.isNull(dictData)) {
            return JsonResult.error("该业务平台对应字典表数据不存在");
        }
        url = url + dictData.getValue();
        log.info("请求url:{}", url);
        ResponseEntity<JsonResult> response;
        try {
            response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, JsonResult.class);
        } catch (Exception e) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "业务平台更新租户失败");
        }
        if (null == response || !response.hasBody()) {
            log.error("业务平台更新租户响应失败");
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "业务平台更新租户失败");
        }
        if (response.getBody().getCode() != JsonResult.SUCCESS) {
            log.error("业务平台更新租户响应失败,数据来源:" + platform.getPlatformName());
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), response.getBody().getMsg());
        }
        return JsonResult.success();
    }

    /**
     * 获取平台数据
     *
     * @param code
     * @return
     */
    private Platform getPlatform(String code) {
        return platformMapper.selectOne(Wrappers.<Platform>lambdaQuery()
                .eq(Platform::getPlatformCode, code)
                .eq(Platform::getMark, 1));
    }

    /**
     * 获取字典表数据
     *
     * @param code
     * @param dictCode
     * @return
     */
    private DictData getDictData(String code, String dictCode) {
        DictData dictData = dictDataMapper.selectOne(Wrappers.<DictData>lambdaQuery()
                .eq(DictData::getDictType, code)
                .eq(DictData::getCode, dictCode)
                .eq(DictData::getMark, MarkTypeEnum.VALID.getCode()));
        return dictData;
    }
}
