package com.gic.haoban.manage.service.service.chat.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.gic.haoban.manage.api.dto.chat.GroupChatHmMemberRelationDTO;
import com.gic.haoban.manage.service.dao.mapper.chat.*;
import com.gic.haoban.manage.service.pojo.bo.chat.GroupChatHmMemberRelationBO;
import com.gic.haoban.manage.service.service.chat.GroupChatUserService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.gic.api.base.commons.BasePageInfo;
import com.gic.api.base.commons.Page;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.util.PageHelperUtils;
import com.gic.commons.util.UniqueIdUtils;
import com.gic.haoban.common.utils.RolesListUtils;
import com.gic.haoban.manage.api.constants.Manage3Constants;
import com.gic.haoban.manage.api.dto.SecretSettingDTO;
import com.gic.haoban.manage.api.dto.WxEnterpriseQwDTO;
import com.gic.haoban.manage.api.dto.chat.GroupChatHmDTO;
import com.gic.haoban.manage.api.dto.hm.HmLinkChatDTO;
import com.gic.haoban.manage.api.dto.qdto.chat.ChatHmSearchQDTO;
import com.gic.haoban.manage.api.enums.SecretTypeEnum;
import com.gic.haoban.manage.service.dao.mapper.hm.HmLinkChatMapper;
import com.gic.haoban.manage.service.dao.mapper.hm.HmLinkMapper;
import com.gic.haoban.manage.service.entity.chat.TabChatNotice;
import com.gic.haoban.manage.service.entity.chat.TabGroupChat;
import com.gic.haoban.manage.service.entity.chat.TabGroupChatHm;
import com.gic.haoban.manage.service.entity.chat.TabGroupChatHmRelation;
import com.gic.haoban.manage.service.entity.hm.TabHmLink;
import com.gic.haoban.manage.service.pojo.bo.chat.GroupChatHmBO;
import com.gic.haoban.manage.service.pojo.bo.chat.GroupChatHmRelationBO;
import com.gic.haoban.manage.service.service.SecretSettingService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.haoban.manage.service.service.chat.GroupChatHmService;
import com.gic.haoban.manage.service.service.hm.HmLinkChatService;
import com.gic.wechat.api.dto.qywx.chat.AddJoinWayDTO;
import com.gic.wechat.api.service.qywx.QywxChatApiService;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Sets;

@Service("groupChatHmService")
public class GroupChatHmServiceImpl implements GroupChatHmService {

    private static final Logger logger = LoggerFactory.getLogger(GroupChatHmService.class);

    @Autowired
    private QywxChatApiService qywxChatApiService;
    @Autowired
    private WxEnterpriseService wxEnterpriseService;
    @Autowired
    private SecretSettingService secretSettingService;
    @Autowired
    private GroupChatMapper groupChatMapper;
    @Autowired
    private GroupChatHmMapper groupChatHmMapper;
    @Autowired
    private GroupChatHmRelationMapper groupChatHmRelationMapper;
    @Autowired
    private HmLinkChatMapper hmLinkChatMapper;
    @Autowired
    private ChatNoticeMapper chatNoticeMapper;
    @Autowired
    private HmLinkChatService hmLinkChatService;
    @Autowired
    private HmLinkMapper hmLinkMapper;
    @Autowired
    private GroupChatUserMapper groupChatUserMapper;

