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

import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.Page;
import com.gic.clerk.api.dto.ClerkDTO;
import com.gic.clerk.api.service.ClerkService;
import com.gic.clerk.api.service.RightService;
import com.gic.commons.util.EntityUtil;
import com.gic.haoban.base.api.common.BasePageInfo;
import com.gic.haoban.common.utils.PageUtil;
import com.gic.haoban.common.utils.StringUtil;
import com.gic.haoban.manage.api.dto.StaffClerkRelationDTO;
import com.gic.haoban.manage.api.dto.WxEnterpriseQwDTO;
import com.gic.haoban.manage.api.dto.qdto.hm.HmQrcodeQDTO;
import com.gic.haoban.manage.api.enums.BindTypeEnum;
import com.gic.haoban.manage.api.enums.ChannelCodeEnum;
import com.gic.haoban.manage.api.service.hm.HmClerkRelationApiService;
import com.gic.haoban.manage.api.service.hm.HmQrcodeApiService;
import com.gic.haoban.manage.service.dao.mapper.TabHaobanMemberClerkChatConfigMapper;
import com.gic.haoban.manage.service.dao.mapper.TabHaobanStaffClerkRelationMapper;
import com.gic.haoban.manage.service.entity.MemberClerkChatConfig;
import com.gic.haoban.manage.service.entity.TabHaobanStaff;
import com.gic.haoban.manage.service.entity.TabHaobanStaffClerkRelation;
import com.gic.haoban.manage.service.service.*;
import com.gic.member.api.service.MemberApiService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
public class StaffClerkRelationServiceImpl implements StaffClerkRelationService {

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

    @Autowired
    private TabHaobanStaffClerkRelationMapper mapper;

    @Autowired
    private StaffClerkBindLogService staffClerkBindLogService;

    @Autowired
    private ExternalClerkRelatedService externalClerkRelatedService;

    @Autowired
    private ClerkMainStoreRelatedService clerkMainStoreRelatedService;

    @Autowired
    private TabHaobanMemberClerkChatConfigMapper memberClerkChatConfigMapper;

    @Autowired
    private HmQrcodeApiService hmQrcodeApiService;
    @Autowired
    private StaffService staffService;
    @Autowired
    private HmClerkRelationApiService hmClerkRelationApiService;
    @Autowired
    private WxEnterpriseService wxEnterpriseService;
    @Autowired
    private MemberApiService memberApiService;
    @Autowired
    private ClerkService clerkService;
    @Autowired
    private RightService rightService;

    @Override
    public List<StaffClerkRelationDTO> listBindCode(String wxEnterpriseId, String enterpriseId, Set<String> clerkCodeList) {
        return  this.filterDelClerkList(mapper.listBindCode(wxEnterpriseId, enterpriseId, clerkCodeList));
    }

    @Override
    public List<StaffClerkRelationDTO> listBindCodeByStaffId(List<String> enterpriseIdList, String staffId) {
        return  this.filterDelClerkList(mapper.listBindCodeByStaffId(enterpriseIdList, staffId));
    }

    @Override
    public boolean delBind(String oldClerkId, String optStaffId, int channelCode, String newClerkId, String wxEnterpriseId) {
        TabHaobanStaff staff =  this.staffService.selectById(optStaffId) ;
        if(null != staff) {
            wxEnterpriseId = staff.getWxEnterpriseId() ;
        }
        StaffClerkRelationDTO clerkRelation = mapper.getOneByClerkId(oldClerkId, wxEnterpriseId);
        if (null == clerkRelation) {
            logger.info("老的绑定关联不存在,clerkId={}", oldClerkId);
            return true;
        }
        int i = mapper.changeStatusByClerkId(oldClerkId, 0);
        String enterpriseId = clerkRelation.getEnterpriseId();
        if(StringUtils.isNotBlank(newClerkId)) {
            this.externalClerkRelatedService.updateClerkInfo(clerkRelation.getStaffId() , oldClerkId , newClerkId) ;
        }else {
            List<String> memberIds = externalClerkRelatedService.getByStoreIdAndStaffId(clerkRelation.getStoreId(), clerkRelation.getStaffId());
            //删除 并设置主门店
            clerkMainStoreRelatedService.delMainStore(clerkRelation.getStaffId(), clerkRelation.getStoreId(), clerkRelation.getWxEnterpriseId());
            //推入日志
            delMemberQywxFlag(enterpriseId, memberIds); 
        }
        staffClerkBindLogService.pushToMq(clerkRelation.getStaffId(), optStaffId, BindTypeEnum.UNBIND.getVal(), channelCode, clerkRelation.getStaffClerkRelationId());
        //废弃活码
        hmClerkRelationApiService.delByClerkId(oldClerkId, enterpriseId, clerkRelation.getWxEnterpriseId(), channelCode, newClerkId);
        return i > 0;
    }


