package com.sckw.system.dubbo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sckw.core.common.enums.enums.ErrorCodeEnum;
import com.sckw.core.exception.BusinessPlatfromException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.EntTypeEnum;
import com.sckw.core.utils.*;
import com.sckw.core.web.response.result.PageDataResult;
import com.sckw.redis.utils.RedissonUtils;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.req.ActualDisPatchDto;
import com.sckw.system.api.model.dto.req.SingleTripTotalTimeDto;
import com.sckw.system.api.model.dto.res.*;
import com.sckw.system.dao.KwsRoleDao;
import com.sckw.system.dao.SysDictDao;
import com.sckw.system.model.*;
import com.sckw.system.model.vo.res.FindAreaTreeResVo;
import com.sckw.system.model.vo.res.KwsUserResVo;
import com.sckw.system.repository.KwsEntTypeRepository;
import com.sckw.system.repository.KwsRoleRepository;
import com.sckw.system.repository.KwsUserRepository;
import com.sckw.system.repository.KwsUserRoleRepository;
import com.sckw.system.service.KwsUserService;
import com.sckw.system.service.SysAreaService;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author czh
 * @desc 远程接口
 * @date 2023/6/12
 */
@DubboService(group = "design", version = "1.0.0")
@RequiredArgsConstructor
public class RemoteSystemServiceImpl implements RemoteSystemService {

    @Autowired
    private SysDictDao sysDictDao;

    @Resource
    private KwsUserService kwsUserService;

    @Autowired
    private RemoteBaseService remoteBaseService;

    @Autowired
    private SysAreaService sysAreaService;

    private final KwsRoleDao kwsRoleDao;
    private final KwsEntTypeRepository kwsEntTypeRepository;
    private final KwsUserRepository kwsUserRepository;
    private final KwsRoleRepository roleRepository;
    private final KwsUserRoleRepository userRoleRepository;

    /**
     * @param keys type#value,type#value
     * @return Map<String, SysDictResDto>
     * @desc: 根据类型id查字典，先查redis，没查到查数据库，查出来了存redis
     * @author: czh
     * @date: 2023/7/5
     */
    @Override
    public Map<String, SysDictResDto> queryDictMapByTypeValues(String keys) {
        if (StringUtils.isBlank(keys)) {
            return Collections.emptyMap();
        }
        Map<String, SysDictResDto> map = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        String[] typeValueArr = keys.split(Global.COMMA);
        for (String typeValue : typeValueArr) {
            if (StringUtils.isNotBlank(typeValue)) {
                String[] split = typeValue.split(Global.POUND);
                if (split == null || split.length < Global.NUMERICAL_TWO) {
                    continue;
                }
                SysDictResDto sysDictResDto = queryDictByTypeAndValue(split[0], split[1]);
                map.put(typeValue, sysDictResDto);
            }
        }

        return map;
    }

    /**
     * @param type 类型
     * @return Map<String, SysDictResDto>
     * @desc: 根据类型id查字典，先查redis，没查到查数据库，查出来了存redis
     * @author: czh
     * @date: 2023/7/5
     */
    @Override
    public Map<String, SysDictResDto> queryDictMapByType(String type) {
        if (StringUtils.isBlank(type)) {
            return Collections.emptyMap();
        }
        List<SysDictResDto> sysDictResDtos = queryDictByType(type);
        if (CollectionUtils.isEmpty(sysDictResDtos)) {
            return Collections.emptyMap();
        }

        return sysDictResDtos.stream().collect(Collectors.toMap(SysDictResDto::getValue, v -> v));
    }

    /**
     * @param type 类型
     * @return SysDictResDto
     * @desc: 根据类型id查字典，先查redis，没查到查数据库，查出来了存redis
     * @author: czh
     * @date: 2023/7/5
     */
    @Override
    public List<SysDictResDto> queryDictByType(String type) {
        if (StringUtils.isBlank(type)) {
            return Collections.emptyList();
        }
        String key = Global.REDIS_SYS_DICT_TYPE_PREFIX + type;
        String dictCache = RedissonUtils.getString(key);
        //从redis查，查不到从数据库查，并写入redis
        if (StringUtils.isBlank(dictCache)) {
            List<SysDict> sysDictList = sysDictDao.queryByType(type);
            if (CollectionUtils.isEmpty(sysDictList)) {
                return Collections.emptyList();
            }
            List<SysDictResDto> sysDictResDtos = BeanUtils.copyToList(sysDictList, SysDictResDto.class);
            RedissonUtils.putString(key, JSON.toJSONString(sysDictResDtos), Global.COMMON_EXPIRE);
            return sysDictResDtos;
        }
        RedissonUtils.putString(key, dictCache, Global.COMMON_EXPIRE);
        return JSONObject.parseArray(dictCache, SysDictResDto.class);
    }

    @Override
    public Map<String, Map<String, String>> queryDictByType(List<String> list) {
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyMap();
        }

