package com.cmeeting.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmeeting.ad.entity.SysUserSync;
import com.cmeeting.constant.MeetingState;
import com.cmeeting.dto.UserDTO;
import com.cmeeting.log.service.ProcessLogService;
import com.cmeeting.mapper.primary.*;
import com.cmeeting.pojo.*;
import com.cmeeting.service.ModulePermissionService;
import com.cmeeting.service.SysUserSyncService;
import com.cmeeting.service.TencentMeetingService;
import com.cmeeting.util.RedisUtils;
import com.cmeeting.util.SignatureUtil;
import com.cmeeting.util.TencentMeetingApiUtil;
import com.cmeeting.vo.CorpRecordsVO;
import com.cmeeting.vo.TencentMeetingVO;
import com.google.gson.*;
import com.tencentcloudapi.wemeet.Client;
import com.tencentcloudapi.wemeet.core.authenticator.AuthenticatorBuilder;
import com.tencentcloudapi.wemeet.core.authenticator.JWTAuthenticator;
import com.tencentcloudapi.wemeet.core.exception.ClientException;
import com.tencentcloudapi.wemeet.core.exception.ServiceException;
import com.tencentcloudapi.wemeet.service.meetings.api.MeetingsApi;
import com.tencentcloudapi.wemeet.service.meetings.model.*;
import com.tencentcloudapi.wemeet.service.user_manager.api.UserManagerApi;
import com.tencentcloudapi.wemeet.service.user_manager.model.V1UsersListGet200Response;
import com.tencentcloudapi.wemeet.service.user_manager.model.V1UsersListGet200ResponseUsersInner;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class TencentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper, TencentMeetingUser> implements TencentMeetingService {
    @Resource
    private TecentMeetingMapper tecentMeetingMapper;
    @Resource
    private MeetingInfoMapper meetingInfoMapper;
    @Resource
    private AuthMapper authMapper;
    @Resource
    private SysUserSyncMapper sysUserSyncMapper;
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private ProcessLogService processLogService;
    @Resource
    private ModulePermissionService modulePermissionService;
    @Resource
    private SysUserSyncService sysUserSyncService;
    @Resource
    private UserIdMapper userIdMapper;
    @Resource
    private WeComUserMapper weComUserMapper;


    private static final String HMAC_ALGORITHM = "HmacSHA256";
    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    @Value(value = "${tencent.search-scope}")
    private Integer searchDays;
    /**
     * 查询会议不得早于这个时间
     */
    @Value(value = "${tencent.search-end-time}")
    private String searchEndTime;
    @Value(value = "${tencent.appId}")
    private String tencentAppId;
    @Value(value = "${tencent.sdkId}")
    private String tencentSdkId;
    @Value(value = "${tencent.secretId}")
    private String tencentSecretId;
    @Value(value = "${tencent.secretKey}")
    private String tencentSecretKey;
    @Value(value = "${tencent.admin.userId}")
    private String tencentAdminUserId;
    @Value(value = "${permission.applicationId}")
    private String permissionApplicationId;
    @Value(value = "${permission.tenantId}")
    private String permissionTenantId;

    @Override
    public void batchInsert(List<TencentMeetingUser> users) {
        tecentMeetingMapper.batchInsertUsers(users);
    }


    @Override
    public void doUsers() {
        // 获取到全部用户
        List<TencentMeetingUser> users = fetchUsersInBatches();
        ;
        // 检查重名并设置标志
        markDuplicateNamesTecent(users);
        // 批量插入数据库（分批次）
        int batchSize = 1000;
        for (int i = 0; i < users.size(); i += batchSize) {
            List<TencentMeetingUser> batch = users.subList(i, Math.min(i + batchSize, users.size()));
            batchInsert(batch);
        }

    }

    /**
     * 获取会议信息以及会议对应的转录文件信息
     * @return
     */
    @Override
    public List<TencentMeetingVO.RecordFile> getMeetingFiles() {
        List<TencentMeetingVO.RecordFile> meetingFiles = new ArrayList<>();
        List<MeetingInfo> meetingSaveList = new ArrayList<>();
        // 查询近searchDays天的会议录制列表
        try {
            ZonedDateTime now = ZonedDateTime.now();
            long startTime = now.minusDays(searchDays).toEpochSecond();
            long endTime = now.toEpochSecond();
            try {
                long end = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(searchEndTime).getTime() / 1000;
                //仅查询2025-07-30 23:59:59之后的会议
                if (end > endTime) {
                    return new ArrayList<>();
                }
                if (end > startTime) {
                    startTime = end;
                }
            } catch (Exception e) {
                log.error("参数searchEndTime格式错误！");
            }

            AtomicInteger currentPage = new AtomicInteger(1);

            //获取总页数
            CorpRecordsVO firstData = fetchMeetingRecords(tencentAdminUserId, 1, startTime, endTime, 1, 20);
            Integer totalPage = firstData.getTotalPage();
            log.info("总页数: {}", totalPage);
            //目前已存储的会议id
            List<TencentMeetingVO.SimpleMeetingInfo> meetingIds = meetingInfoMapper.getAllMeetingIds();
            List<TencentMeetingUser> meetingUsers = tecentMeetingMapper.getAlluser2();
            Map<String, String> meetingMap = meetingUsers.stream().collect(Collectors.toMap(TencentMeetingUser::getUserId, TencentMeetingUser::getUserName));
            while (currentPage.intValue() <= totalPage){
                CorpRecordsVO data = fetchMeetingRecords(tencentAdminUserId, 1, startTime, endTime, currentPage.getAndIncrement(), 20);
                //设置总页数
                if (data != null && data.getRecordMeetings() != null && !data.getRecordMeetings().isEmpty()) {
                    List<CorpRecordsVO.RecordMeeting> meetings = data.getRecordMeetings();
                    for (CorpRecordsVO.RecordMeeting meeting : meetings) {
                        //录制文件未转码完成，跳过 1：录制中 2：转码中 3：转码完成
                        if (meeting.getState() != 3) {
                            continue;
                        }
                        log.info("【会议定时检索】转录文件的meetingId->{}，recordFileId->{}", meeting.getMeetingId(), meeting.getMeetingRecordId());
                        //查询会议详情
                        String meetingId = meeting.getMeetingId();
                        String meetingRecordId = meeting.getMeetingRecordId();
                        if (meetingRecordId == null) {
                            log.error("记录不存在！");
                            continue;
                        }
                        String subMeetingId = null;
                        LocalDateTime mediaStartTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(Long.valueOf(meeting.getMediaStartTime())), ZoneId.systemDefault());
                        String hostId = "";
                        try {
                            String userid = meeting.getUserid();
                            //获取子会议id
                            V1HistoryMeetingsUseridGet200Response v1HistoryMeetingsUseridGet200Response = TencentMeetingApiUtil.ApiV1HistoryMeetingsUseridGetRequest(userid, meeting.getMeetingCode(),
                                    String.valueOf(mediaStartTime.toLocalDate().atStartOfDay().atZone(ZoneId.systemDefault()).toEpochSecond()),
                                    String.valueOf(mediaStartTime.toLocalDate().atStartOfDay().plusDays(1).atZone(ZoneId.systemDefault()).toEpochSecond()));
                            if (v1HistoryMeetingsUseridGet200Response == null) {
                                continue;
                            }
                            List<V1HistoryMeetingsUseridGet200ResponseMeetingInfoListInner> historyMeetingInfoList = v1HistoryMeetingsUseridGet200Response.getMeetingInfoList();
                            if (CollectionUtils.isEmpty(historyMeetingInfoList)) {
                                log.error("会议未结束，获取子会议id信息失败");
                                continue;
                            }
                            V1HistoryMeetingsUseridGet200ResponseMeetingInfoListInner historyMeeting = historyMeetingInfoList.get(0);
                            //如果是周期会议
                            if (historyMeeting.getMeetingType() == 1) {
                                subMeetingId = historyMeeting.getSubMeetingId();
                            }

                            List<CorpRecordsVO.RecordFile> recordFiles = meeting.getRecordFiles();
                            //按转录文件时间升序，便于后续的内容拼接
                            List<String> recordFileIdList = recordFiles.stream().sorted(Comparator.comparingLong(CorpRecordsVO.RecordFile::getRecordStartTime))
                                    .map(CorpRecordsVO.RecordFile::getRecordFileId).collect(Collectors.toList());

                            boolean flag = true;
                            if (CollUtil.isNotEmpty(meetingIds)) {
                                for (TencentMeetingVO.SimpleMeetingInfo meetingInfo : meetingIds) {
                                    String meetingRecordIdTemp = meetingInfo.getMeetingRecordId();
                                    if (meetingRecordIdTemp != null && meetingRecordIdTemp.equals(meetingRecordId)) {
                                        flag = false;
                                        break;
                                    }
                                }
                            }

                            //如果数据库中已有相同会议id的记录，跳过同步
                            if(flag){
                                log.info("【会议检索】新的会议记录MeetingRecordId->:{}, meetingId->{}, recordIds: {}", meetingRecordId,meeting.getMeetingId(), String.join(",", recordFileIdList));

                                String hostName;
                                //优先使用会议列表中已有的主持人字段
                                if (StringUtils.isNotEmpty(meeting.getHostUserId())) {
                                    hostId = meeting.getHostUserId();
                                    hostName = meetingMap.getOrDefault(hostId, null);
                                    log.info("从会议列表中成功获取到主持人信息, hostId: {}", hostId);
                                } else {
                                    //判断主持人是否存在，如果主持人未参会，是查不到主持人的
                                    //如果主持人未参会，使用会议详情中的创建人作为主持人
                                    V1MeetingsMeetingIdGet200Response meetingResponseData = TencentMeetingApiUtil.ApiV1MeetingsMeetingIdGetRequest(meetingId);
                                    if (meetingResponseData == null) {
                                        continue;
                                    }
                                    List<V1MeetingsMeetingIdGet200ResponseMeetingInfoListInner> meetingInfoList = meetingResponseData.getMeetingInfoList();
                                    V1MeetingsMeetingIdGet200ResponseMeetingInfoListInner meetingInfo = meetingInfoList.get(0);
                                    //会议详情中有主持人信息
                                    if (!CollectionUtils.isEmpty(meetingInfo.getCurrentHosts())) {
                                        log.info("尝试从会议详情中获取主持人信息");
                                        hostId = meetingInfo.getCurrentHosts().get(0).getUserid();
                                        hostName = meetingMap.containsKey(hostId) ?  meetingMap.get(hostId) :null;
                                    } else {
                                        // 用户角色
                                        // 0：普通成员角色 1：创建者角色 2：主持人 3：创建者+主持人 4：游客 5：游客+主持人 6：联席主持人 7：创建者+联席主持人
                                        // 主持人角色
                                        List<Long> hostRoleList = Arrays.asList(2L, 3L, 5L, 6L, 7L);
                                        V1MeetingsMeetingIdParticipantsGet200Response participantsData = TencentMeetingApiUtil.ApiV1MeetingsMeetingIdParticipantsGetRequest(meetingId, subMeetingId);
                                        if (participantsData == null) {
                                            continue;
                                        }
                                        List<V1MeetingsMeetingIdParticipantsGet200ResponseParticipantsInner> participants = participantsData.getParticipants();
                                        Optional<V1MeetingsMeetingIdParticipantsGet200ResponseParticipantsInner> host = participants.stream().filter(item -> hostRoleList.contains(item.getUserRole())).findFirst();
                                        if (host.isPresent()) {
                                            hostId = host.get().getUserid();
                                            hostName = new String(Base64.getDecoder().decode(host.get().getUserName()));
                                        }else{
                                            log.error("未找到主持人，默认没有生成纪要权限, meetId: {}, subId: {}", meetingId, subMeetingId);
                                            continue;
                                        }
                                    }
                                }

                                //1. 企业微信授权，然后通过企业微信创建会议绑定上腾讯会议ID成功 则为企业微信授权
                                UserId temp = userIdMapper.selectOne(new LambdaQueryWrapper<UserId>().eq(UserId::getTid, hostId));
                                if (temp == null) {
                                    throw new RuntimeException("企业微信未授权！");
                                }
                                String userId = temp.getWid();
                                log.info("用户: {}, uid是否绑定企业微信: {}", userId, true);

                                // 2. 会议助手后台页面（用户权限调整）-授权用户清单中包括
                                List<SysUserSyncCategory> categoryList = sysUserSyncService.getCategoryListByUserId(userId);
                                List<String> deptIds = categoryList.stream().map(SysUserSyncCategory::getDeptId).collect(Collectors.toList());
                                if (!modulePermissionService.checkAdminPermission(deptIds, userId)) {
                                    throw new RuntimeException("该用户未授权会议纪要功能！");
                                }
                                log.info("用户: {}, 超管是否授权给用户: {}", userId, true);

                                // 3. 用户或超管取消个人纪要功能权限
                                boolean generateAccess = modulePermissionService.personalStatus(userId);
                                log.info("用户: {}, 个人是否开启纪要功能: {}", userId, generateAccess);

                                // 4. 个人是否取消推送邮箱功能
                                //emailPushAccess = generateAccess && (weComUserMap.containsKey(userDTO.getWid()) ? weComUserMap.get(userDTO.getWid()).getEmailPushAccess() : Boolean.FALSE);
                                WeComUser weComUser = weComUserMapper.selectOne(new LambdaQueryWrapper<WeComUser>().eq(WeComUser::getUserId, userId));
                                boolean emailPushAccess = generateAccess && weComUser.getEmailPushAccess();
                                log.info("用户: {},是否推送邮箱: {}", userId, emailPushAccess);

                                // 5. 查询个人邮箱
                                SysUserSync sysUserSync = sysUserSyncMapper.selectOne(new LambdaQueryWrapper<SysUserSync>().eq(SysUserSync::getUserId, userId).last("limit 1"));
                                String email = sysUserSync.getEmail() != null ? sysUserSync.getEmail() : "";

                                // 查询会议开始和结束时间
                                MeetingInfo startAndEndTimeByMeetingId = TencentMeetingApiUtil.getStartAndEndTimeByMeetingId(meetingId);
                                //会议基本信息保存
                                MeetingInfo meetingItem = MeetingInfo.builder()
                                        .meetingRecordId(meetingRecordId)
                                        .meetingId(meetingId)
                                        .meetingCode(meeting.getMeetingCode())
                                        .subject(meeting.getSubject())
                                        .startTime(startAndEndTimeByMeetingId != null ? startAndEndTimeByMeetingId.getStartTime() : mediaStartTime)
                                        .endTime(startAndEndTimeByMeetingId != null ? startAndEndTimeByMeetingId.getEndTime() : null)
                                        .isGenerated(Boolean.FALSE).emailGenerateAccess(generateAccess)
                                        .emailPushAccess(emailPushAccess).isPushed(Boolean.FALSE).syncTime(LocalDateTime.now())
                                        .subMeetingId(subMeetingId).generateRetry(Boolean.FALSE).pushRetry(Boolean.FALSE)
                                        .host(hostName)
                                        .hostUid(hostId)
                                        .status(MeetingState.NEW.getCode())
//                                            .participantUsers(participants.stream()
//                                                    .map(item->new String(Base64.getDecoder().decode(item.getUserName()))).distinct().collect(Collectors.joining("、")))
                                        .recordFileId(String.join(",", recordFileIdList))
                                        .email(email)
                                        .build();

                                meetingFiles.add(TencentMeetingVO.RecordFile.builder()
                                        .meetingId(meetingId)
                                        .subMeetingId(subMeetingId)
                                        .meetingRecordId(meetingRecordId)
                                        .recordFileIdList(recordFileIdList).build());
                                meetingSaveList.add(meetingItem);
                            }
                        } catch (Exception e) {
                            if (e instanceof NoSuchElementException) {
                                log.error("智能体没权限, meetingId: {}, hostId: {}", meetingId, hostId);
                            } else {
                                log.error(e.getMessage());
                            }
                        }
                    }
                }
            }
            if(meetingSaveList.size() > 0){
                meetingInfoMapper.batchInsert(meetingSaveList);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            processLogService.log(null, null, sw.toString());
            throw new RuntimeException(e.getMessage());
        }
        return meetingFiles;
    }

    /**
     * 获取有权限的人员
     *
     * @param userIdRelations
     * @return
     */
    @Override
    public List<UserDTO> getAccessUserIds(Map<String, String> userIdRelations) {
        try {
            //权限控制-- 管理员和授权用户都包括
            List<CoreModulePermissions> auths = authMapper.getAuthByTargetId(permissionApplicationId, permissionTenantId);
            //1. 授权的部门,type为1的为人员，为0表示部门
            List<CoreModulePermissions> authDepts = auths.stream().filter(item -> item.getType().equals(0)).collect(Collectors.toList());
            List<String> deptPath = new ArrayList<>();
            for (CoreModulePermissions authDept : authDepts) {
                String deptId = authDept.getRelId();
                getDeptPath(deptPath, deptId);
            }
            //已被授权部门下的userid
            List<String> accessUserIds = !CollectionUtils.isEmpty(deptPath) ? sysUserSyncMapper.getUsersByDept(deptPath) : new ArrayList<>();

            //2. 已被直接授权的人员追加进去
            accessUserIds.addAll(auths.stream().filter(item -> item.getType().equals(1)).map(CoreModulePermissions::getRelId).collect(Collectors.toList()));
            if (!CollectionUtils.isEmpty(accessUserIds)) {
                //查出人员邮箱
                List<UserDTO> userEmailList = sysUserSyncMapper.getUserEmail();
                Map<String, UserDTO> userEmailMap = CollectionUtils.isEmpty(userEmailList) ? new HashMap<>()
                        : userEmailList.stream().collect(Collectors.toMap(UserDTO::getWid, Function.identity(), (existing, replacement) -> existing));

                List<UserDTO> accessUsers = new ArrayList<>();
                for (String accessUserId : accessUserIds) {
                    if (userIdRelations.containsKey(accessUserId)) {
                        UserDTO accessUser = new UserDTO();
                        accessUser.setWid(accessUserId);
                        accessUser.setTid(userIdRelations.get(accessUserId));
                        if (userEmailMap.containsKey(accessUserId)) {
                            UserDTO emailMsg = userEmailMap.get(accessUserId);
                            accessUser.setEmail(emailMsg.getEmail());
                        }
                        accessUsers.add(accessUser);
                    }
                }
                return accessUsers;
            }
            return new ArrayList<>();
        } catch (Exception e) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            processLogService.log(null, null, sw.toString());
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取部门的路径
     *
     * @param deptPath
     * @param deptId
     */
    private void getDeptPath(List<String> deptPath, String deptId) {
        if (!deptPath.contains(deptId)) deptPath.add(deptId);
        List<String> subDeptIds = sysUserSyncMapper.getSubDeptId(deptId);
        if (CollectionUtils.isEmpty(subDeptIds)) return;

        for (String subDeptId : subDeptIds) {
            //部门id去重
            if (!deptPath.contains(subDeptId)) {
                deptPath.add(subDeptId);
                getDeptPath(deptPath, subDeptId);
            }
        }

    }

    /**
     * 拉取账户级的会议记录列表
     *
     * @param operatorId
     * @param operatorIdType
     * @param startTime
     * @param endTime
     * @param page
     * @param pageSize
     * @throws Exception
     */
    public CorpRecordsVO fetchMeetingRecords(String operatorId, int operatorIdType, long startTime, long endTime, int page, int pageSize)
            throws Exception {
        String uri = String.format(
                "/v1/corp/records?start_time=%d&end_time=%d&page=%d&page_size=%d&operator_id=%s&operator_id_type=%d",
                startTime, endTime, page, pageSize, operatorId, operatorIdType
        );

        String httpMethod = "GET";
        String nonce = String.valueOf(new Random().nextInt(100000));
        String timestamp = String.valueOf(Instant.now().getEpochSecond());

        // 3. 生成签名
        String signature = SignatureUtil.generateSignature(tencentSecretId, tencentSecretKey, httpMethod, nonce, timestamp, uri, "");
        log.info("fetchMeetingRecords params: {}, {}", page, pageSize);
        // 4. 发送请求
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet("https://api.meeting.qq.com" + uri);
            request.setHeader("X-TC-Key", tencentSecretId);
            request.setHeader("X-TC-Timestamp", timestamp);
            request.setHeader("X-TC-Nonce", nonce);
            request.setHeader("X-TC-Signature", signature);
            request.setHeader("AppId", tencentAppId);
            request.setHeader("SdkId", tencentSdkId);

            // 5. 解析响应
            String response = EntityUtils.toString(httpClient.execute(request).getEntity());
            JsonObject jsonResponse = JsonParser.parseString(response).getAsJsonObject();
            Gson gson = new GsonBuilder()
                    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                    .create();

            // 将 JsonObject 转换为实体类
            CorpRecordsVO corpRecords = gson.fromJson(jsonResponse, CorpRecordsVO.class);
            return corpRecords;
        }
    }

    /**
     * 标记企业微信重名用户
     */
    public static void markDuplicateNamesTecent(List<TencentMeetingUser> users) {
        // 按姓名分组，统计每个名字出现的次数
        Map<String, Long> nameCountMap = users.stream()
                .collect(Collectors.groupingBy(TencentMeetingUser::getUserName, Collectors.counting()));

        // 设置是否重名标志
        users.forEach(user -> {
            if (nameCountMap.get(user.getUserName()) > 1) {
                user.setIsrepeatName("1"); // 重名
            } else {
                user.setIsrepeatName("0"); // 不重名
            }
        });
    }

    /**
     * 腾讯会议通过通讯录获取员工信息
     *
     * @return
     */
    private List<TencentMeetingUser> fetchUsersInBatches() {
        if (redisUtils.hasKey("TENCENT_USER_ARRAY")) {
            return (List<TencentMeetingUser>) redisUtils.get("TENCENT_USER_ARRAY");
        }
        //构造client客户端
        Client client = new Client.Builder()
                .withAppId(tencentAppId).withSdkId(tencentSdkId)
                .withSecret(tencentSecretId, tencentSecretKey)
                .build();
        //先请求一条数据，获取到数据总量
        UserManagerApi.ApiV1UsersListGetRequest firstRequest =
                new UserManagerApi.ApiV1UsersListGetRequest.Builder()
                        .page(String.valueOf(1))
                        .pageSize(String.valueOf(1))
                        .operatorId(tencentAdminUserId)
                        .operatorIdType("1")
                        .build();
        UserManagerApi.ApiV1UsersListGetResponse firstResponse;
        try {
            firstResponse = client.user_manager().v1UsersListGet(firstRequest, new JWTAuthenticator.Builder()
                    .nonce(BigInteger.valueOf(Math.abs((new SecureRandom()).nextInt())))
                    .timestamp(String.valueOf(System.currentTimeMillis() / 1000L)));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取腾会人员信息失败");
            return new ArrayList<>();
        }
        Long totalUsers = firstResponse.getData().getTotalCount();

        // 使用线程安全的集合存储结果
        List<TencentMeetingUser> resultList = Collections.synchronizedList(new ArrayList<>());


        Integer pageSize = 20;
        int maxPage = (totalUsers.intValue() + pageSize - 1) / pageSize;
        for (int currentPage = 1; currentPage <= maxPage; currentPage++) {
            try {
                // 1. 构造请求参数
                UserManagerApi.ApiV1UsersListGetRequest request =
                        new UserManagerApi.ApiV1UsersListGetRequest.Builder()
                                .page(String.valueOf(currentPage))
                                .pageSize(String.valueOf(pageSize))
                                .operatorId(tencentAdminUserId)
                                .operatorIdType("1")
                                .build();

                // 2. 构造JWT鉴权器
                AuthenticatorBuilder<JWTAuthenticator> authenticatorBuilder =
                        new JWTAuthenticator.Builder()
                                .nonce(BigInteger.valueOf(Math.abs((new SecureRandom()).nextInt())))
                                .timestamp(String.valueOf(System.currentTimeMillis() / 1000L));

                // 3. 发送请求
                UserManagerApi.ApiV1UsersListGetResponse response =
                        client.user_manager().v1UsersListGet(request, authenticatorBuilder);

                V1UsersListGet200Response responseData = response.getData();
                List<V1UsersListGet200ResponseUsersInner> users = responseData.getUsers();

                System.out.printf("第 %d 页，获取到 %d 个用户:\n", currentPage, responseData.getCurrentSize());

                // 4. 处理响应并转换为TencentMeetingUser对象
                for (V1UsersListGet200ResponseUsersInner user : users) {
                    // 创建TencentMeetingUser对象并设置属性
                    TencentMeetingUser meetingUser = new TencentMeetingUser();
                    meetingUser.setUserId(user.getUserid());
                    meetingUser.setUserName(user.getUsername());
                    meetingUser.setIsrepeatName("0"); // 默认设为不重名，可根据实际业务调整

                    resultList.add(meetingUser);  // 添加到集合
                    System.out.printf("用户ID: %s, 用户名: %s\n", user.getUserid(), user.getUsername());
                }

            } catch (ClientException e) {
                System.out.printf("客户端错误: %s\n", e);
                throw new RuntimeException(e);
            } catch (ServiceException e) {
                System.out.printf("服务端错误: %s\n", e);
                System.out.printf("完整响应: %s\n", new String(e.getApiResp().getRawBody()));
                throw new RuntimeException(e);
            }
        }
        redisUtils.set("TENCENT_USER_ARRAY", resultList);
        // 输出结果
        System.out.printf("\n所有用户获取完成，共获取 %d 个用户\n", resultList.size());
        return resultList;
    }

    /**
     * 通过meetingCode获取到会议主持人对应的腾讯会议userid
     *
     * @param meetingCode
     * @return
     */
    @Override
    public String getMeetingHost(String meetingCode) {
        /**
         * 腾讯会议参数
         */
        Client client = new Client.Builder()
                .withAppId(tencentAppId).withSdkId(tencentSdkId)
                .withSecret(tencentSecretId, tencentSecretKey)
                .build();
        MeetingsApi.ApiV1MeetingsGetRequest request =
                new MeetingsApi.ApiV1MeetingsGetRequest.Builder()
                        .userid(tencentAdminUserId)
                        .instanceid("1")
                        .meetingCode(meetingCode)
                        .build();

        try {
            MeetingsApi.ApiV1MeetingsGetResponse response =
                    client.meetings().v1MeetingsGet(request,
                            new JWTAuthenticator.Builder()
                                    .nonce(BigInteger.valueOf(Math.abs((new SecureRandom()).nextInt())))
                                    .timestamp(String.valueOf(System.currentTimeMillis() / 1000L)));
            // 提取主持人 userid
            if (response == null || response.getData() == null) {
                return null;
            }
            V1MeetingsGet200Response responseData = response.getData();
            if (responseData.getMeetingInfoList() == null || responseData.getMeetingInfoList().isEmpty()) {
                return null;
            }
            V1MeetingsGet200ResponseMeetingInfoListInner meetingInfo = responseData.getMeetingInfoList().get(0);
            if (meetingInfo.getCurrentHosts() == null || meetingInfo.getCurrentHosts().isEmpty()) {
                return null;
            }
            String hostUserId = meetingInfo.getCurrentHosts().get(0).getUserid();
            log.info("成功获取主持人userid: {}", hostUserId);
            return hostUserId;
        } catch (Exception e) {
            return null;
        }
    }

}
