package com.fs.ipad;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.core.redis.RedisCacheT;
import com.fs.common.exception.base.BaseException;
import com.fs.common.utils.PubFun;
import com.fs.common.utils.StringUtils;
import com.fs.ipad.param.WxGetSessionRoomListParam;
import com.fs.ipad.param.WxRoomUserListParam;
import com.fs.ipad.param.WxSendAtMsgParam;
import com.fs.ipad.vo.*;
import com.fs.qw.domain.QwExternalContact;
import com.fs.qw.domain.QwGroupChat;
import com.fs.qw.domain.QwUser;
import com.fs.qw.mapper.QwExternalContactMapper;
import com.fs.qw.mapper.QwGroupChatMapper;
import com.fs.sop.domain.QwSop;
import com.fs.sop.domain.SopUserLogs;
import com.fs.sop.mapper.QwSopMapper;
import com.fs.sop.mapper.SopUserLogsMapper;
import com.fs.wxwork.dto.*;
import com.fs.wxwork.service.WxWorkServiceNew;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Slf4j
@Component
@AllArgsConstructor
public class IpadSendUtils {

    private final WxWorkServiceNew wxWorkService;
    private final RedisCacheT<String> redisCache;
    private final QwGroupChatMapper qwGroupChatMapper;
    private final QwSopMapper qwSopMapper;
    private final QwExternalContactMapper qwExternalContactMapper;
    private final SopUserLogsMapper sopUserLogsMapper;
    private final RedisCache redisCacheUrl;
    private final String FILE_KEY = "ipad:upload:";

    /**
     * 发送卡片消息
     */
    public WxWorkResponseDTO<WxwSendLinkMsgRespDTO> sendLink(LinkVo vo){
        WxwSendLinkMsgDTO dto = new WxwSendLinkMsgDTO();
        dto.setUuid(vo.getUuid());
        dto.setSend_userid(userIds(vo));
        dto.setUrl(vo.getUrl());
        dto.setTitle(vo.getTitle());
        dto.setContent(vo.getContent());
        dto.setImgurl(vo.getImgUrl());
        dto.setIsRoom(vo.isRoom());
        return wxWorkService.SendLinkMsg(dto, vo.getServerId());
    }

    /**
     * 发送文本
     */
    public WxWorkResponseDTO<WxWorkSendTextMsgRespDTO> sendTxt(TxtVo vo){
        WxWorkSendTextMsgDTO dto = new WxWorkSendTextMsgDTO();
        dto.setUuid(vo.getUuid());
        dto.setSend_userid(userIds(vo));
        dto.setContent(vo.getContent());
        dto.setIsRoom(vo.isRoom());
        return wxWorkService.SendTextMsg(dto, vo.getServerId());
    }

    // 公共文件获取
    private <T> T getFile(String key, Class<T> clazz, Supplier<T> supplier) {
        String obj = redisCache.getCacheObject(key);
        T t;
        if(StringUtils.isEmpty(obj)){
            t = supplier.get();
            redisCache.setCacheObject(key, JSON.toJSONString(t), 3, TimeUnit.DAYS);
        }else{
            t = JSON.parseObject(obj, clazz);
        }
        return t;
    }