        Map<String, Map<String, String>> map = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        for (String type : list) {
            List<SysDictResDto> sysDictResDtos = queryDictByType(type);
            if (CollectionUtils.isEmpty(sysDictResDtos)) {
                continue;
            }

            Map<String, String> collect = sysDictResDtos.stream().collect(Collectors.toMap(SysDictResDto::getValue, SysDictResDto::getLabel, (n, o) -> n));
            map.put(type, collect);
        }
        return map;
    }

    @Override
    public DictProduct queryProductName(String value) {
        return sysDictDao.queryProductName(value);
    }

    /**
     * @param type 字典类型，value key
     * @return SysDictResDto
     * @desc: 根据字典类型和key查
     * @author: czh
     * @date: 2023/7/7
     */
    @Override
    public SysDictResDto queryDictByTypeAndValue(String type, String value) {
        if (StringUtils.isBlank(type) || StringUtils.isBlank(value)) {
            return null;
        }
        String key = Global.REDIS_SYS_DICT_PREFIX + type + Global.POUND + value;
        String dictCache = RedissonUtils.getString(key);
        //从redis查，查不到从数据库查，并写入redis
        if (StringUtils.isBlank(dictCache)) {
            SysDict sysDict = sysDictDao.queryByTypeAndValue(type, value);
            if (Objects.isNull(sysDict)) {
                return null;
            }
            SysDictResDto sysDictResDto = new SysDictResDto();
            BeanUtils.copyProperties(sysDict, sysDictResDto);
            RedissonUtils.putString(key, JSON.toJSONString(sysDictResDto), Global.COMMON_EXPIRE);
            return sysDictResDto;
        }
        RedissonUtils.putString(key, dictCache, Global.COMMON_EXPIRE);
        return JSONObject.parseObject(dictCache, SysDictResDto.class);
    }

    /**
     * @param type 字典类型
     * @return SysDictResDto
     * @desc: 根据字典类型和key查字典
     * @author: czh
     * @date: 2023/7/7
     */
    @Override
    public List<SysDictGroupResDto> queryDictGroupByType(String type) {
        if (StringUtils.isBlank(type)) {
            return Collections.emptyList();
        }
        List<SysDict> sysDicts = sysDictDao.queryByType(type);
        if (CollectionUtils.isEmpty(sysDicts)) {
            return Collections.emptyList();
        }

        //取最顶层去递归
        List<SysDictGroupResDto> list = new ArrayList<>();
        sysDicts = sysDicts.stream().filter(item -> item.getParentId().equals(String.valueOf(Global.NO))).toList();
        if (CollectionUtils.isEmpty(sysDicts)) {
            return Collections.emptyList();
        }

        sysDicts.forEach(item -> {
            SysDictGroupResDto sysDictGroupResDto = queryDictGroupByTypeAndValue(type, item.getValue());
            if (!Objects.isNull(sysDictGroupResDto)) {
                list.add(sysDictGroupResDto);
            }
        });

        return list;
    }


    /**
     * @param type 字典类型 value key
     * @return SysDictResDto
     * @desc: 根据字典类型和key查最底层的数据
     * @author: czh
     * @date: 2023/7/7
     */
    @Override
    public List<SysDictResDto> queryDictBottom(String type, String value) {
        if (StringUtils.isBlank(type) || StringUtils.isBlank(value)) {
            return Collections.emptyList();
        }
        SysDictGroupResDto sysDictGroupResDto = queryDictGroupByTypeAndValue(type, value);
        if (Objects.isNull(sysDictGroupResDto)) {
            return Collections.emptyList();
        }

        if (CollectionUtils.isEmpty(sysDictGroupResDto.getChild())) {
            SysDictResDto sysDictResDto = new SysDictResDto();
            BeanUtils.copyProperties(sysDictGroupResDto, sysDictResDto);
            return Collections.singletonList(sysDictResDto);
        }
        return BeanUtils.copyToList(checkNextLevelDict(sysDictGroupResDto.getChild()), SysDictResDto.class);
    }

    @Override
    public List<SysDictResDto> queryGoodsDict(String keywords) {
        if (StringUtils.isBlank(keywords)) {
            return Collections.emptyList();
        }
        //industry_type  classification_type product_name_type
        List<SysDictResDto> sysDictResDtos1 = queryDictByType("industry_type");
        List<SysDictResDto> collect = sysDictResDtos1.stream().filter(d -> StrUtil.contains(d.getLabel(), keywords)).toList();
        List<SysDictResDto> res = new ArrayList<>(collect);
        List<SysDictResDto> sysDictResDtos2 = queryDictByType("classification_type");
        List<SysDictResDto> collect2 = sysDictResDtos2.stream().filter(d -> StrUtil.contains(d.getLabel(), keywords)).toList();
        res.addAll(collect2);
        List<SysDictResDto> sysDictResDtos3 = queryDictByType("product_name_type");
        List<SysDictResDto> collect3 = sysDictResDtos3.stream().filter(d -> StrUtil.contains(d.getLabel(), keywords)).toList();
        res.addAll(collect3);
        return res;
    }

    @Override
    public List<SysDictResDto> queryDictFrontAll(String type, String value) {
        if (StringUtils.isBlank(type) || StringUtils.isBlank(value)) {
            return Collections.emptyList();
        }

        SysDict sysDict = sysDictDao.queryByTypeAndValue(type, value);
        if (Objects.isNull(sysDict)) {
            return Collections.emptyList();
        }

        List<SysDictResDto> list = new ArrayList<>();
        getFrontAll(sysDict, list);
        List<SysDictResDto> result = new ArrayList<>();
        for (int n = list.size() - 1; n >= 0; n--) {
            result.add(list.get(n));
        }
        return result;
    }

    private void getFrontAll(SysDict sysDict, List<SysDictResDto> list) {
        String parentId = sysDict.getParentId();
        SysDictResDto sysDictResDto = new SysDictResDto();
        BeanUtils.copyProperties(sysDict, sysDictResDto);
        list.add(sysDictResDto);

        if (String.valueOf(Global.NUMERICAL_ZERO).equals(parentId)) {
            return;
        }

        SysDict sysDict1 = sysDictDao.selectByKey(Long.valueOf(parentId));
        getFrontAll(sysDict1, list);
    }

    private List<SysDictGroupResDto> checkNextLevelDict(List<SysDictGroupResDto> list) {
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<SysDictGroupResDto> sysDictGroupResDtos = list.stream().filter(item -> CollectionUtils.isNotEmpty(item.getChild())).toList();
        if (CollectionUtils.isEmpty(sysDictGroupResDtos)) {
            return list;
        }

        List<SysDictGroupResDto> child = new ArrayList<>();
        for (SysDictGroupResDto sysDictGroupResDto : sysDictGroupResDtos) {
            child.addAll(sysDictGroupResDto.getChild());
        }
        return checkNextLevelDict(child);
    }

    /**
     * @param type 字典类型，value key
     * @return SysDictGroupResDto
     * @desc: 根据字典类型和key查字典组
     * @author: czh
     * @date: 2023/7/7
     */
    @Override
    public SysDictGroupResDto queryDictGroupByTypeAndValue(String type, String value) {
        if (StringUtils.isBlank(type) || StringUtils.isBlank(value)) {
            return null;
        }
        String key = Global.REDIS_SYS_DICT_GROUP_PREFIX + type + Global.POUND + value;
        String dictCache = RedissonUtils.getString(key);
        //从redis查，查不到从数据库查，并写入redis
        if (StringUtils.isBlank(dictCache)) {
            List<SysDict> list = sysDictDao.selectAll();
            if (CollectionUtils.isEmpty(list)) {
                return null;
            }
            Optional<SysDict> first = list.stream().filter(item -> item.getType().equals(type) && item.getValue().equals(value)).findFirst();
            if (first.isEmpty()) {
                return null;
            }

            SysDictGroupResDto sysDictGroupResDto = new SysDictGroupResDto();
            BeanUtils.copyProperties(first.get(), sysDictGroupResDto);
            sysDictGroupResDto.setUrl(FileUtils.splice(sysDictGroupResDto.getUrl()));
            sysDictGroupResDto.setChild(getChild(sysDictGroupResDto.getId(), list));
            RedissonUtils.putString(key, JSON.toJSONString(sysDictGroupResDto), Global.COMMON_EXPIRE);
            return sysDictGroupResDto;
        }
        RedissonUtils.putString(key, dictCache, Global.COMMON_EXPIRE);
        return JSONObject.parseObject(dictCache, SysDictGroupResDto.class);
    }


    /**
     * @param entId 企业id
     * @return EntCacheResDto
     * @desc: 从缓存查企业信息
     * @author: czh
     * @date: 2023/7/7
     */
    @Override
    public EntCacheResDto queryEntCacheById(Long entId) {
        if (Objects.isNull(entId)) {
            return null;
        }
        String key = Global.REDIS_ENTERPRISE_PREFIX + entId;
        String dictCache = RedissonUtils.getString(key);
        //从redis查，查不到从数据库查，并写入redis
        if (StringUtils.isBlank(dictCache)) {
            EntCacheResDto entCacheResDto = getEntCacheResDto(entId);
            if (Objects.isNull(entCacheResDto)) {
                return null;
            }
            RedissonUtils.putString(key, JSON.toJSONString(entCacheResDto), Global.COMMON_EXPIRE);
            return entCacheResDto;
        }

        EntCacheResDto entCacheResDto = JSONObject.parseObject(dictCache, EntCacheResDto.class);
        if (Objects.isNull(entCacheResDto.getContactsId())) {
            entCacheResDto = getEntCacheResDto(entId);
            if (Objects.isNull(entCacheResDto)) {
                return null;
            }
        }

        RedissonUtils.putString(key, dictCache, Global.COMMON_EXPIRE);
        return entCacheResDto;
    }

    @Nullable
    private EntCacheResDto getEntCacheResDto(Long entId) {
        KwsEnterpriseResDto kwsEnterpriseResDto = remoteBaseService.queryEnterpriseById(entId);
        if (Objects.isNull(kwsEnterpriseResDto)) {
            return null;
        }

        EntCacheResDto entCacheResDto = new EntCacheResDto();
        BeanUtils.copyProperties(kwsEnterpriseResDto, entCacheResDto);
//        entCacheResDto.setDeptInfo(remoteBaseService.queryDeftInfoByEntId(entId));
        entCacheResDto.setCertificateInfo(remoteBaseService.queryCertificateByEntId(entId));
        KwsUser kwsUser = remoteBaseService.queryManageByEntId(entId);
        if (Objects.nonNull(kwsUser)) {
            entCacheResDto.setContactsId(kwsUser.getId());
            entCacheResDto.setContacts(kwsUser.getName());
            entCacheResDto.setPhone(kwsUser.getPhone());
        }
        List<EntTypeResDto> entTypeResDtos = remoteBaseService.queryEntTypeById(entId);
        if (CollectionUtils.isNotEmpty(entTypeResDtos)) {
            entCacheResDto.setEntTypes(String.join(Global.COMMA, entTypeResDtos.stream().map(EntTypeResDto::getType).map(String::valueOf).distinct().toList()));
            entCacheResDto.setEntTypeNames(EntTypeEnum.getNames(entCacheResDto.getEntTypes()));
        }
        return entCacheResDto;
    }

    /**
     * @param entName 企业名
     * @return EntCacheResDto
     * @desc: 从缓存查企业信息 模糊匹配
     * @author: czh
     * @date: 2023/7/7
     */
    @Override
    public List<EntCacheResDto> queryEntCacheByName(String entName) {
        if (StringUtils.isBlank(entName)) {
            return Collections.emptyList();
        }
        List<KwsEnterprise> kwsEnterprises = remoteBaseService.findEnts(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
            put("firmName", entName);
        }});
        if (CollectionUtils.isEmpty(kwsEnterprises)) {
            return Collections.emptyList();
        }

        List<EntCacheResDto> list = new ArrayList<>();
        for (KwsEnterprise kwsEnterprise : kwsEnterprises) {
            EntCacheResDto entCacheResDto = queryEntCacheById(kwsEnterprise.getId());
            if (!Objects.isNull(entCacheResDto)) {
                list.add(entCacheResDto);
            }
        }
        return list;
    }

    /**
     * @param entIdList 企业id集合
     * @return Map<Long, EntCacheResDto>
     * @desc: 查企业树
     * @author: czh
     * @date: 2023/7/17
     */
    @Override
    public Map<Long, EntCacheResDto> queryEntTreeByIds(List<Long> entIdList) {
        if (CollectionUtils.isEmpty(entIdList)) {
            return Collections.emptyMap();
        }
        Map<Long, EntCacheResDto> result = new HashMap<>(4);
        for (Long entId : entIdList) {
            EntCacheResDto entCacheResDto = queryEntCacheById(entId);
            if (Objects.isNull(entCacheResDto)) {
                continue;
            }
            remoteBaseService.fillRelate(entCacheResDto);

            //有父企业
            Long parentId = entCacheResDto.getParentId();
            if (Objects.nonNull(parentId)) {
                EntCacheResDto parent = queryEntCacheById(parentId);
                parent.setChild(Collections.singletonList(entCacheResDto));
                result.put(entId, parent);
                continue;
            }

            //没有主体单位
            String entDeptIds = entCacheResDto.getEntDeptIds();
            if (StringUtils.isBlank(entDeptIds)) {
                result.put(entId, entCacheResDto);
                continue;
            }

            //有主体单位
            List<Long> entDeptIdList = Arrays.stream(entDeptIds.split(Global.COMMA)).map(Long::parseLong).toList();
            List<EntCacheResDto> child = queryEntCacheByIds(entDeptIdList);
            entCacheResDto.setChild(child);
            result.put(entId, entCacheResDto);
        }
        return result;
    }

    @Override
    public List<KwsEntDeptDto> queryEntDeptByPid(Long entPid) {
        List<KwsEntDeptDto> entDeptDtos = new ArrayList<>();
        List<KwsEntDept> entDepts = remoteBaseService.queryEntDeptCacheByIds(new ArrayList<>() {{
            add(entPid);
        }});
        if (CollectionUtils.isEmpty(entDepts)) {
            return entDeptDtos;
        }

        return BeanUtils.copyToList(entDepts, KwsEntDeptDto.class);
    }

    @Override
    public EntCacheResDto queryEntTreeById(Long entId) {
        if (Objects.isNull(entId)) {
            return null;
        }
        Map<Long, EntCacheResDto> longEntCacheResDtoMap = queryEntTreeByIds(Collections.singletonList(entId));
        if (longEntCacheResDtoMap.isEmpty()) {
            return null;
        }
        return longEntCacheResDtoMap.get(entId);
    }

    @Override
    public EntCacheResDto queryEntByName(String entName) {
        return remoteBaseService.queryEntByName(entName);
    }

    @Override
    public List<EntCacheResDto> queryEntCacheByIds(List<Long> entIds) {
        if (CollectionUtils.isEmpty(entIds)) {
            return Collections.emptyList();
        }
        List<EntCacheResDto> list = new ArrayList<>();
        entIds.stream().distinct().toList().forEach(entId -> {
            EntCacheResDto entCacheResDto = queryEntCacheById(entId);
            if (Objects.nonNull(entCacheResDto)) {
                list.add(entCacheResDto);
            }
        });
        return list;
    }

    @Override
    public Map<Long, List<EntCacheResDto>> queryEntDeptCacheByIds(List<Long> entIds) {
        if (CollectionUtils.isEmpty(entIds)) {
            return Collections.emptyMap();
        }
        List<KwsEntDept> kwsEntDepts = remoteBaseService.queryEntDeptCacheByIds(entIds);
        if (CollectionUtils.isEmpty(kwsEntDepts)) {
            return Collections.emptyMap();
        }

        Map<Long, List<KwsEntDept>> collect = kwsEntDepts.stream().collect(Collectors.groupingBy(KwsEntDept::getEntPid));
        Map<Long, List<EntCacheResDto>> map = new HashMap<>(4);
        for (Long key : collect.keySet()) {
            List<KwsEntDept> kwsEntDepts1 = collect.get(key);
            List<Long> entIdList = kwsEntDepts1.stream().map(KwsEntDept::getEntId).toList();
            List<EntCacheResDto> entCacheResDtos = queryEntCacheByIds(entIdList);
            map.put(key, entCacheResDtos);
        }
        return map;
    }

    @Override
    public Map<Long, EntCacheResDto> queryEntCacheMapByIds(List<Long> entIds) {
        if (CollectionUtils.isEmpty(entIds)) {
            return Collections.emptyMap();
        }
        List<EntCacheResDto> entCacheResDtos = queryEntCacheByIds(entIds);
        if (CollectionUtils.isEmpty(entCacheResDtos)) {
            return Collections.emptyMap();
        }
        return entCacheResDtos.stream().collect(Collectors.toMap(EntCacheResDto::getId, x -> x, (oldValue, newValue) -> newValue));
    }

    @Override
    public UserCacheResDto queryUserCacheById(Long userId) {
        if (Objects.isNull(userId)) {
            return null;
        }
        String key = Global.REDIS_USER_PREFIX + userId;
        String dictCache = RedissonUtils.getString(key);
        //从redis查，查不到从数据库查，并写入redis
        if (StringUtils.isBlank(dictCache)) {
            KwsUser kwsUser = kwsUserService.selectByKey(userId);
            if (Objects.isNull(kwsUser)) {
                return null;
            }

            UserCacheResDto userCacheResDto = new UserCacheResDto();
            BeanUtils.copyProperties(kwsUser, userCacheResDto);
            userCacheResDto.setRoleInfo(remoteBaseService.queryRoleInfoByUserId(userId));

//            List<KwsUserDeptResDto> kwsUserDeptResDtos = remoteBaseService.queryUserDeptByUserId(userId);
//            if (CollectionUtils.isEmpty(kwsUserDeptResDtos)) {
//                return userCacheResDto;
//            }

//            List<Long> deptIds = kwsUserDeptResDtos.stream().map(KwsUserDeptResDto::getDeptId).toList();
//            List<KwsDeptResDto> kwsDeptResDtos = remoteBaseService.queryDeptByIds(deptIds);
//            if (CollectionUtils.isEmpty(kwsDeptResDtos)) {
//                return userCacheResDto;
//            }

            // Long entId = kwsDeptResDtos.get(0).getEntId();
            KwsEnterpriseResDto kwsEnterpriseResDto = remoteBaseService.queryEnterpriseById(kwsUser.getEntId());
            if (Objects.isNull(kwsEnterpriseResDto)) {
                return userCacheResDto;
            }

            EntCacheResDto entCacheResDto = new EntCacheResDto();
            BeanUtils.copyProperties(kwsEnterpriseResDto, entCacheResDto);
            //entCacheResDto.setDeptInfo(BeanUtils.copyToList(kwsDeptResDtos, DeptInfoPojo.class));
            entCacheResDto.setCertificateInfo(remoteBaseService.queryCertificateByEntId(kwsUser.getId()));
            userCacheResDto.setEntInfo(entCacheResDto);
            RedissonUtils.putString(key, JSON.toJSONString(userCacheResDto), Global.COMMON_EXPIRE);
            return userCacheResDto;
        }
        RedissonUtils.putString(key, dictCache, Global.COMMON_EXPIRE);
        return JSONObject.parseObject(dictCache, UserCacheResDto.class);
    }

    @Override
    public UserResDto queryUserById(Long userId) {
        KwsUser kwsUser = kwsUserService.selectByKey(userId);
        if (Objects.nonNull(kwsUser)) {
            UserResDto bean = BeanUtil.toBean(kwsUser, UserResDto.class);
            KwsEntType one = kwsEntTypeRepository.lambdaQuery().eq(KwsEntType::getEntId, kwsUser.getEntId()).last("limit 1").one();
            if (Objects.nonNull(one)) {
                bean.setType(one.getType());
            }
            return bean;
        }
        return null;
    }

    @Override
    public UserResDto queryUserByPhone(String phone) {
        KwsUser kwsUser = kwsUserService.selectByPhone(phone);
        if (Objects.nonNull(kwsUser)) {
            UserResDto bean = BeanUtil.toBean(kwsUser, UserResDto.class);
            return bean;
        }
        return null;
    }

    @Override
    public List<UserCacheResDto> queryUserCacheByIds(List<Long> userIds) {
        if (CollectionUtils.isEmpty(userIds)) {
            return Collections.emptyList();
        }
        List<UserCacheResDto> list = new ArrayList<>();
        userIds.stream().distinct().toList().forEach(e -> {
            UserCacheResDto dto = queryUserCacheById(e);
            if (Objects.nonNull(dto)) {
                list.add(dto);
            }
        });
        return list;
    }

    @Override
    public Map<Long, UserCacheResDto> queryUserCacheMapByIds(List<Long> userIds) {
        if (CollectionUtils.isEmpty(userIds)) {
            return Collections.emptyMap();
        }
        List<UserCacheResDto> userCacheResDtos = queryUserCacheByIds(userIds);
        if (CollectionUtils.isEmpty(userCacheResDtos)) {
            return Collections.emptyMap();
        }
        return userCacheResDtos.stream().collect(Collectors.toMap(UserCacheResDto::getId, x -> x, (oldValue, newValue) -> newValue));
    }

    @Override
    public SysAreaCacheResDto queryAreaCacheById(Integer code) {
        if (Objects.isNull(code)) {
            return null;
        }
        String key = Global.REDIS_AREA_PREFIX + code;
        String areaCache = RedissonUtils.getString(key);
        //从redis查，查不到从数据库查，并写入redis
        if (StringUtils.isBlank(areaCache)) {
            SysArea sysArea = sysAreaService.selectById(code);
            if (Objects.isNull(sysArea)) {
                return new SysAreaCacheResDto();
            }

            SysAreaCacheResDto sysAreaCacheResDto = BeanUtils.copyProperties(sysArea, SysAreaCacheResDto.class);
            RedissonUtils.putString(key, JSON.toJSONString(sysAreaCacheResDto), Global.COMMON_EXPIRE);
            return sysAreaCacheResDto;
        }
        RedissonUtils.putString(key, areaCache, Global.COMMON_EXPIRE);
        return JSONObject.parseObject(areaCache, SysAreaCacheResDto.class);
    }

    @Override
    public List<AreaTreeFrontResDto> queryAreaTreeFrontByCodeList(List<Integer> list) {
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<SysArea> sysAreas = sysAreaService.selectByIds(list);
        if (CollectionUtils.isEmpty(sysAreas)) {
            return Collections.emptyList();
        }

        int maxLevel = sysAreas.stream().map(SysArea::getLevel).max(Integer::compareTo).get();
        List<AreaTreeFrontResDto> areaTreeFrontResDtoList = BeanUtils.copyToList(sysAreas, AreaTreeFrontResDto.class);
        List<AreaTreeFrontResDto> upLevel = new ArrayList<>();
        for (int i = maxLevel; i > 1; i--) {
            int finalI = i;
            List<AreaTreeFrontResDto> currentLevelArea = areaTreeFrontResDtoList.stream().filter(item -> item.getLevel().equals(finalI)).toList();
            for (AreaTreeFrontResDto areaTreeFrontResDto : currentLevelArea) {
                if (!upLevel.stream().map(AreaTreeFrontResDto::getCode).toList().contains(areaTreeFrontResDto.getCode())) {
                    upLevel.add(areaTreeFrontResDto);
                }
            }

            upLevel.removeIf(x -> x.getLevel() > finalI);
            Map<Integer, List<AreaTreeFrontResDto>> collect = upLevel.stream().collect(Collectors.groupingBy(AreaTreeFrontResDto::getPcode));
            for (Integer pcode : collect.keySet()) {
                SysArea sysArea = sysAreaService.selectById(pcode);
                AreaTreeFrontResDto areaTreeFrontResDto = new AreaTreeFrontResDto();
                areaTreeFrontResDto.setCode(sysArea.getCode());
                areaTreeFrontResDto.setPcode(sysArea.getPcode());
                areaTreeFrontResDto.setName(sysArea.getName());
                areaTreeFrontResDto.setLevel(sysArea.getLevel());
                areaTreeFrontResDto.setChild(collect.get(pcode));
                upLevel.add(areaTreeFrontResDto);
            }
        }

        return upLevel.stream().filter(x -> x.getLevel() == 1).toList();
    }


    @Override
    public UserCacheResDto queryManagerInfoByEntId(Long entId) {
        if (Objects.isNull(entId)) {
            return null;
        }
        KwsEnterpriseResDto kwsEnterpriseResDto = remoteBaseService.queryEnterpriseById(entId);
        if (Objects.isNull(kwsEnterpriseResDto) || Objects.isNull(kwsEnterpriseResDto.getManager())) {
            return null;
        }

        return queryUserCacheById(kwsEnterpriseResDto.getManager());
    }

    /**
     * @param id 父id，需要遍历的list
     * @return SysDictGroupResDto
     * @desc: 构建字典组
     * @author: czh
     * @date: 2023/7/7
     */
    private List<SysDictGroupResDto> getChild(Long id, List<SysDict> list) {
        if (Objects.isNull(id) || CollectionUtils.isEmpty(list)) {
            return null;
        }
        List<SysDictGroupResDto> child = new ArrayList<>();
        for (SysDict sysDict : list) {
            if (sysDict.getParentId().equals(String.valueOf(id))) {
                SysDictGroupResDto sysDictGroupResDto = new SysDictGroupResDto();
                BeanUtils.copyProperties(sysDict, sysDictGroupResDto);
                sysDictGroupResDto.setUrl(FileUtils.splice(sysDictGroupResDto.getUrl()));
                child.add(sysDictGroupResDto);
            }
        }

        if (!CollectionUtils.isEmpty(child)) {
            for (SysDictGroupResDto sysDictGroupResDto : child) {
                sysDictGroupResDto.setChild(getChild(sysDictGroupResDto.getId(), list));
            }
        }

        return CollectionUtils.isEmpty(child) ? null : child;
    }


    /**
     * @param code 区域code
     * @return List<FindAreaTreeResVo>
     * @desc: 查区域树
     * @author: czh
     * @date: 2023/7/31
     */
    public List<FindAreaTreeResVo> queryAreaTree(Integer code) {
        if (Objects.isNull(code)) {
            return Collections.emptyList();
        }
        String key = Global.REDIS_GROUP_AREA_PREFIX + code;
        String areaCache = RedissonUtils.getString(key);
        if (StringUtils.isBlank(areaCache)) {
            List<FindAreaTreeResVo> findAreaTreeResVos = queryAreaGroup(code);
            RedissonUtils.putString(key, JSON.toJSONString(findAreaTreeResVos), Global.MINUS_ONE);
            return findAreaTreeResVos;
        }

        return JSONArray.parseArray(areaCache, FindAreaTreeResVo.class);
    }

    /**
     * @param code 区域code
     * @return List<FindAreaTreeResVo>
     * @desc: 查区域树
     * @author: czh
     * @date: 2023/7/31
     */
    private List<FindAreaTreeResVo> queryAreaGroup(Integer code) {
        if (Objects.isNull(code)) {
            return Collections.emptyList();
        }

        List<SysArea> list = sysAreaService.findList(null);
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }

        return getAreaChild(BeanUtils.copyToList(list, FindAreaTreeResVo.class), code);
    }

    private List<FindAreaTreeResVo> getAreaChild(List<FindAreaTreeResVo> findAreaTreeResVoList, Integer code) {
        List<FindAreaTreeResVo> result = findAreaTreeResVoList.stream().filter(item -> item.getPcode().equals(code)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(result)) {
            return null;
        }
        for (FindAreaTreeResVo findAreaTreeResVo : result) {
            if (findAreaTreeResVo.getLevel().equals(Global.NUMERICAL_THREE)) {
                continue;
            }

            findAreaTreeResVo.setChild(getAreaChild(findAreaTreeResVoList, findAreaTreeResVo.getCode()));
        }
        return result;
    }

    /**
     * @param entId 企业ID
     * @return
     * @desc 企业详情(企业登录 / 司机登录)
     * @author zk
     * @date 2023/8/10
     */
    @Override
    public EntCacheResDto queryEntDetails(Long entId) {
        if (Objects.isNull(entId)) {
            return null;
        }
        return remoteBaseService.queryEntDetails(entId);
    }

    /**
     * @param account    账号
     * @param systemType 系统类型
     * @desc 用户详情(企业端登录 / 运营端登录)
     * @author zk
     * @date 2023/8/10
     **/
    @Override
    public KwsUserResDto queryUserDetails(String account, Integer systemType) {
        if (Objects.isNull(systemType) || StringUtils.isBlank(account)) {
            return null;
        }
        Map<String, Object> params = new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
            put("account", account);
            put("systemType", systemType);
        }};
        KwsUserResVo userResVo = kwsUserService.queryUserRole(params);
        if (Objects.nonNull(userResVo)) {
            KwsUserResDto userResDto = new KwsUserResDto();
            BeanUtils.copyPropertiesValue(userResVo, userResDto);
            return userResDto;
        }
        return null;
    }

    /**
     * @desc 查询专场集
     * @author zk
     * @date 2023/12/14
     **/
    @Override
    public List<SpecialResVo> querySpecial() {
        return remoteBaseService.findSpecial();
    }

    /**
     * @param code 专场编号
     * @param type 企业类型
     * @desc 专场编号查询关联企业ID
     * @author zk
     * @date 2023/12/16
     **/
    @Override
    public List<Long> queryEntIdsByCode(String code, String type) {
        return remoteBaseService.findEntIdsByCode(code, type);
    }

    /**
     * @param code 专场编号
     * @desc 专场编号查询是否为主平台
     * @author zk
     * @date 2023/12/16
     **/
    @Override
    public boolean queryMainPlatform(String code) {
        return remoteBaseService.queryMainPlatform(code);
    }

    /**
     * 企业主键id查询数据库企业信息
     *
     * @param entIds 企业id查询数据库企业信息
     * @return
     */
    @Override
    public Map<Long, KwsEnterpriseResDto> queryEnterpriseByEntIds(List<Long> entIds) {
        return remoteBaseService.queryEnterpriseByEntIds(entIds);
    }

    /**
     * 企业名称 精确查询企业
     *
     * @param enterpriseName
     * @return
     */
    @Override
    public KwsEnterpriseResDto findEnterpriseByName(String enterpriseName) {
        KwsEnterpriseResDto dto = remoteBaseService.findEnterpriseByName(enterpriseName);
        return dto;
    }

    /**
     * 分页查询企业信息
     *
     * @param pageNum  当前页数
     * @param pageSize 每页大小
     * @param entId    企业 id
     * @return 企业数据
     */
    @Override
    public PageDataResult<KwsEnterpriseResDto> pageEnt(int pageNum, int pageSize, Long entId) {
        return remoteBaseService.pageEnt(pageNum, pageSize, entId);
    }

    @Override
    public KwsEnterpriseResDto queryEnterpriseByEntId(Long entId) {
        return remoteBaseService.queryEnterpriseById(entId);
    }

    @Override
    public List<KwsEnterpriseResDto> queryEntListByEntIds(List<Long> entIds) {
        return remoteBaseService.queryEntListByEntIds(entIds);
    }


    @Override
    public EntTypeResDto queryEntTypeById(Long entId) {
        List<EntTypeResDto> entTypeResDtoList = remoteBaseService.queryEntTypeById(entId);
        if (entTypeResDtoList.isEmpty()) {
            return null;
        }
        return entTypeResDtoList.get(0);
    }

    @Override
    public KwsRoleDto queryByRoleIdAndEntId(Long currentRoleId) {
        KwsRole kwsRole = kwsRoleDao.selectByKey(currentRoleId);
        if (Objects.isNull(kwsRole)) {
            return new KwsRoleDto();
        }
        KwsRoleDto kwsRoleDto = new KwsRoleDto();
        kwsRoleDto.setName(kwsRole.getName());
        kwsRoleDto.setEntId(kwsRole.getEntId());
        kwsRoleDto.setId(kwsRole.getId());
        kwsRoleDto.setStatus(kwsRole.getStatus());
        return kwsRoleDto;
    }

    @Override
    public List<EntTypeResDto> queryEntTypeByIds(Set<Long> entIds) {
        List<KwsEntType> kwsEnterprises = kwsEntTypeRepository.queryByEntIds(entIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(kwsEnterprises)) {
            return List.of();
        }
        return kwsEnterprises.stream()
                .map(RemoteSystemServiceImpl::getEntTypeResDto)
                .collect(Collectors.toList());

    }

    @NotNull
    private static EntTypeResDto getEntTypeResDto(KwsEntType item) {
        EntTypeResDto entTypeResDto = new EntTypeResDto();
        entTypeResDto.setEntId(item.getEntId());
        entTypeResDto.setType(item.getType());
        entTypeResDto.setId(item.getId());
        entTypeResDto.setRemark(item.getRemark());
        entTypeResDto.setStatus(item.getStatus());
        entTypeResDto.setCreateBy(item.getCreateBy());
        entTypeResDto.setCreateTime(item.getCreateTime());
        entTypeResDto.setUpdateBy(item.getUpdateBy());
        entTypeResDto.setUpdateTime(item.getUpdateTime());
        entTypeResDto.setDelFlag(item.getDelFlag());
        return entTypeResDto;
    }

    /**
     * 计算平台配置的运单单趟总耗时
     * 获取自动派单系数配置（单趟耗时 = 装货时间 + 卸货时间 + 运输时间 + 返回时间）
     *
     * @param dto
     * @return
     */
    public Integer calSingleTripTotalTimes(SingleTripTotalTimeDto dto) {
        //装货时长
        Integer vehicleLoadingHours = dto.getVehicleLoadingHours();
        //卸货货时长
        Integer vehicleUnloadingHours = dto.getVehicleUnloadingHours();
        //平均行驶速度
        Integer vehicleAvgSpeed = dto.getVehicleAvgSpeed();
        if (vehicleLoadingHours <= 0 || vehicleUnloadingHours <= 0 || vehicleAvgSpeed <= 0) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "司机配置的装货时长/卸货时长/平均行驶速度需要≥0!");
        }

        //应卸货地与实际卸货地之间距离
        double twoPlaceDistanceKm = com.sckw.core.utils.LocUtils.calculateDistanceByAmap(
                Optional.ofNullable(dto.getLon1()).map(String::valueOf).orElse(null),
                Optional.ofNullable(dto.getLat1()).map(String::valueOf).orElse(null),
                Optional.ofNullable(dto.getLon2()).map(String::valueOf).orElse(null),
                Optional.ofNullable(dto.getLat2()).map(String::valueOf).orElse(null));
        // 如果高德API调用失败，使用原始方法作为备选
        if (twoPlaceDistanceKm == -1) {
            twoPlaceDistanceKm = DistanceUtils.calculateDistance(
                    Optional.ofNullable(dto.getLon1()).map(Double::valueOf).orElse(null),
                    Optional.ofNullable(dto.getLat1()).map(Double::valueOf).orElse(null),
                    Optional.ofNullable(dto.getLon2()).map(Double::valueOf).orElse(null),
                    Optional.ofNullable(dto.getLat2()).map(Double::valueOf).orElse(null));
        }
        //运输时间/返回时间(小时) = 两地距离除以平均行驶速度
        if (twoPlaceDistanceKm == 0.0 || Double.isNaN(twoPlaceDistanceKm)) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "物流运单装货地址有误!");
        }
        BigDecimal bdDividend = BigDecimal.valueOf(twoPlaceDistanceKm);
        BigDecimal bdDivisor = BigDecimal.valueOf(vehicleAvgSpeed);
        //运输时间小时
        BigDecimal transportTimeHours = bdDividend.divide(bdDivisor, 4, RoundingMode.HALF_UP);
        //运输时间分钟取整 = 往返时间
        Integer transportTimeMinutes = transportTimeHours.multiply(BigDecimal.valueOf(60)).setScale(0, RoundingMode.HALF_UP).intValue();
        //单趟总耗时
        return vehicleLoadingHours + vehicleUnloadingHours + transportTimeMinutes + transportTimeMinutes;
    }


    /**
     * 计算平台配置贸易订单实际派车数
     *
     * @param dto
     * @return
     */
    @Override
    public Integer getActualDisPatch(ActualDisPatchDto dto) {
        //车辆平均载重
        Integer vehicleAvgLoad = dto.getVehicleAvgLoad();
        if (vehicleAvgLoad <= 0) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "车辆平均载重配置需大于0!");
        }
        //缓冲系数
        BigDecimal bufferCoefficient = dto.getBufferCoefficient();
        if (bufferCoefficient.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "缓冲系数配置需大于0!");
        }
        //工作时长
        Integer vehicleWorkHours = dto.getVehicleWorkHours();
        if (vehicleWorkHours <= 0) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "车辆工作时长配置需大于0!");
        }
        //订单天数
        long daysBetween = DateUtils.daysBetween(dto.getStartTime(), dto.getEndTime());
        //总运输时间 = 工作时长 * 订单天数
        Long totalTransportationTime = vehicleWorkHours * daysBetween;
        // 平台单趟耗时
        Integer singleTripTotalTimes = getSingleTripTotalTimes(dto);
        if (singleTripTotalTimes == null && singleTripTotalTimes <= 0) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "单车最大往返次数需大于0!");
        }
        //单车最大往返次数 = 总运输时间/单趟耗时
        BigDecimal totalTimeBig = new BigDecimal(totalTransportationTime);
        BigDecimal singleTripBig = new BigDecimal(singleTripTotalTimes);
        BigDecimal roundTripBig = totalTimeBig.divide(singleTripBig, 2, RoundingMode.HALF_UP);
        Integer maxRoundTripTimes = roundTripBig.setScale(0, RoundingMode.CEILING).intValue();

        //单车总运量 = 车辆平均载重 X 单车最大往返次数
        int totalVehicle = vehicleAvgLoad * maxRoundTripTimes;
        BigDecimal totalVehicleBig = new BigDecimal(totalVehicle);
        //所需车辆数 = 订单总量/单车总运量
        BigDecimal vehiclesNum = dto.getAmount().divide(totalVehicleBig, 0, RoundingMode.CEILING);

        //实际派车 = 所需车辆数 X 缓冲系数（向上取整）
        BigDecimal actualVehicleBig = vehiclesNum.multiply(bufferCoefficient);
        Integer actualVehicle = actualVehicleBig.setScale(0, RoundingMode.FLOOR).intValue();
        return actualVehicle;
    }

    @Override
    public KwsUserResDto queryByAccount(String account) {
        KwsUser kwsUser = kwsUserRepository.queryByAccount( account);
        if (kwsUser != null) {
            KwsUserResDto kwsUserResDto = new KwsUserResDto();
            BeanUtil.copyProperties(kwsUser, kwsUserResDto);
            return kwsUserResDto;
        }
        return null;
    }

    /**
     * 平台单趟耗时
     *
     * @param dto
     * @return
     */
    private Integer getSingleTripTotalTimes(ActualDisPatchDto dto) {
        SingleTripTotalTimeDto totalTimeDto = new SingleTripTotalTimeDto();
        totalTimeDto.setEntId(dto.getEntId());
        totalTimeDto.setLon1(dto.getLon1());
        totalTimeDto.setLat1(dto.getLat1());
        totalTimeDto.setLon2(dto.getLon2());
        totalTimeDto.setLat2(dto.getLat2());
        //行为规则
        totalTimeDto.setVehicleLoadingHours(dto.getVehicleLoadingHours());
        totalTimeDto.setVehicleUnloadingHours(dto.getVehicleUnloadingHours());
        totalTimeDto.setVehicleAvgSpeed(dto.getVehicleAvgSpeed());
        //计算运单单趟耗时
        return calSingleTripTotalTimes(totalTimeDto);

    }

    /**
     * 通过企业id查询user
     * @param entId
     * @return
     */
    public List<KwsUserResDto> queryByEntId(Long entId) {
        // 查询角色
        List<KwsRole> roles = roleRepository.queryByEntId(entId);
        if (CollectionUtils.isEmpty(roles)) {
            return Collections.emptyList();
        }
        Set<Long> roleIds = roles.stream()
                .filter(role -> Objects.equals(role.getName(), "门卫"))
                .map(KwsRole::getId)
                .collect(Collectors.toSet());

        // 查询用户和角色映射
        List<KwsUserRole> userRoles = userRoleRepository.queryByRoleIds(roleIds);
        if (CollectionUtils.isEmpty(userRoles)) {
            return Collections.emptyList();
        }
        Set<Long> userIds = userRoles.stream()
                .map(KwsUserRole::getUserId)
                .collect(Collectors.toSet());

        // 查询用户
        List<KwsUser> kwsUserList = kwsUserRepository.queryByUserIds(userIds);
        if (CollectionUtils.isEmpty(kwsUserList)) {
            return Collections.emptyList();
        }

        return kwsUserList.stream()
                .map(kwsUser -> BeanUtil.copyProperties(kwsUser, KwsUserResDto.class))
                .collect(Collectors.toList());
    }

    /**
     * 通过企业id查询user
     * @param userId
     * @return
     */
    public KwsUserResDto queryByUserId(Long userId) {
        KwsUser kwsUser = kwsUserRepository.queryByUserId(userId);
        if (kwsUser != null) {
            KwsUserResDto kwsUserResDto = new KwsUserResDto();
            BeanUtil.copyProperties(kwsUser, kwsUserResDto);
            return kwsUserResDto;
        }
        return new KwsUserResDto();
    }

}