    @Override
    public Page<GroupChatHmBO> listPage(ChatHmSearchQDTO qdto, BasePageInfo basePageInfo) {
        String wxEnterpriseId = qdto.getWxEnterpriseId();
        String enterpriseId = qdto.getEnterpriseId();
        if (StringUtils.isNotBlank(qdto.getSearchParams())) {
            String params = qdto.getSearchParams();
            qdto.setSearchParamsCode(params + "%");
            qdto.setSearchParams("%" + params + "%");
        }
        Long linkId = qdto.getLinkId();
        if (null != linkId) {
            // 查询链接下的关联的活码列表
            List<HmLinkChatDTO> linkChatList = this.hmLinkChatMapper.listByLinkId(wxEnterpriseId, enterpriseId, linkId);
            if (CollectionUtils.isEmpty(linkChatList)) {
                return new Page<>();
            }
            List<Long> chatHmIdList = linkChatList.stream().map(o -> o.getChatHmId()).collect(Collectors.toList());
            TabHmLink link = this.hmLinkMapper.selectById(linkId);
            if (null == link) {
                return new Page<>();
            }
            chatHmIdList.add(link.getOtherChatHmId());
            qdto.setChatHmIdList(chatHmIdList);
        }
        PageHelper.startPage(basePageInfo);
        List<TabGroupChatHm> list = this.groupChatHmMapper.list(qdto);
        Page<GroupChatHmBO> retPage = PageHelperUtils.changePageHelperToCurrentPage(list, GroupChatHmBO.class);

        if (CollectionUtils.isNotEmpty(retPage.getResult())) {
            List<Long> hmIdList = retPage.getResult().stream().map(o -> o.getChatHmId()).collect(Collectors.toList());
            List<GroupChatHmRelationBO> boList = this.groupChatHmRelationMapper.getHmValidChatCount(hmIdList);
            Map<Long, Integer> map = boList.stream().collect(
                    Collectors.toMap(GroupChatHmRelationBO::getChatHmId, GroupChatHmRelationBO::getUsableChatCount));
            retPage.getResult().forEach(item -> {
                Long hmId = item.getChatHmId();
                if (null != map.get(hmId)) {
                    item.setUsableChatCount(map.get(hmId));
                }
            });
        }
        return retPage;
    }

    @Override
    public GroupChatHmBO getById(Long hmId) {
        TabGroupChatHm hm = this.groupChatHmMapper.selectById(hmId);
        if (null == hm) {
            return null;
        }
        this.updateLinkCount(hm.getWxEnterpriseId(), Arrays.asList(hmId));
        String wxEnterpriseId = hm.getWxEnterpriseId(); ;
        SecretSettingDTO secretSetting = secretSettingService.getSecretSetting(wxEnterpriseId, SecretTypeEnum.CUSTOMIZED_APP.getVal());
        if (null != secretSetting && hm.getAutoCreateRoom() == 1) {
            List<TabGroupChatHmRelation> chatRelation = this.groupChatHmRelationMapper.listByChatHmId(hmId);
            if(CollectionUtils.isNotEmpty(chatRelation)) {
                this.handleAutoCreateRoom(wxEnterpriseId, secretSetting.getSecretVal(), hm, chatRelation, null);
            }
        }
        GroupChatHmBO bo = EntityUtil.changeEntityByJSON(GroupChatHmBO.class, hm);
        return bo;
    }

    @Override
    public void discard(Long chatHmId, String wxEnterpriseId, String clerkId, String clerkName) {
        TabGroupChatHm hm = this.groupChatHmMapper.selectById(chatHmId);
        this.groupChatHmMapper.discard(chatHmId, wxEnterpriseId, clerkId, clerkName);
        if (StringUtils.isNotBlank(hm.getWxConfigId())) {
            SecretSettingDTO secretSetting = secretSettingService.getSecretSetting(wxEnterpriseId,
                    SecretTypeEnum.CUSTOMIZED_APP.getVal());
            if (null != secretSetting) {
                WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
                ServiceResponse<Void> resp = this.qywxChatApiService.delJoinWay(qwDTO.getDkCorpid(),
                        secretSetting.getSecretVal(), hm.getWxConfigId(),qwDTO.getUrlHost());
                logger.info("删除群活码={}", JSON.toJSON(resp));
            }
        }
    }