    /**
     * 发送图片
     */
    public WxWorkResponseDTO<WxwSendCDNImgMsgRespDTO> sendImg(FileVo vo){
        WxCdnUploadImgLinkResp resp = getFile(FILE_KEY + "img:" + vo.getUrl(), WxCdnUploadImgLinkResp.class, () -> uploadImage(vo.getUuid(), vo.getServerId(), vo.getUrl()));
        WxwSendCDNImgMsgDTO dto = new WxwSendCDNImgMsgDTO();
        dto.setCdnkey(resp.getCdn_key());
        dto.setAeskey(resp.getAes_key());
        dto.setMd5(resp.getMd5());
        dto.setFileSize(resp.getSize());
        dto.setFileSize(resp.getSize());
        dto.setUuid(vo.getUuid());
        dto.setSend_userid(userIds(vo));
        dto.setIsRoom(vo.isRoom());

        dto.setWidth(resp.getWidth());
        dto.setHeight(resp.getHeight());
        dto.setMid_image_size(resp.getMid_image_size());
        dto.setThumb_file_size(resp.getThumb_file_size());
        dto.setThumb_image_width(resp.getThumb_image_width());
        dto.setThumb_image_height(resp.getThumb_image_height());
        dto.setThumb_file_md5(resp.getThumb_file_md5());
        return wxWorkService.SendCDNImgMsg(dto, vo.getServerId());
    }
    /**
     * 发送文件
     */
    public WxWorkResponseDTO<WxwSendCDNFileMsgRespDTO> sendFile(FileVo vo){
        WxwUploadCdnLinkFileRespDTO resp = getFile(FILE_KEY + "file:" + vo.getUrl(), WxwUploadCdnLinkFileRespDTO.class, () -> uploadFile(vo.getUuid(), vo.getServerId(), vo.getUrl()));
        WxwSendCDNFileMsgDTO dto = new WxwSendCDNFileMsgDTO();
        dto.setCdnkey(resp.getCdn_key());
        dto.setAeskey(resp.getAes_key());
        dto.setMd5(resp.getMd5());
        dto.setFileSize(resp.getSize().longValue());
        dto.setFile_name(vo.getUrl().substring(vo.getUrl().lastIndexOf('/') + 1));
        dto.setUuid(vo.getUuid());
        dto.setSend_userid(userIds(vo));
        dto.setIsRoom(vo.isRoom());
        return wxWorkService.SendCDNFileMsg(dto, vo.getServerId());
    }
    /**
     * 发送文件
     */
    public WxWorkResponseDTO<WxwSendCDNVoiceMsgRespDTO> sendVoice(FileVo vo){
        WxwUploadCdnLinkFileRespDTO resp = getFile(FILE_KEY + "voice:" + vo.getUrl(), WxwUploadCdnLinkFileRespDTO.class, () -> uploadFile(vo.getUuid(), vo.getServerId(), vo.getUrl()));
        WxwSendCDNVoiceMsgDTO dto = new WxwSendCDNVoiceMsgDTO();
        dto.setCdnkey(resp.getCdn_key());
        dto.setVoice_time(vo.getVoiceTime());
        dto.setAeskey(resp.getAes_key());
        dto.setMd5(resp.getMd5());
        dto.setFileSize(resp.getSize());
        dto.setUuid(vo.getUuid());
        dto.setSend_userid(userIds(vo));
        dto.setIsRoom(vo.isRoom());
        return wxWorkService.SendCDNVoiceMsg(dto, vo.getServerId());
    }
    /**
     * 发送文件
     */
    public WxWorkResponseDTO<WxwSendCDNVideoMsgRespDTO> sendVideo(FileVo vo){
        WxCdnUploadVideoResp resp = getFile(FILE_KEY + "voice:" + vo.getUrl(), WxCdnUploadVideoResp.class, () -> uploadVideo(vo.getUuid(), vo.getServerId(), vo.getUrl()));
        WxwSendCDNVideoMsgDTO dto = new WxwSendCDNVideoMsgDTO();
        dto.setCdnkey(resp.getCdn_key());
        dto.setAeskey(resp.getAes_key());
        dto.setMd5(resp.getMd5());
        dto.setFileSize(resp.getSize());
        dto.setUuid(vo.getUuid());
        dto.setSend_userid(userIds(vo));
        dto.setIsRoom(vo.isRoom());
        return wxWorkService.SendCDNVideoMsg(dto, vo.getServerId());
    }
    /**
     * 发送视频号
     */
    public WxWorkResponseDTO<WxwSendVideoNumberRespDTO> sendWxVideo(WxVideoVo vo){
        WxwSendVideoNumberMsgDTO dto = new WxwSendVideoNumberMsgDTO();
        dto.setUuid(vo.getUuid());
        dto.setSend_userid(userIds(vo));
        dto.setIsRoom(vo.isRoom());
        dto.setCoverUrl(vo.getCoverUrl());
        dto.setThumbUrl(vo.getThumbUrl());
        dto.setAvatar(vo.getAvatar());
        dto.setNickname(vo.getNickname());
        dto.setDesc(vo.getDesc());
        dto.setUrl(vo.getUrl());
        dto.setExtras(vo.getExtras());
        dto.setObjectId(vo.getObjectId());
        dto.setObjectNonceId(vo.getObjectNonceId());
        return wxWorkService.SendVideoNumber(dto, vo.getServerId());
    }
    /**
     * 发送小程序
     */
    public WxWorkResponseDTO<WxWorkSendAppMsgRespDTO> sendMiniProgram(MiniProgramVo vo){
        WxCdnUploadImgLinkResp resp = getFile(FILE_KEY + "voice:" + vo.getImgUrl(), WxCdnUploadImgLinkResp.class, () -> uploadImage(vo.getUuid(), vo.getServerId(), vo.getImgUrl()));
        WxWorkSendAppMsgDTO dto = new WxWorkSendAppMsgDTO();
        dto.setCdnkey(resp.getCdn_key());
        dto.setAeskey(resp.getAes_key());
        dto.setMd5(resp.getMd5());
        dto.setFileSize(resp.getSize());
        dto.setUuid(vo.getUuid());
        dto.setSend_userid(userIds(vo));
        dto.setIsRoom(vo.isRoom());
        dto.setDesc(vo.getDesc());
        dto.setTitle(vo.getTitle());
        dto.setWeappIconUrl(vo.getWeappIconUrl());
        dto.setUsername(vo.getUsername());
        dto.setPagepath(vo.getPagepath());
        dto.setAppid(vo.getAppid());
        return wxWorkService.SendAppMsg(dto, vo.getServerId());
    }





