package com.tzld.piaoquan.api.job.wecom.thirdpart;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.tzld.piaoquan.api.component.WeComThirdPartyApiClient;
import com.tzld.piaoquan.api.dao.mapper.wecom.thirdpart.ThirdPartWeComRoomMapper;
import com.tzld.piaoquan.api.dao.mapper.wecom.thirdpart.ext.ThirdPartWeComMapperExt;
import com.tzld.piaoquan.api.model.param.wecom.thirdpart.*;
import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComRoom;
import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComRoomUser;
import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComStaff;
import com.tzld.piaoquan.api.model.po.wecom.thirdpart.ThirdPartWeComStaffUser;
import com.tzld.piaoquan.api.service.wecom.thirdparty.WeComThirdPartyService;
import com.tzld.piaoquan.growth.common.utils.DateUtil;
import com.tzld.piaoquan.growth.common.utils.RedisUtils;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class WeComCreateRoomJob {

    @Autowired
    WeComThirdPartyService weComThirdPartyService;
    @Autowired
    WeComThirdPartyApiClient apiClient;
    @Autowired
    WeComUserDetailJob userDetailJob;
    @Autowired
    ThirdPartWeComRoomMapper roomMapper;
    @Autowired
    ThirdPartWeComMapperExt thirdPartWeComMapperExt;

    @Autowired
    private RedisUtils redisUtils;

    @Value("${create.room.member.max.nums:39}")
    private Integer memberMaxNums;
    @Value("${create.room.daily.max.num:5}")
    private Integer dailyMaxNum;
    @Value("${create.room.daily.max.add.user.times:5}")
    private Integer dailyMaxAddUserTimes;
    @Value("${create.room.name.prefix:票圈快看}")
    private String roomNamePrefix;

    private final static ExecutorService pool = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(1000),
            new ThreadFactoryBuilder().setNameFormat("WeComCreateRoomJob-%d").build(),
            new ThreadPoolExecutor.AbortPolicy());

    @XxlJob("autoCreateRoom")
    public ReturnT<String> autoCreateRoomJob(String param) {
        List<ThirdPartWeComStaff> activeStaffList = weComThirdPartyService.getActiveStaffList();
        CountDownLatch cdl = new CountDownLatch(activeStaffList.size());
        for (ThirdPartWeComStaff staff : activeStaffList) {
            if (staff.getAutoCreateRoom() != 1) {
                cdl.countDown();
                continue;
            }
            pool.execute(() -> {
                try {
                    createStaffRoom(staff);
                } catch (Exception e) {
                    log.error("autoCreateRoomJob error", e);
                } finally {
                    cdl.countDown();
                }
            });
        }
        try {
            cdl.await();
        } catch (InterruptedException e) {
            log.error("autoCreateRoomJob error", e);
        }
        return ReturnT.SUCCESS;
    }

    private void createStaffRoom(ThirdPartWeComStaff staff) {
        // 获取所有未加群客户
        List<ThirdPartWeComStaffUser> staffUserList = thirdPartWeComMapperExt.getNoGroupStaffUserList(staff.getThirdStaffId());
        if (CollectionUtils.isEmpty(staffUserList)) {
            return;
        }
        // 已创建群添加群成员
        List<ThirdPartWeComRoom> roomList = weComThirdPartyService.getAllStaffRoomList(staff.getId());
        List<Integer> roomNums = roomList.stream()
                .map(o -> {
                    try {
                        String roomName = o.getName();
                        if (!roomName.contains(roomNamePrefix)) {
                            return null;
                        }
                        return Integer.parseInt(roomName.replace(roomNamePrefix, ""));
                    } catch (Exception e) {
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .sorted(Comparator.comparing(Integer::intValue).reversed())
                .collect(Collectors.toList());
        Integer maxRoomNum = CollectionUtils.isNotEmpty(roomNums) ? roomNums.get(0) : 0;
        // 获取当日新创建群 达到上限 不创建
        Long roomCount = weComThirdPartyService.getTodayCreateRoomCount(staff.getId());
        if (roomCount >= dailyMaxNum) {
            return;
        }
        // 未加群客户创建新群
        if (CollectionUtils.isNotEmpty(staffUserList)) {
            createNewRoom(staff, staffUserList, maxRoomNum);
        }
        userDetailJob.syncRoomList(staff);
    }

    private CommonResponse<String> addRoomUser(ThirdPartWeComStaff staff,
                                               ThirdPartWeComRoom room,
                                               List<Long> vids,
                                               List<ThirdPartWeComStaffUser> addUserList) {
        if (room.getAddUserStatus() != 1 || room.getMemberCount() >= memberMaxNums) {
            return null;
        }
        String dateStr = DateUtil.getCurrentDateStr("yyyyMMdd");
        String key = "addRoomUserTimes:" + dateStr + ":" + staff.getThirdStaffId() + ":" + room.getThirdRoomId();
        int addRoomUserTimes = redisUtils.getInteger(key);
        if (addRoomUserTimes >= dailyMaxAddUserTimes) {
            return null;
        }
        InvitationToRoomRequest request = new InvitationToRoomRequest();
        request.setUuid(staff.getThirdUuid());
        request.setRoomid(Long.parseLong(room.getThirdRoomId()));
        request.setVids(vids);
        CommonResponse<String> commonResponse = weComThirdPartyService.invitationToRoom(request);
        if (Objects.nonNull(commonResponse)) {
            // 群成员添加存储
            saveRoomUser(room, addUserList);
        }
        redisUtils.setIncrementValue(key, 1, 24 * 60 * 60L);
        return commonResponse;
    }

    private void createNewRoom(ThirdPartWeComStaff staff,
                               List<ThirdPartWeComStaffUser> staffUserList,
                               Integer roomNum) {
        Iterator<ThirdPartWeComStaffUser> iterator = staffUserList.iterator();
        // createRoom 暂时每次任务仅创建一个群
        //while (iterator.hasNext()) {
        List<Long> vids = new ArrayList<>();
        List<ThirdPartWeComStaffUser> addUserList = new ArrayList<>();
        int size = staffUserList.size() > memberMaxNums ? memberMaxNums : staffUserList.size();
        size--;
        while (iterator.hasNext() && size > 0) {
            ThirdPartWeComStaffUser item = iterator.next();
            vids.add(item.getUserId());
            size--;
            iterator.remove();
            addUserList.add(item);
        }
        // 群创建
        CreateRoomWxRequest request = new CreateRoomWxRequest();
        request.setUuid(staff.getThirdUuid());
        request.setRoomName(roomNamePrefix + (++roomNum));
        request.setVids(vids);
        CreateRoomWxResponse createRoomWxResponse = weComThirdPartyService.createRoom(request);
        if (Objects.isNull(createRoomWxResponse)) {
            return;
        }
        // 群管理设置 防骚扰
        updateRoomManagement(staff, createRoomWxResponse);
        // add room save
        ThirdPartWeComRoom roomDetail = new ThirdPartWeComRoom();
        roomDetail.setCorpId(staff.getCorpId());
        roomDetail.setStaffId(staff.getId());
        roomDetail.setThirdRoomId(createRoomWxResponse.getRoomid());
        roomDetail.setThirdCreateUserId(createRoomWxResponse.getCreateid());
        roomDetail.setName(createRoomWxResponse.getRoomname());
        roomDetail.setCreateTime(new Date());
        roomDetail.setUpdateTime(new Date());
        roomMapper.insertSelective(roomDetail);
        // 群成员添加存储
        saveRoomUser(roomDetail, addUserList);
        //}
    }

    private void updateRoomManagement(ThirdPartWeComStaff staff, CreateRoomWxResponse createRoomWxResponse) {
        SetRoomManagementRequest setRoomManagementRequest = new SetRoomManagementRequest();
        setRoomManagementRequest.setUuid(staff.getThirdUuid());
        setRoomManagementRequest.setRoomid(Long.parseLong(createRoomWxResponse.getRoomid()));
        setRoomManagementRequest.setNewFlag(69206023);
        apiClient.setRoomManagement(setRoomManagementRequest);
        // 查询防骚扰规则 并配置所有规则
        QueryCRMAntiSpamRuleRequest antiSpamRuleRequest = new QueryCRMAntiSpamRuleRequest();
        antiSpamRuleRequest.setUuid(staff.getThirdUuid());
        List<AntiSpamRuleResponse.AntiSpamRule> antiSpamRuleList = weComThirdPartyService.queryCRMAntiSpamRule(antiSpamRuleRequest);
        if (CollectionUtils.isNotEmpty(antiSpamRuleList)) {
            // 设置防骚扰规则
            SetRoomAntiRequest setRoomAntiRequest = new SetRoomAntiRequest();
            setRoomAntiRequest.setUuid(staff.getThirdUuid());
            setRoomAntiRequest.setRoomid(Long.parseLong(createRoomWxResponse.getRoomid()));
            setRoomAntiRequest.setAntiIds(antiSpamRuleList.stream().map(AntiSpamRuleResponse.AntiSpamRule::getId).collect(Collectors.toList()));
            apiClient.setRoomAnti(setRoomAntiRequest);
        }
        // createRoom 设置管理员
        //apiClient.addRoomAdmins();
    }

    private void saveRoomUser(ThirdPartWeComRoom room,
                              List<ThirdPartWeComStaffUser> addUserList) {
        if (CollectionUtils.isEmpty(addUserList)) {
            return;
        }
        List<ThirdPartWeComRoomUser> saveList = new ArrayList<>();
        for (ThirdPartWeComStaffUser staffUser : addUserList) {
            ThirdPartWeComRoomUser roomUser = new ThirdPartWeComRoomUser();
            roomUser.setThirdRoomId(room.getThirdRoomId());
            roomUser.setCreateTime(new Date());
            roomUser.setUpdateTime(new Date());
            roomUser.setUin(staffUser.getUserId());
            saveList.add(roomUser);
        }
        if (CollectionUtils.isNotEmpty(saveList)) {
            thirdPartWeComMapperExt.batchInsertThirdPartWeComRoomUser(saveList);
        }
    }

    @XxlJob("autoAddRoomUser")
    public ReturnT<String> autoAddRoomUserJob(String param) {
        List<ThirdPartWeComStaff> activeStaffList = weComThirdPartyService.getActiveStaffList();
        CountDownLatch cdl = new CountDownLatch(activeStaffList.size());
        for (ThirdPartWeComStaff staff : activeStaffList) {
            if (staff.getAutoCreateRoom() != 1) {
                cdl.countDown();
                continue;
            }
            pool.execute(() -> {
                try {
                    addStaffRoomUser(staff);
                } catch (Exception e) {
                    log.error("addStaffRoomUser error", e);
                } finally {
                    cdl.countDown();
                }
            });
        }
        try {
            cdl.await();
        } catch (InterruptedException e) {
            log.error("autoAddRoomUserJob error", e);
        }
        return ReturnT.SUCCESS;
    }

    private void addStaffRoomUser(ThirdPartWeComStaff staff) {
        // 获取所有未加群客户
        List<ThirdPartWeComStaffUser> staffUserList = thirdPartWeComMapperExt.getNoGroupStaffUserList(staff.getThirdStaffId());
        if (CollectionUtils.isEmpty(staffUserList)) {
            return;
        }
        List<ThirdPartWeComRoom> roomList = weComThirdPartyService.getStaffRoomList(staff.getId());
        for (ThirdPartWeComRoom room : roomList) {
            if (room.getAddUserStatus() != 1) {
                continue;
            }
            List<Long> vids = new ArrayList<>();
            List<ThirdPartWeComStaffUser> addUserList = new ArrayList<>();
            Iterator<ThirdPartWeComStaffUser> iterator = staffUserList.iterator();
            int size = memberMaxNums - room.getMemberCount();
            while (iterator.hasNext() && size > 0) {
                ThirdPartWeComStaffUser item = iterator.next();
                vids.add(item.getUserId());
                size--;
                iterator.remove();
                addUserList.add(item);
            }
            addRoomUser(staff, room, vids, addUserList);
        }
        userDetailJob.syncRoomList(staff);
    }

}