    // 群加满后,处理活码,剔除满的群，加入企微自动建的群
    @Override
    public void handleChatOff(String wxEnterpriseId, Long groupChatId) {
        SecretSettingDTO secretSetting = secretSettingService.getSecretSetting(wxEnterpriseId,
                SecretTypeEnum.CUSTOMIZED_APP.getVal());
        if (null == secretSetting) {
            logger.info("未配置代开发");
            return;
        }
        List<Long> hmIdList = this.groupChatHmRelationMapper.listChatHmId(groupChatId);
        if (CollectionUtils.isEmpty(hmIdList)) {
            logger.info("群加满后,处理活码,群未关联活码,chatid={}", groupChatId);
            return;
        }
        for (Long chatHmId : hmIdList) {
            TabGroupChatHm hm = this.groupChatHmMapper.selectById(chatHmId);
            if (null == hm) {
                logger.info("群活码不存在,chatHmId={}", chatHmId);
                continue;
            }
            if (hm.getAutoCreateRoom() == 0) {
                logger.info("无开启自动建群,不处理自动踢群hmid={}", hm.getChatHmId());
                continue;
            }
            List<TabGroupChatHmRelation> chatRelation = this.groupChatHmRelationMapper.listByChatHmId(chatHmId);
            if (CollectionUtils.isEmpty(chatRelation)) {
                logger.info("活码无关联群,chatHmId={}", chatHmId);
                continue;
            }
            this.handleAutoCreateRoom(wxEnterpriseId, secretSetting.getSecretVal(), hm, chatRelation, groupChatId);
        }
    }

    /**
     * 处理开启自动建群的,如果群满自动下线后,需要从活码中提出.注意使用的是代开发应用
     */
    private void handleAutoCreateRoom(String wxEnterpriseId, String secret, TabGroupChatHm hm,
            List<TabGroupChatHmRelation> chatRelation, Long thisGroupChatId) {
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        String configId = hm.getWxConfigId();
        ServiceResponse<AddJoinWayDTO> joinResp = this.qywxChatApiService.getJoinWay(qwDTO.getDkCorpid(), secret,
                configId,qwDTO.getUrlHost());
        logger.info("处理群活码满-查询群活码={}", JSON.toJSON(joinResp));
        if (joinResp.isSuccess()) {
            AddJoinWayDTO join = joinResp.getResult();
            List<String> qwChatIdList = join.getChat_id_list();
            if (CollectionUtils.isNotEmpty(qwChatIdList)) {
                if (qwChatIdList.size() == 1) {
                    logger.info("只有1个群");
                    if(null != thisGroupChatId) {
                        this.saveChatFullNotice(wxEnterpriseId, thisGroupChatId);
                    }
                    return;
                }
                List<Long> chatIdList = chatRelation.stream().map(dto -> dto.getGroupChatId())
                        .collect(Collectors.toList());
                List<TabGroupChat> chatList = this.groupChatMapper.listByIdSet(new HashSet<>(chatIdList));
                if(CollectionUtils.isNotEmpty(chatList)) {
                    for(TabGroupChat chat : chatList) {
                        if(StringUtils.isEmpty(chat.getStaffId())) {
                            logger.info("群未初始化,无群主");
                            return ;
                        }
                    }
                }
                List<String> hbIdList = chatList.stream().map(dto -> dto.getWxChatIdDk()).collect(Collectors.toList());
                logger.info("企微群列表={},haoban列表={}", qwChatIdList, hbIdList);
                // 差异-企微比好办多的群
                List<String> qwList = RolesListUtils.differenceList(qwChatIdList, hbIdList);
                if (qwChatIdList.size() == hbIdList.size() && CollectionUtils.isEmpty(qwList)) {
                    logger.info("群未变化");
                    if(null != thisGroupChatId) {
                        this.saveChatFullNotice(wxEnterpriseId, thisGroupChatId);
                    }
                    return;
                }
                // 处理要踢的
                List<String> bakQwChatIdList = EntityUtil.changeEntityListByJSON(String.class, qwChatIdList);
                for (String wxChatId : bakQwChatIdList) {
                    TabGroupChat chat = this.groupChatMapper.selectByWxChatIdDk(wxEnterpriseId, wxChatId);
                    if (null == chat) {
                        continue;
                    }
                    TabGroupChat cid = null;
                    String staffId = chat.getStaffId();
                    for (TabGroupChat obj : chatList) {
                        if (obj.getStaffId().equals(staffId)) {
                            if (null == cid) {
                                cid = obj;
                            } else {
                                if (obj.getTotalCount() > cid.getTotalCount()) {
                                    cid = obj;
                                }
                            }
                        }
                    }
                    boolean flag = false ;
                    if (null != cid) {
                        logger.info("hm={},群={},要删={}", wxChatId, qwChatIdList, cid.getWxChatId());
                        Iterator<String> it = qwChatIdList.iterator() ;
                        while(it.hasNext()) {
                            if(it.next().equals(cid.getWxChatIdDk())) {
                                it.remove(); 
                                flag = true ;
                                break ;
                            }
                        }
                    }
                    if(flag) {
                        break ;
                    }
                }
                logger.info("处理后群活码应有的群={}", qwChatIdList);
                // 保存活码
                List<TabGroupChat> list = this.groupChatMapper.listByWxWxChatIdListDk(wxEnterpriseId,
                        qwChatIdList);
                if (CollectionUtils.isEmpty(list) || list.size() != qwChatIdList.size()) {
                    if(null != thisGroupChatId) {
                        this.saveChatFullNotice(wxEnterpriseId, thisGroupChatId);
                    }
                    logger.info("查询群列表空,或数量不一致,dkList={}", qwChatIdList);
                    return;
                }
                List<Long> groupChatIdList = list.stream().map(dto -> dto.getGroupChatId())
                        .collect(Collectors.toList());
                GroupChatHmDTO hmDTO = EntityUtil.changeEntityByJSON(GroupChatHmDTO.class, hm);
                hmDTO.setChatIdList(groupChatIdList);
                this.saveHm(hmDTO, 2);
             }
        }
    }