    /**
     * 获取发送对象的userid
     * @param vo 调用接口参数
     * @return 返回的userid
     */
    private Long userIds(BaseVo vo){
        if(vo.isRoom()){
            return chatIds(vo);
        }
        WxWorkUserId2VidDTO wxWorkUserId2VidDTO = new WxWorkUserId2VidDTO();
        wxWorkUserId2VidDTO.setOpenid(Collections.singletonList(vo.getExId()));
        wxWorkUserId2VidDTO.setCorpid(vo.getCorpId());
        wxWorkUserId2VidDTO.setScorpid(vo.getCorpCode());
        wxWorkUserId2VidDTO.setUuid(vo.getUuid());
        WxWorkResponseDTO<List<WxWorkVid2UserIdRespDTO>> WxWorkVid2UserIdRespDTO = wxWorkService.UserId2Vid(wxWorkUserId2VidDTO, vo.getServerId());
        List<WxWorkVid2UserIdRespDTO> data = WxWorkVid2UserIdRespDTO.getData();
        if(data.isEmpty()) {
            log.error("未找到用户数据，基础数据：{}，请求数据：{}，返回数据：{}", vo, JSON.toJSONString(wxWorkUserId2VidDTO), JSON.toJSONString(WxWorkVid2UserIdRespDTO));
            throw new BaseException("未找到用户：" + vo.getId());
        }
        return data.get(0).getUser_id();
    }