    private void delMemberQywxFlag(String enterpriseId, List<String> memberIds) {
        for (String memberId : memberIds) {
            //解绑通知会员
            int count = externalClerkRelatedService.getCountByMemberId(memberId);
            if (count == 0) {
                logger.info("通知会员 删除企微好友,该会员无任何好友关系，memberId:{}", memberId);
                memberApiService.updateMemberQywxFlag(enterpriseId, memberId, 0);
                memberApiService.updateMemberQywxEveryOccasion(enterpriseId, memberId, 0, new Date());
                continue;
            }
            logger.info("通知会员 删除企微好友 每次调用更新为非企微好友时间 memberId：{}", memberId);
            memberApiService.updateMemberQywxEveryOccasion(enterpriseId, memberId, 1, new Date());
        }
    }

    @Override
    public boolean delBindByStoreIds(String wxEnterpriseId, Set<String> storeIds, String optStaffId, int channelCode) {
        if (CollectionUtils.isEmpty(storeIds)) {
            logger.info("没有传门店列表：{}", wxEnterpriseId);
            return true;
        }
        List<String> storeIdList = new ArrayList<>();
        storeIdList.addAll(storeIds) ;
        List<StaffClerkRelationDTO> needUnbind = mapper.listByStoreIds(wxEnterpriseId, storeIdList);
        if (CollectionUtils.isEmpty(needUnbind)) {
            logger.info("没有门店绑定了需要解绑的：{}", wxEnterpriseId);
            return true;
        }

        for (StaffClerkRelationDTO staffClerkRelation : needUnbind) {
            String enterpriseId = staffClerkRelation.getEnterpriseId();
            //删除好友通知会员
            List<String> memberIds = externalClerkRelatedService.getByStoreIdAndStaffId(staffClerkRelation.getStoreId(), staffClerkRelation.getStaffId());
            delMemberQywxFlag(enterpriseId, memberIds);
        }

        List<String> need = needUnbind.stream().map(tab -> tab.getStaffClerkRelationId()).collect(Collectors.toList());
        //清除绑定
        mapper.delByStoreIds(storeIds);
        //删除主门店
        clerkMainStoreRelatedService.delMainStoreByStoreIds(storeIds);
        //放入队列
        staffClerkBindLogService.pushToMqBatch(optStaffId, BindTypeEnum.UNBIND.getVal(), channelCode, need);
        for (StaffClerkRelationDTO clerkRelation : needUnbind) {
            //废弃活码
            String enterpriseId = clerkRelation.getEnterpriseId();
            hmClerkRelationApiService.delByClerkId(clerkRelation.getClerkId(), enterpriseId, wxEnterpriseId, channelCode);
        }
        return true;
    }