    @Override
    public ServiceResponse<GroupChatHmDTO> saveHm(GroupChatHmDTO dto) {
        return this.saveHm(dto, 1);
    }

    /**
     * 
     * @Title: saveHm @Description: TODO(这里用一句话描述这个方法的作用) @author xugh @param
     * dto @param autoDel 自动剔除1否 2是 @return @throws
     */
    private ServiceResponse<GroupChatHmDTO> saveHm(GroupChatHmDTO dto, int autoDel) {
        String wxEnterpriseId = dto.getWxEnterpriseId();
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        SecretSettingDTO secretSetting = secretSettingService.getSecretSetting(wxEnterpriseId,
                SecretTypeEnum.CUSTOMIZED_APP.getVal());
        if (null == secretSetting) {
            logger.info("没有配置代开应用");
            return ServiceResponse.failure("9999", "没有配置代开应用");
        }
        boolean updateFlag = false;
        Long hmid = dto.getChatHmId();
        if (null != hmid) {
            updateFlag = true;
        } else {
            hmid = UniqueIdUtils.uniqueLong();
        }
        dto.setChatHmId(hmid);
        dto.setChatHmCode("HM10" + hmid);
        List<Long> chatidList = dto.getChatIdList();
        List<TabGroupChat> chatList = this.groupChatMapper.listByIdSet(new HashSet<>(chatidList));
        List<String> wxChatidList = chatList.stream().filter(item -> StringUtils.isNotBlank(item.getWxChatIdDk()))
                .map(item -> item.getWxChatIdDk()).collect(Collectors.toList());
        logger.info("企微群id={}", wxChatidList);
        AddJoinWayDTO joinDTO = new AddJoinWayDTO();
        joinDTO.setScene(2);
        joinDTO.setRemark(dto.getName());
        joinDTO.setAuto_create_room(dto.getAutoCreateRoom() == null ? 0 : dto.getAutoCreateRoom());
        joinDTO.setRoom_base_id(dto.getRoomBaseId() == null ? 0 : dto.getRoomBaseId());
        joinDTO.setRoom_base_name(dto.getRoomBaseName());
        joinDTO.setState(Manage3Constants.QHM + hmid);
        joinDTO.setChat_id_list(wxChatidList);

        TabGroupChatHm hm = EntityUtil.changeEntityByJSON(TabGroupChatHm.class, dto);
        hm.setChatCount(wxChatidList.size());
        List<TabGroupChatHmRelation> relationList = new ArrayList<>();
        if (updateFlag) {
            joinDTO.setConfig_id(hm.getWxConfigId());
            ServiceResponse<Void> updateResp = this.qywxChatApiService.updateJoinWay(qwDTO.getDkCorpid(),
                    secretSetting.getSecretVal(), joinDTO,qwDTO.getUrlHost());
            if (!updateResp.isSuccess()) {
                return ServiceResponse.failure("9999", updateResp.getMessage());
            }
            this.groupChatHmMapper.updateById(hm);
            List<TabGroupChatHmRelation> oldList = this.groupChatHmRelationMapper.listByChatHmId(hmid);
            List<Long> oldIdList = oldList.stream().map(o -> o.getGroupChatId()).collect(Collectors.toList());
            List<Long> newIdList = dto.getChatIdList();
            Sets.SetView<Long> delView = Sets.difference(Sets.newHashSet(oldIdList), Sets.newHashSet(newIdList));
            List<Long> delIdList = delView.stream().collect(Collectors.toList());
            logger.info("要删除的群={}", delIdList);
            if (CollectionUtils.isNotEmpty(delIdList)) {
                this.groupChatHmRelationMapper.delete(hmid, delIdList, autoDel);
            }
            Sets.SetView<Long> addView = Sets.difference(Sets.newHashSet(newIdList), Sets.newHashSet(oldIdList));
            List<Long> addIdList = addView.stream().collect(Collectors.toList());
            logger.info("要新加的群={}", addIdList);

            for (Long chatId : addIdList) {
                TabGroupChatHmRelation entity = new TabGroupChatHmRelation();
                entity.setChatHmId(hm.getChatHmId());
                entity.setWxEnterpriseId(wxEnterpriseId);
                entity.setGroupChatId(chatId);
                entity.setEnterpriseId(hm.getEnterpriseId());
                entity.setRelationId(UniqueIdUtils.uniqueLong());
                relationList.add(entity);
            }
            if (CollectionUtils.isNotEmpty(relationList)) {
                this.groupChatHmRelationMapper.insertBatch(relationList);
                // 更新群的企业id到活码的企业ID
                logger.info("自动更新群关联的GIC企业ID,eid={},addIdList={}", hm.getEnterpriseId(), addIdList);
                this.groupChatMapper.updateChatEnterpriseId(wxEnterpriseId, hm.getEnterpriseId(), addIdList, 1);
            }

        } else {
            ServiceResponse<String> addResp = this.qywxChatApiService.addJoinWay(qwDTO.getDkCorpid(),
                    secretSetting.getSecretVal(), joinDTO,qwDTO.getUrlHost());
            logger.info("addResp={}", JSON.toJSONString(addResp));
            if (!addResp.isSuccess()) {
                return ServiceResponse.failure("9999", addResp.getMessage());
            }
            String configId = addResp.getResult();
            ServiceResponse<AddJoinWayDTO> getResp = this.qywxChatApiService.getJoinWay(qwDTO.getDkCorpid(),
                    secretSetting.getSecretVal(), configId,qwDTO.getUrlHost());
            logger.info("getResp={}", JSON.toJSONString(getResp));
            if (!getResp.isSuccess()) {
                return ServiceResponse.failure("9999", getResp.getMessage());
            }
            String qrCode = getResp.getResult().getQr_code();
            hm.setWxConfigId(configId);
            hm.setWxQrCode(qrCode);
            this.groupChatHmMapper.insert(hm);
            // 保存realtion
            for (TabGroupChat item : chatList) {
                TabGroupChatHmRelation entity = EntityUtil.changeEntity(TabGroupChatHmRelation.class, item);
                entity.setChatHmId(hm.getChatHmId());
                entity.setRelationId(UniqueIdUtils.uniqueLong());
                relationList.add(entity);
            }
            this.groupChatHmRelationMapper.insertBatch(relationList);
        }
        return ServiceResponse.success(dto);
    }