    /**
     * 获取发送群的ID
     * @param vo 调用接口参数
     * @return 返回的userid
     */
    private Long chatIds(BaseVo vo){
        WxWorkChatIdToRoomIdDTO tdo = new WxWorkChatIdToRoomIdDTO();
        tdo.setChatid(vo.getExId());
        tdo.setCorpid(vo.getCorpId());
        tdo.setUuid(vo.getUuid());
        WxWorkResponseDTO<WxWorkChatIdToRoomIdResp> result = wxWorkService.ChatIdToRoomId(tdo, vo.getServerId());
        if(result.getErrcode() != 0){
            throw new BaseException(result.getErrmsg());
        }
        WxWorkChatIdToRoomIdResp data = result.getData();
        if(data == null || data.getRoom_id() == null) {
            log.error("未找到群聊数据，请求数据：{}，返回数据：{}", JSON.toJSONString(tdo), JSON.toJSONString(result));
            throw new BaseException("未找到群聊：" + vo.getId());
        }
        return data.getRoom_id();
    }

    /**
     * 上传图片
     * @param uuid     登录唯一标识
     * @param serverId 请求服务器ID
     * @param url      上传图片地址
     * @return 上传的返回信息
     */
    private WxCdnUploadImgLinkResp uploadImage(String uuid, Long serverId, String url){
        WxCdnUploadImgLinkDTO dto = new WxCdnUploadImgLinkDTO();
        dto.setUuid(uuid);
        dto.setUrl(enUrl(url));
        WxWorkResponseDTO<WxCdnUploadImgLinkResp> result = wxWorkService.cdnUploadImgLink(dto, serverId);
        if(result.getErrcode() != 0) throw new BaseException("上传图片失败：" + result.getErrmsg());
        return result.getData();
    }
    /**
     * 上传视频
     * @param uuid     登录唯一标识
     * @param serverId 请求服务器ID
     * @param url      上传图片地址
     * @return 上传的返回信息
     */
    private WxCdnUploadVideoResp uploadVideo(String uuid, Long serverId, String url){
        WxCdnUploadVideoLinkDTO dto = new WxCdnUploadVideoLinkDTO();
        dto.setUuid(uuid);
        dto.setUrl(enUrl(url));
        dto.setFilename(url.substring(url.lastIndexOf('/') + 1));
        WxWorkResponseDTO<WxCdnUploadVideoResp> result = wxWorkService.uploadCdnVideoLink(dto, serverId);
        if(result.getErrcode() != 0) throw new BaseException("上传视频失败：" + result.getErrmsg());
        return result.getData();
    }
    /**
     * 上传语言
     * @param uuid     登录唯一标识
     * @param serverId 请求服务器ID
     * @param url      上传图片地址
     * @return 上传的返回信息
     */
    private WxwUploadCdnLinkFileRespDTO uploadSilk(String uuid, Long serverId, String url){
        WxwUploadCdnLinkFileDTO dto = new WxwUploadCdnLinkFileDTO();
        dto.setUuid(uuid);
        dto.setUrl(enUrl(url));
        WxWorkResponseDTO<WxwUploadCdnLinkFileRespDTO> result = wxWorkService.uploadCdnLinkFile(dto, serverId);
        if(result.getErrcode() != 0) throw new BaseException("上传语言失败：" + result.getErrmsg());
        return result.getData();
    }
    /**
     * 上传文件
     * @param uuid     登录唯一标识
     * @param serverId 请求服务器ID
     * @param url      上传图片地址
     * @return 上传的返回信息
     */
    private WxwUploadCdnLinkFileRespDTO uploadFile(String uuid, Long serverId, String url){
        WxwUploadCdnLinkFileDTO dto = new WxwUploadCdnLinkFileDTO();
        dto.setUuid(uuid);
        dto.setUrl(enUrl(url));
        dto.setFilename(url.substring(url.lastIndexOf('/') + 1));
        WxWorkResponseDTO<WxwUploadCdnLinkFileRespDTO> result = wxWorkService.uploadCdnLinkFile(dto, serverId);
        if(result.getErrcode() != 0) throw new BaseException("上传文件失败：" + result.getErrmsg());
        return result.getData();
    }