    @Override
    public String bind(StaffClerkRelationDTO dto, String optStaffId, int channelCode) {
        String staffId = dto.getStaffId();
        TabHaobanStaff tabHaobanStaff = staffService.selectById(staffId);
        if (tabHaobanStaff == null) {
            logger.error("员工不存在:{}", staffId);
            return "";
        }
        ClerkDTO clerkDTO = clerkService.getClerkByClerkId(dto.getClerkId());
        if (clerkDTO != null) {
            dto.setClerkType(clerkDTO.getClerkType());
        }
        String staffClerkRelationId = insert(dto);
        if (StringUtils.isNotBlank(staffClerkRelationId)) {
            String wxEnterpriseId = dto.getWxEnterpriseId();
            Integer manageFlag = dto.getManageFlag();
            String enterpriseId = dto.getEnterpriseId();
            //导购和店长需要设置主门店
            if (manageFlag != null && manageFlag == 1) {
                //do nothing
            } else {
                logger.info("设置主门店并创建活码：manageFlag:{},staffId:{}", manageFlag, staffId);
                clerkMainStoreRelatedService.getMainStoreByStaffId(staffId, wxEnterpriseId);
                //有活码权限的企业
                boolean flag = rightService.hasRightForAdmin(enterpriseId, "hb_m0206");
                if (flag) {
                    // 绑定自动创建活码
                    HmQrcodeQDTO hmQrcodeQDTO = new HmQrcodeQDTO();
                    hmQrcodeQDTO.setHmType(1);
                    hmQrcodeQDTO.setWxEnterpriseId(wxEnterpriseId);
                    hmQrcodeQDTO.setEnterpriseId(enterpriseId);
                    hmQrcodeQDTO.setName(tabHaobanStaff.getStaffName());
                    hmQrcodeQDTO.setPassFlag(1);
                    hmQrcodeQDTO.setStoreId(dto.getStoreId());
                    hmQrcodeQDTO.setClerkIdList(Collections.singletonList(dto.getClerkId()));
                    hmQrcodeQDTO.setInvokingType(channelCode);
                    hmQrcodeApiService.add(hmQrcodeQDTO);
                }
            }
            //推入日志
            staffClerkBindLogService.pushToMq(staffId, optStaffId, BindTypeEnum.BIND.getVal(), channelCode, staffClerkRelationId);
        }
        return staffClerkRelationId;
    }


    @Override
    public StaffClerkRelationDTO getBindByClerkId(String clerkId, String wxEnterpriseId) {
        return this.filterDelClerk(mapper.getOneByClerkId(clerkId, wxEnterpriseId));
    }

    @Override
    public StaffClerkRelationDTO getByCodeAndEnterpriseId(String clerkCode, String enterpriseId) {
        return mapper.getByCodeAndEnterpriseId(clerkCode, enterpriseId);
    }

    @Override
    public StaffClerkRelationDTO getStaffClerkRelationDTO(String clerkCode, String enterpriseId) {
        return mapper.getStaffClerkRelationDTO(clerkCode, enterpriseId);
    }


    @Override
    public String insert(StaffClerkRelationDTO staffClerkRelation) {
        Integer manageFlag = staffClerkRelation.getManageFlag();
        String uuid = StringUtil.randomUUID();
        staffClerkRelation.setStaffClerkRelationId(uuid);
        staffClerkRelation.setCreateTime(new Date());
        staffClerkRelation.setUpdateTime(new Date());
        staffClerkRelation.setStatusFlag(1);
        staffClerkRelation.setOpenConcatFlag(1);
        staffClerkRelation.setManageFlag(manageFlag == null ? 0 : manageFlag);
        TabHaobanStaffClerkRelation relation = EntityUtil.changeEntityByJSON(TabHaobanStaffClerkRelation.class, staffClerkRelation);
        mapper.insert(relation);
        return uuid;
    }

    @Override
    public int cleanStaffClerk(String wxEnterpriseId, List<String> delStaffIds) {
        delStaffIds.forEach(staffId -> {
            List<StaffClerkRelationDTO> relationDTOS = listBindCodeByStaffId(null, staffId);
            if (CollectionUtils.isNotEmpty(relationDTOS)) {
                relationDTOS.forEach(mid -> {
                    staffClerkBindLogService.pushToMq(mid.getStaffId(), "-1", BindTypeEnum.UNBIND.getVal(), ChannelCodeEnum.WEIXIN_DEL.getCode(), mid.getStaffClerkRelationId());
                });
            }
        });
        int ret = mapper.cleanStaffDepart(wxEnterpriseId, delStaffIds);
        externalClerkRelatedService.cleanStaffRelated(wxEnterpriseId, delStaffIds);
        return ret;
    }