    private void saveChatFullNotice(String wxEnterpriseId, Long groupChatId) {
        TabChatNotice entity = new TabChatNotice();
        entity.setId(UniqueIdUtils.uniqueLong());
        entity.setWxEnterpriseId(wxEnterpriseId);
        entity.setChatId(groupChatId);
        entity.setType(4);
        entity.setCreateTime(new Date());
        entity.setStatusFlag(0);
        entity.setMsg(null);
        this.chatNoticeMapper.insert(entity);
    }

    @Override
    public void updateLinkCount(String wxEnterpriseId, List<Long> chatHmIdList) {
        logger.info("更新活码链接数={},{}", wxEnterpriseId, chatHmIdList);
        if (CollectionUtils.isNotEmpty(chatHmIdList)) {
            Set<Long> set = new HashSet<>(chatHmIdList);
            List<HmLinkChatDTO> linkGroup = this.hmLinkChatService.getLinkCountForHm(wxEnterpriseId,
                    new ArrayList<>(set));
            List<Long> allList = linkGroup.stream().map(dto -> dto.getChatHmId()).collect(Collectors.toList());
            logger.info("更新活码链接数,有数据={}", allList);
            linkGroup.forEach(dto -> {
                Long hmId = dto.getChatHmId();
                int count = dto.getLinkCount();
                this.groupChatHmMapper.updateLinkCount(hmId, count);
            });
            for (Long id : chatHmIdList) {
                if (!allList.contains(id)) {
                    logger.info("更新活码链接数,全删除的{}", wxEnterpriseId, id);
                    this.groupChatHmMapper.updateLinkCount(id, 0);
                }
            }
        }
    }

