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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.util.UniqueIdUtils;
import com.gic.content.api.service.ContentProducerApiService;
import com.gic.haoban.app.customer.service.api.service.InnerApiService;
import com.gic.haoban.common.utils.StringUtil;
import com.gic.haoban.manage.api.dto.CommonMQDTO;
import com.gic.haoban.manage.api.dto.StaffClerkRelationDTO;
import com.gic.haoban.manage.api.dto.StaffDTO;
import com.gic.haoban.manage.api.enums.ChannelCodeEnum;
import com.gic.haoban.manage.api.service.HaobanCommonMQApiService;
import com.gic.haoban.manage.api.service.StaffClerkRelationApiService;
import com.gic.haoban.manage.api.service.hm.HmQrcodeApiService;
import com.gic.haoban.manage.service.config.Config;
import com.gic.haoban.manage.service.dao.mapper.StaffMapper;
import com.gic.haoban.manage.service.dao.mapper.TabHaobanStaffClerkRelationMapper;
import com.gic.haoban.manage.service.dao.mapper.WxEnterpriseMapper;
import com.gic.haoban.manage.service.entity.TabHaobanStaff;
import com.gic.haoban.manage.service.entity.TabHaobanWxEnterprise;
import com.gic.haoban.manage.service.entity.fee.TabHaobanQywxFeeAccountStaff;
import com.gic.haoban.manage.service.pojo.bo.StaffListBO;
import com.gic.haoban.manage.service.service.StaffDepartmentRelatedService;
import com.gic.haoban.manage.service.service.StaffService;
import com.gic.haoban.manage.service.service.chat.GroupChatService;
import com.gic.haoban.manage.service.service.fee.HaobanQywxFeeAccountStaffService;
import com.gic.haoban.manage.service.service.hm.HmQrcodeService;
import com.gic.redis.data.util.RedisUtil;
import com.gic.wechat.api.dto.qywx.fee.AccountListDTO;
import com.gic.wechat.api.dto.qywx.fee.AccountListResponseDTO;
import com.gic.wechat.api.dto.qywx.fee.ActiveInfoUserResponseDTO;
import com.gic.wechat.api.service.qywx.QywxOrderApiService;
import com.gic.wechat.api.service.qywx.QywxUserApiService;
import com.github.pagehelper.Page;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
public class StaffServiceImpl implements StaffService {
    private static final Logger log = LogManager.getLogger(StaffServiceImpl.class);

    @Autowired
    private StaffMapper mapper;
    @Autowired
    private QywxOrderApiService qywxOrderApiService ;
    @Autowired
    private WxEnterpriseMapper wxEnterpriseMapper ;
    @Autowired
    private Config config ;
    @Autowired
    private HaobanQywxFeeAccountStaffService haobanQywxFeeAccountStaffService;
    @Autowired
    private QywxUserApiService qywxUserApiService ;
    @Autowired
    private TabHaobanStaffClerkRelationMapper staffClerkRelationMapper ;
    @Autowired
    private ContentProducerApiService contentProducerApiService ;
    @Autowired
    private GroupChatService groupChatService ;
    @Autowired
    private HmQrcodeService hmQrcodeService ;
    @Autowired
    private HmQrcodeApiService hmQrcodeApiService ;
    @Autowired
    private InnerApiService innerApiService ;
    @Autowired
    private StaffClerkRelationApiService staffClerkRelationApiService ;
    @Autowired
    private StaffDepartmentRelatedService staffDepartmentRelatedService ;
    @Autowired
    private HaobanCommonMQApiService haobanCommonMQApiService ;