    @Override
    public StaffClerkRelationDTO getOneBindByStoreId(String staffId, String storeId) {
        StaffClerkRelationDTO dto = this.filterDelClerk(mapper.getOneByStoreIdAndStaffId(storeId,staffId));
        return dto ;
    }

    @Override
    public StaffClerkRelationDTO getByClerkId(String clerkId) {
        return this.filterDelClerk(mapper.getOneByClerkId(clerkId, null));
    }

    @Override
    public StaffClerkRelationDTO getByClerkId(String clerkId, String wxEnterpriseId) {
        StaffClerkRelationDTO staffClerkRelation = mapper.getOneByClerkId(clerkId, wxEnterpriseId);
        return EntityUtil.changeEntityNew(StaffClerkRelationDTO.class, staffClerkRelation);
    }

    @Override
    public List<StaffClerkRelationDTO> listByClerkIds(List<String> clerkList) {
        if (CollectionUtils.isEmpty(clerkList)) {
            return Collections.EMPTY_LIST;
        }
        return mapper.listByClerkIds(clerkList, null);
    }

    @Override
    public List<StaffClerkRelationDTO> listByStaffId(String wxEnterpriseId, String staffId) {
        return EntityUtil.changeEntityListByJSON(StaffClerkRelationDTO.class, mapper.lisByStaffId(wxEnterpriseId, staffId, null));
    }

    @Override
    public List<StaffClerkRelationDTO> listByStaffId(String wxEnterpriseId, String staffId, List<String> storeIdList) {
        return EntityUtil.changeEntityListByJSON(StaffClerkRelationDTO.class, mapper.lisByStaffId(wxEnterpriseId, staffId, storeIdList));
    }

    @Override
    public void saveChatConfig(MemberClerkChatConfig memberClerkChatConfig) {
        memberClerkChatConfig.setStatus(1);
        memberClerkChatConfig.setCreateTime(new Date());
        memberClerkChatConfig.setUpdateTime(new Date());
        memberClerkChatConfigMapper.insert(memberClerkChatConfig);
    }

    @Override
    public MemberClerkChatConfig getChatConfig(String staffId, String memberId) {
        MemberClerkChatConfig chatConfig = memberClerkChatConfigMapper.getChatByMemberIdStaffId(memberId, staffId);
        return chatConfig;
    }

    @Override
    public List<String> listByWxEnterpriseId(String wxEnterpriseId) {
        return mapper.listByWxEnterpriseId(wxEnterpriseId);
    }

    @Override
    public Page<StaffClerkRelationDTO> pageByWxEnterpriseId(String wxEnterpriseId, BasePageInfo pageInfo) {
        PageHelper.startPage(pageInfo);
        List<StaffClerkRelationDTO> clerkBindList = mapper.pageByWxEnterpriseId(wxEnterpriseId);
        Page<StaffClerkRelationDTO> retPage = PageUtil.changePageHelperToCurrentPage(new PageInfo<>(clerkBindList), StaffClerkRelationDTO.class);
        return retPage;
    }

    @Override
    public List<StaffClerkRelationDTO> listBindByStoreId(String wxEnterpriseId, String storeId) {
        return mapper.listByStoreIds(wxEnterpriseId, Arrays.asList(storeId));
    }

    @Override
    public List<StaffClerkRelationDTO> listBindStoreIdByEnterpriseId(String enterpriseId) {
        List<StaffClerkRelationDTO> clerkRelations = mapper.listBindStoreIdByEnterpriseId(enterpriseId);
        if (CollectionUtils.isEmpty(clerkRelations)) {
            return new ArrayList<>();
        }
        return EntityUtil.changeEntityListNew(StaffClerkRelationDTO.class, clerkRelations);
    }