    @Override
    public List<Long> listHmGroupChatId(String wxEnterpriseId, Long chatHmId) {
        List<TabGroupChatHmRelation> list = this.groupChatHmRelationMapper.listByChatHmId(chatHmId);
        return list.stream().map(dto -> dto.getGroupChatId()).collect(Collectors.toList());
    }

    @Override
    public Page<GroupChatHmMemberRelationDTO> memberGroupChatHmPage(String enterpriseId, String memberId, BasePageInfo basePageInfo) {
        PageHelper.startPage(basePageInfo);
        List<TabGroupChatHm> tabGroupChatHmList = groupChatHmMapper.listAvailableByEnterpriseId(enterpriseId);
        Page<GroupChatHmMemberRelationDTO> resultPage = PageHelperUtils.changePageHelperToCurrentPage(tabGroupChatHmList, GroupChatHmMemberRelationDTO.class);
        if (CollectionUtils.isNotEmpty(resultPage.getResult())) {
            List<Long> chatHmIdList = resultPage.getResult().stream().map(GroupChatHmMemberRelationDTO::getChatHmId).distinct().collect(Collectors.toList());
            List<Long> memberJoinChatHmIdList = groupChatUserMapper.listMemberChatHmIdByChatHmIdsAndMemberId(chatHmIdList, enterpriseId, memberId)
                    .stream().map(GroupChatHmMemberRelationBO::getChatHmId).distinct().collect(Collectors.toList());
            resultPage.getResult().forEach(dto -> {
                if (memberJoinChatHmIdList.contains(dto.getChatHmId())) {
                    dto.setMemberIsJoin(1);
                } else {
                    dto.setMemberIsJoin(0);
                }
            });
        }
        return resultPage;
    }

    @Override
    public Integer memberJoinGroupChatHmCount(String enterpriseId, String memberId) {
        return groupChatUserMapper.getByMember(enterpriseId, memberId).size();
    }
}