    /**
     * 上传大文件
     * @param uuid     登录唯一标识
     * @param serverId 请求服务器ID
     * @param url      上传图片地址
     * @return 上传的返回信息
     */
    private WxBigFileUploadLinkResp uploadBigFile(String uuid, Long serverId, String url){
        WxBigFileUploadLinkDTO dto = new WxBigFileUploadLinkDTO();
        dto.setUuid(uuid);
        dto.setFileurl(enUrl(url));
        dto.setFilename(url.substring(url.lastIndexOf('/') + 1));
        WxWorkResponseDTO<WxBigFileUploadLinkResp> result = wxWorkService.bigFileUploadLink(dto, serverId);
        if(result.getErrcode() != 0) throw new BaseException("上传大文件失败：" + result.getErrmsg());
        return result.getData();
    }

    public WxLoginResp isLogin(String uuid, Long serverId){
        WxLoginDTO dto = new WxLoginDTO();
        dto.setUuid(uuid);
        WxWorkResponseDTO<WxLoginResp> result = wxWorkService.isLogin(dto, serverId);
        if(result.getErrcode() != 0) throw new BaseException("验证登录失败：" + result.getErrmsg());
        return result.getData();
    }

    private static String enUrl(String url) {
        try {
            // 先通过URL类自动编码
            URL urlObj = new URL(url);
            // 提取组件并构建URI（自动编码非ASCII字符）
            URI uri = new URI(
                    urlObj.getProtocol(),
                    urlObj.getUserInfo(),
                    urlObj.getHost(),
                    urlObj.getPort(),
                    urlObj.getPath(),
                    urlObj.getQuery(),
                    urlObj.getRef()
            );
            return uri.toASCIIString();
        } catch (MalformedURLException e) {
            throw new BaseException("URL格式异常: " + url + "======" + e.getMessage());
        } catch (URISyntaxException e) {
            throw new BaseException("URI语法异常: " + url + "======" + e.getMessage());
        }
    }

    public void loginOut(String uuid, Long serverId){
        WxWorkGetQrCodeDTO dto = new WxWorkGetQrCodeDTO();
        dto.setUuid(uuid);
        wxWorkService.LoginOut(dto, serverId);
    }
    public List<WxGetSessionRoomListVo.RoomList> getSessionRoomList(String uuid, Long serverId){
        WxGetSessionRoomListParam param = new WxGetSessionRoomListParam();
        param.setUuid(uuid);
        WxWorkResponseDTO<WxGetSessionRoomListVo> result = wxWorkService.getSessionRoomList(param, serverId);
        if(result.getErrcode() != 0) throw new BaseException("获取会话群聊失败：" + result.getErrmsg());
        return result.getData().getRoom_list();
    }

    public List<WxRoomUserListVo.MemberList> getSessionRoomUserList(String uuid, Long roomId, Long serverId){
        WxRoomUserListParam param = new WxRoomUserListParam();
        param.setUuid(uuid);
        param.setRoomid(roomId);
        WxWorkResponseDTO<WxRoomUserListVo> result = wxWorkService.getRoomUserList(param, serverId);
        if(result.getErrcode() != 0) throw new BaseException("获取群聊用户列表错误：" + result.getErrmsg());
        return result.getData().getMember_list();
    }

    public void sendTextAtMsg(WxSendAtMsgParam param, Long serverId){
        WxWorkResponseDTO<WxSendAtMsgVo> result = wxWorkService.sendTextAtMsg(param, serverId);
        log.info("发送返回数据：{}", result);
        if(result.getErrcode() != 0) throw new BaseException("发送@消息错误：" + result.getErrmsg());
    }

    public void sendTxtNoVo(WxWorkSendTextMsgDTO dto, Long serverId){
        WxWorkResponseDTO<WxWorkSendTextMsgRespDTO> result = wxWorkService.SendTextMsg(dto, serverId);
        log.info("发送返回数据：{}", result);
        if(result.getErrcode() != 0) throw new BaseException("发送消息错误：" + result.getErrmsg());
    }