    @Override
    public TabHaobanStaff selectById(String id) {
        if (StringUtils.isBlank(id)) {
            return null;
        }
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public TabHaobanStaff selectByNationcodeAndPhoneNumber(String wxEnterpriseId, String nationcode, String phoneNumber) {
        if (StringUtils.isBlank(phoneNumber)) {
            return null;
        }
        return mapper.selectByNationcodeAndPhoneNumber(wxEnterpriseId, nationcode, phoneNumber);
    }

    @Override
    public String add(TabHaobanStaff tab) {
        Date now = new Date();
        tab.setCreateTime(now);
        tab.setUpdateTime(now);
        if (StringUtils.isBlank(tab.getStaffId())) {
            tab.setStaffId(StringUtil.randomUUID());
        }
        tab.setStatusFlag(1);
        tab.setAddNum(0);
        String lockKey = "tabstaff:"+tab.getWxEnterpriseId()+tab.getWxUserId() ;
        RedisUtil.lock(lockKey,2l, TimeUnit.SECONDS,2l);
        TabHaobanStaff staff = this.mapper.selectByUserIdAndEnterpriseId(tab.getWxUserId(),tab.getWxEnterpriseId()) ;
        if(null != staff) {
            RedisUtil.unlock(lockKey);
            return staff.getStaffId() ;
        }
        mapper.insertSelective(tab);
        CommonMQDTO mq = new CommonMQDTO() ;
        mq.setType(11) ;
        Map<String,String> map = new HashMap<>() ;
        map.put("staffId",tab.getStaffId()) ;
        mq.setParams(map);
        this.haobanCommonMQApiService.putCommonDelayMessage(mq, 10);
        RedisUtil.unlock(lockKey);
        return tab.getStaffId();
    }

    @Override
    public Page<TabHaobanStaff> pageStaff(StaffListBO staffListBO) {
        if (null == staffListBO){
            return new Page<>();
        }
        String sortField = "a."+staffListBO.getSortField();
        staffListBO.setSortField(sortField);
        //业务需求：许可激活时间和过期时间增加升序和降序排序，时间为空的数据无论升序还是降序排序均排在最后
        if("asc".equals(staffListBO.getSortType()) || "ASC".equals(staffListBO.getSortType())){
            String s = "ISNULL("+sortField+"),"+sortField;
            staffListBO.setSortField(s);
        }
        //时间处理
        if (StrUtil.isNotBlank(staffListBO.getStartTime())) {
            staffListBO.setStartTime(staffListBO.getStartTime() + " 00:00:00");
        }
        if (StrUtil.isNotBlank(staffListBO.getEndTime())) {
            staffListBO.setEndTime(staffListBO.getEndTime() + " 23:59:59");
        }
        return mapper.pageStaff(staffListBO);
    }

    @Override
    public TabHaobanStaff selectByUserIdAndEnterpriseId(String userId, String wxEnterpriseId) {
        return mapper.selectByUserIdAndEnterpriseId(userId, wxEnterpriseId);
    }

    @Override
    public TabHaobanStaff selectByUserIdAndEnterpriseId(String wxUserId, String wxOpenUserId , String wxEnterpriseId) {
        if (StringUtils.isBlank(wxUserId)) {
            log.info("wxUserId is null");
            return null;
        }
        TabHaobanStaff staff = this.mapper.selectByUserIdAndEnterpriseId(wxUserId, wxEnterpriseId) ;
        if (null == staff && null != wxOpenUserId && !wxUserId.equals(wxOpenUserId)) {
            return  this.mapper.selectByUserIdAndEnterpriseId(wxOpenUserId, wxEnterpriseId) ;
        }
        return staff;
    }

    @Override
    public void updateByPrimaryKey(TabHaobanStaff tab) {
        tab.setUpdateTime(new Date());
        mapper.updateByPrimaryKeySelective(tab);
    }

    @Override
    public int delByStaffId(String staffId) {
        return this.mapper.delStaff(staffId);
    }

    @Override
    public List<StaffDTO> listByUserIdsAndWxEnterpriseId(List<String> userIds, String wxEnterpriseId) {
        return EntityUtil.changeEntityListByJSON(StaffDTO.class, this.mapper.listByUserIdsAndWxEnterpriseId(userIds, wxEnterpriseId));
    }

    @Override
    public int cleanStaff(String wxEnterpriseId, List<String> staffIds) {
        return mapper.cleanStaff(wxEnterpriseId, staffIds);
    }

    @Override
    public List<String> listDelUserStaffId(String wxEnterpriseId, List<String> staffIds) {
        return mapper.listUserStaffId(wxEnterpriseId, staffIds);
    }

    @Override
    public List<TabHaobanStaff> listNoStatusByStaffIds(String wxEnterpriseId, List<String> staffIds) {
        return mapper.listNoStatusStaffIds(wxEnterpriseId, staffIds);
    }

    @Override
    public int updateOpenUserIdsByUserId(String wxEnterpriseId, String wxUserId, String wxOpenUseId) {
        return mapper.updateOpenUserIdsByUserId(wxEnterpriseId, wxUserId, wxOpenUseId);
    }

    @Override
    public void delOtherStaffByWxUserId(String wxUserId, String staffId, String wxEnterpriseId) {
        mapper.delOtherStaffByWxUserId(wxUserId, staffId, wxEnterpriseId);
    }

    @Override
    public int updateAddNumById(String staffId) {
        return mapper.updateAddNumById(staffId);
    }

    @Override
    public int resetAddNum() {
        return mapper.resetAddNum();
    }

    @Override
    public int updateActiveStatusById(String staffId,  Date activeTime, Date expireTime,
            String activeCode) {
        return mapper.updateActiveStatusById(staffId, activeTime, expireTime, activeCode) ;
    }

    @Override
    public void updateOpenConcatFlag(List<String> wxUserIdList,int mixFlag) {
        if(CollectionUtils.isEmpty(wxUserIdList)) {
            return ;
        }
        this.mapper.updateOpenConcatFlag(wxUserIdList,mixFlag);
    }

    @Override
    public void activedAccountTimer(String wxEid) {
        log.info("开始查询激活账号,wxEid={}", wxEid);
        TabHaobanWxEnterprise wxEnterprise = this.wxEnterpriseMapper.selectByPrimaryKey(wxEid) ;
        if(wxEnterprise.getWxSecurityType()>0 && StringUtils.isNotEmpty(wxEnterprise.getOpenCorpid()) && wxEnterprise.getStatusFlag()==1) {
            this.haobanQywxFeeAccountStaffService.deleteAll(wxEid) ;
            this.mapper.deleteActivieInfo(wxEid);
            this.listAccount(wxEnterprise, 500, null);
        }
    }

    @Override
    public Integer getOccupyNum(String wxEnterpriseId) {
        return mapper.getOccupyNum(wxEnterpriseId);
    }

    @Override
    public Integer getExpiringNum(String wxEnterpriseId) {
        return mapper.getExpiringNum(wxEnterpriseId);
    }

    private void listAccount(TabHaobanWxEnterprise wxEnterprise , int limit , String cursor) {
        String wxEnterpriseId = wxEnterprise.getWxEnterpriseId() ;
        String openCorpid = wxEnterprise.getOpenCorpid() ;
        ServiceResponse<AccountListResponseDTO>  resp = this.qywxOrderApiService.listActivedAccount(config.getCorpid(), openCorpid, limit, cursor) ;
        log.info("查询激活账号,wxEid={},返回={}",wxEnterpriseId,JSON.toJSONString(resp));
        if(resp.isSuccess()) {
            AccountListResponseDTO dto = resp.getResult() ;
            List<AccountListDTO> list = dto.getAccountList() ;
            log.info("查询激活账号,size={},wxeid={}",list.size(),wxEnterpriseId);
            this.updateAccount(wxEnterpriseId,openCorpid, list);
            cursor = dto.getNextCursor() ;
            Integer hasMore = dto.getHasMore() ;
            // 从企微拉取下一批数据
            if (StringUtils.isNotBlank(cursor) && null !=hasMore &&  hasMore==1) {
                this.listAccount(wxEnterprise, limit , cursor);
            }
        }
    }

    private void updateAccount(String wxEnterpriseId , String openCorpid ,List<AccountListDTO> list) {
        for(AccountListDTO item : list) {
            String userId = item.getUserid() ;
            ActiveInfoUserResponseDTO activeInfoUserResponseDTO = qywxUserApiService.getActiveInfoByUser(openCorpid, config.getCorpid(), userId);
            log.info("查询用户激活详情={},{}",JSON.toJSONString(activeInfoUserResponseDTO),userId);
            String activeCode = null ;
            if (activeInfoUserResponseDTO.getErrcode() == 0) {
                for(AccountListDTO dto : activeInfoUserResponseDTO.getActiveInfoList()) {
                    if(dto.getType()==2) {
                        activeCode = dto.getActiveCode() ;
                    }
                }
            }
            if(StringUtils.isEmpty(activeCode)){
                log.info("无互通激活码={}",userId);
                continue ;
            }
            Date start = new Date(item.getActiveTime()*1000L) ;
            Date end = new Date(item.getExpireTime()*1000L) ;
            log.info("更新staff表,userId={}",userId);
            TabHaobanStaff staff = this.mapper.selectByUserIdAndEnterpriseId(userId, wxEnterpriseId) ;
            if(null == staff && end.getTime()>System.currentTimeMillis()) {
                staff = this.mapper.getDeleteUser(userId, wxEnterpriseId) ;
            }
            if(null != staff) {
                this.updateActiveStatusById(staff.getStaffId(), start, end, activeCode) ;
            }else {
                log.info("查询激活账号,用户不存在,userid={}",userId);
            }
            TabHaobanQywxFeeAccountStaff accountStaff = new TabHaobanQywxFeeAccountStaff();
            accountStaff.setFeeAccountStaffId(UniqueIdUtils.uniqueLong());
            accountStaff.setWxEnterpriseId(wxEnterpriseId);
            accountStaff.setCorpId(openCorpid);
            accountStaff.setActiveCode(activeCode);
            accountStaff.setWxUserId(userId);
            accountStaff.setAccountType(item.getType());
            accountStaff.setExpireTime(DateUtil.date(item.getExpireTime() * 1000));
            accountStaff.setActiveTime(DateUtil.date(item.getActiveTime() * 1000));
            this.haobanQywxFeeAccountStaffService.save(accountStaff);
        }
    }

    /**
     * 查询成员列表
     *
     * @param staffIds
     * @return
     */
    @Override
    public List<TabHaobanStaff> listStaffWithIds(List<String> staffIds) {
        if (CollectionUtils.isEmpty(staffIds)) {
            return Collections.emptyList();
        }
        return this.mapper.listByIds(staffIds);
    }

    /**
     * 查询企业下所有成员id
     *
     * @param wxEnterpriseIds
     * @return
     */
    @Override
    public List<String> queryStaffIdsWithEnterpriseId(List<String> wxEnterpriseIds) {

        if (CollectionUtils.isEmpty(wxEnterpriseIds)) {
            return Collections.emptyList();
        }
        return this.mapper.queryStaffIdsWithEnterpriseId(wxEnterpriseIds);
    }

    @Override
    public void updateStaffHead(String wxEnterpriseId , String staffId, String headUrl) {
        this.mapper.updateStaffHead(staffId,headUrl) ;
        List<StaffClerkRelationDTO> list =  this.staffClerkRelationMapper.lisByStaffId(wxEnterpriseId,staffId,null) ;
        if(CollectionUtils.isNotEmpty(list)) {
            Map<String,List<StaffClerkRelationDTO>> map = list.stream().collect(Collectors.groupingBy(StaffClerkRelationDTO::getEnterpriseId)) ;
            Set<String> set = map.keySet() ;
            Iterator<String> it = set.iterator() ;
            while(it.hasNext()) {
                String enterpriseId = it.next() ;
                List<String> clerkIdList = map.get(enterpriseId).stream().map(o->o.getClerkId()).collect(Collectors.toList());
                this.contentProducerApiService.updateClerkProducer(enterpriseId,clerkIdList,headUrl) ;
            }
        }
    }

    @Override
    public void delStaff(String wxEnterpriseId ,String staffId) {
        // 销毁卡券
        innerApiService.delCardByStaffId(staffId);
        // 删除导购好友关联关系表
        this.staffDepartmentRelatedService.delByStaffid(staffId);
        // 员工解绑
        List<StaffClerkRelationDTO> staffClerkRelationDTOS = staffClerkRelationApiService
                .listByStaffId(wxEnterpriseId, staffId);
        if (CollectionUtils.isNotEmpty(staffClerkRelationDTOS)) {
            for (StaffClerkRelationDTO staffClerkRelationDTO : staffClerkRelationDTOS) {
                staffClerkRelationApiService.unbindByStaffAndClerkId("-1", staffClerkRelationDTO.getClerkId(),
                        ChannelCodeEnum.QW_DEL_UNBIND.getCode(), wxEnterpriseId);
            }
        }
        // 群状态刷新
        this.groupChatService.ownerDimission(staffId);
        // 删除员工表-注意顺序
        this.delByStaffId(staffId);
        //活码删除
        List<Long> hmIdList = hmQrcodeService.queryByStaffIdAndOverFlag(staffId, wxEnterpriseId, 1);
        if(CollUtil.isNotEmpty(hmIdList)){
            for (Long hmId : hmIdList){
                hmQrcodeApiService.delById(hmId,ChannelCodeEnum.ADMIN_UNBIND.getCode(),null);
            }
        }
    }
}