    @Override
    public List<String> listRelationsStaffId(Set<String> staffIdList) {
        return mapper.listRelationsStaffId(staffIdList);
    }

    @Override
    public List<String> listWxUserIdByClerkIds(List<String> clerkList, String wxEnterpriseId) {
        if (CollectionUtils.isEmpty(clerkList)) {
            return null;
        }
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        if (qwDTO.needOpenUserId3th()) {
            return mapper.listWxUserIdByClerkIds(clerkList, wxEnterpriseId,2);
        }
        return mapper.listWxUserIdByClerkIds(clerkList, wxEnterpriseId,1);
    }

    @Override
    public List<StaffClerkRelationDTO> listIdsByWxUserIds(List<String> wxUserIds, String wxEnterpriseId, String enterpriseId) {
        if (CollectionUtils.isEmpty(wxUserIds)) {
            return null;
        }
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        if (qwDTO.needOpenUserId3th()) {
            return mapper.listIdsByWxUserIds(wxUserIds, wxEnterpriseId, enterpriseId,2);
        }
        return mapper.listIdsByWxUserIds(wxUserIds, wxEnterpriseId, enterpriseId,1);
    }

    @Override
    public List<StaffClerkRelationDTO> listIdsByNotInWxUserIds(List<String> wxUserIds, String wxEnterpriseId, String enterpriseId) {
        if (CollectionUtils.isEmpty(wxUserIds)) {
            return null;
        }
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId);
        if (qwDTO.needOpenUserId3th()) {
            return mapper.listIdsByNotInWxOpenUserIds(wxUserIds, wxEnterpriseId, enterpriseId);
        }
        return mapper.listIdsByNotInWxUserIds(wxUserIds, wxEnterpriseId, enterpriseId);
    }

    @Override
    public int updateOpenConcatFlagById(Integer openConcatFlag, String staffClerkRelationId) {
        return mapper.updateOpenConcatFlagById(openConcatFlag, staffClerkRelationId);
    }

    @Override
    public boolean getBindByStaffIdAndEnterpriseId(String enterpriseId, String staffId) {
        return mapper.getBindByStaffIdAndEnterpriseId(enterpriseId, staffId) > 0;
    }

    @Override
    public List<StaffClerkRelationDTO> listManageBindByStaffId(String staffId) {
        return this.filterDelClerkList(mapper.listManageBindByStaffId(staffId));
    }
    
    private List<StaffClerkRelationDTO> filterDelClerkList(List<StaffClerkRelationDTO> list) {
        if(CollectionUtils.isEmpty(list)) {
            return list ;
        }
        List<StaffClerkRelationDTO> retList = new ArrayList<>() ;
        for(StaffClerkRelationDTO item : list) {
            String clerkId = item.getClerkId() ;
            ClerkDTO clerk = this.clerkService.getclerkById(clerkId) ;
            if(null != clerk && clerk.getStatus() == 1) {
                retList.add(item) ;
            }else {
                this.mapper.delByClerkId(clerkId);
            }
        }
        return retList ;
    }
    
    private StaffClerkRelationDTO filterDelClerk(StaffClerkRelationDTO dto) {
        if(null == dto) {
            return dto ;
        }
        String clerkId = dto.getClerkId() ;
        ClerkDTO clerk = this.clerkService.getclerkById(clerkId) ;
        if(null == clerk || clerk.getStatus() != 1) {
            this.mapper.delByClerkId(clerkId);
            dto = null ;
        }
        return dto ;
    }

    /**
     * 获取企业下所有关联关系
     *
     * @param enterpriseId
     * @return
     */
    @Override
    public List<StaffClerkRelationDTO> listAllRelationDtosByEnterpriseId(String enterpriseId) {
        return this.mapper.listAllRelationDtosByEnterpriseId(enterpriseId);
    }
}