    /**
     * 创建群聊
     * @param qwSop           SOP
     * @param groupName       群聊名称
     * @param qwUser          创建企微账号
     * @param list            客户列表
     * @param maxGroupNum     最大拉群数量
     * @param maxGroupUserNum 单个群聊最大拉取用户数量
     */
    public String createRoom(QwSop qwSop, String groupName, QwUser qwUser, List<QwExternalContact> list, Integer maxGroupNum, Integer maxGroupUserNum, int currentNum) {
        // 最大支持的客户数量
        int maxNum = maxGroupNum * maxGroupUserNum;
        // 根据最大客户数量限制客户
        List<QwExternalContact> joinList = list.stream().limit(maxNum).collect(Collectors.toList());
        // 修改加群状态微 已加群
        joinList.forEach(e -> e.setJoinGroup(1));
        // 用外部联系人ID去换取企微对应的ID
        List<Long> userIds = changeUserIds(qwUser, joinList);
        // 添加的群ID
        List<String> chatIds = new ArrayList<>();
        // 筛选出来的客户可以创建多少个群聊
        int groupNum = BigDecimal.valueOf((double) userIds.size() / maxGroupUserNum).setScale(0, RoundingMode.UP).intValue();
        List<SopUserLogs> logsList = new ArrayList<>();
        // 获取当前日期
        Date currentDate = new Date();
        // 创建格式化器，指定格式为"yyyy年MM月dd日"
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 格式化日期
        String today = sdf.format(currentDate);
        // 循环创建群聊添加客户
        for (int i = 0; i < groupNum; i++) {
            List<Long> collect = userIds.stream().skip((long) i * maxGroupUserNum).limit(maxGroupUserNum).collect(Collectors.toList());
            // 如果人数为空 或者 人数不足最大群聊人数
            if(collect.isEmpty() || collect.size() < maxGroupUserNum) continue;
            // 设置新的群聊名称
            String newGroupName = groupName + (i + 1 + currentNum);
            // 创建群聊对象
            WxCreateRoomMsgDTO dto = new WxCreateRoomMsgDTO();
            // 设置UUID
            dto.setUuid(qwUser.getUid());
            // 设置群聊名称
            dto.setRoomName(newGroupName);
            // 客户ID列表，会自动拉取到群聊里面
            dto.setVids(collect);
            // 请求创建群聊方法
            WxWorkResponseDTO<WxCreateRoomRespDTO> room = wxWorkService.createRoom(dto, qwUser.getServerId());
            // 通过创建群聊接口返回的ID换取系统需要的群聊ID
            String chatId = toChatIds(qwUser.getUid(), room.getData().getRoomid(), qwUser.getServerId());
            // 群聊对象
            QwGroupChat qwGroupChat = new QwGroupChat();
            // 群聊ID
            qwGroupChat.setChatId(chatId);
            // 群聊名称
            qwGroupChat.setName(newGroupName);
            // 对应的SOPID
            qwGroupChat.setSopId(qwSop.getId());
            // 所属的企微ID
            qwGroupChat.setQwUserId(qwUser.getId());
            // 微信对应的群聊ID
            qwGroupChat.setRoomid(room.getData().getRoomid());
            // 创建活修改群聊
            qwGroupChatMapper.insertOrUpdateQwGroupChat(qwGroupChat);
            // 群聊ID添加
            chatIds.add(chatId);
            SopUserLogs sopUserLogs = new SopUserLogs();
            sopUserLogs.setSopId(qwSop.getId());
            sopUserLogs.setSopTempId(qwSop.getTempId());
            sopUserLogs.setQwUserId(qwUser.getQwUserId());
            sopUserLogs.setCorpId(qwSop.getCorpId());
            sopUserLogs.setStartTime(today);
            sopUserLogs.setStatus(1);
            sopUserLogs.setUserId(qwUser.getId() + "|" + qwUser.getCompanyUserId() + "|" + qwUser.getCompanyId());
            sopUserLogs.setChatId(chatId);
            logsList.add(sopUserLogs);
        }
        // 更新客户信息
        qwExternalContactMapper.updateJoinGroup(PubFun.listToNewList(joinList, QwExternalContact::getId));
        // 组装群聊ID
        String chatId = String.join(",", chatIds);
        // 修改SOP对象
        qwSopMapper.updateSopGroupIds(qwSop.getId(), chatId);
        sopUserLogsMapper.batchInsertSopUserLogs(logsList);
        return chatId;
    }
    private String toChatIds(String uuid, Long roomid, Long serverId) {
        WxWorkChatIdToRoomIdDTO tdo = new WxWorkChatIdToRoomIdDTO();
        tdo.setRoom_id(roomid);
        tdo.setUuid(uuid);
        WxWorkResponseDTO<WxWorkChatIdToRoomIdResp> result = wxWorkService.RoomIdToChatId(tdo, serverId);
        if(result.getErrcode() != 0){
            throw new BaseException(result.getErrmsg());
        }
        WxWorkChatIdToRoomIdResp data = result.getData();
        if(data == null || data.getRoom_id() == null) {
            log.error("未找到群聊数据，请求数据：{}，返回数据：{}", JSON.toJSONString(tdo), JSON.toJSONString(result));
            throw new BaseException("未找到群聊：" + roomid);
        }
        return data.getChatid();
    }

    private List<Long> changeUserIds(QwUser qwUser, List<QwExternalContact> joinList) {
        BaseVo vo = new BaseVo();
        vo.setId(qwUser.getId());
        vo.setRoom(false);
        vo.setUuid(qwUser.getUid());
        vo.setExIdList(joinList.stream().map(QwExternalContact::getExternalUserId).collect(Collectors.toList()));
        vo.setServerId(qwUser.getServerId());
        return userIdList(vo);
    }
    private List<Long> userIdList(BaseVo vo){
        if(vo.isRoom()){
            return Collections.emptyList();
        }
        WxWorkUserId2VidDTO wxWorkUserId2VidDTO = new WxWorkUserId2VidDTO();
        wxWorkUserId2VidDTO.setOpenid(vo.getExIdList());
        wxWorkUserId2VidDTO.setCorpid(vo.getCorpId());
        wxWorkUserId2VidDTO.setScorpid(vo.getCorpCode());
        wxWorkUserId2VidDTO.setUuid(vo.getUuid());
        WxWorkResponseDTO<List<WxWorkVid2UserIdRespDTO>> resutl = wxWorkService.UserId2Vid(wxWorkUserId2VidDTO, vo.getServerId());
        List<?> rawData = resutl.getData(); // 先用一个泛型不确定的列表接收
        if(rawData.isEmpty()) {
            log.error("未找到用户数据，基础数据：{}，请求数据：{}，返回数据：{}", vo, JSON.toJSONString(wxWorkUserId2VidDTO), JSON.toJSONString(resutl));
            throw new BaseException("未找到用户：" + vo.getId());
        }
        List<WxWorkVid2UserIdRespDTO> data = new ArrayList<>();
        for (Object item : rawData) {
            if (item instanceof WxWorkVid2UserIdRespDTO) {
                data.add((WxWorkVid2UserIdRespDTO) item);
            } else if (item instanceof JSONObject) {
                // 如果是JSONObject，则需要将其转换为目标类型
                WxWorkVid2UserIdRespDTO dto = ((JSONObject) item).toJavaObject(WxWorkVid2UserIdRespDTO.class);
                data.add(dto);
            } else {
                log.warn("未知类型: {}", item.getClass());
                // 根据实际情况处理，例如跳过或抛出更明确的异常
            }
        }
        return data.stream().map(WxWorkVid2UserIdRespDTO::getUser_id).collect(Collectors.toList());
    }
}
