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

import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.clerk.api.dto.ClerkDTO;
import com.gic.clerk.api.service.ClerkService;
import com.gic.commons.util.DateUtil;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.util.UniqueIdUtils;
import com.gic.haoban.manage.api.dto.CommonMQDTO;
import com.gic.haoban.manage.api.dto.HaobanTaskNoticeDTO;
import com.gic.haoban.manage.api.dto.StaffClerkRelationDTO;
import com.gic.haoban.manage.api.dto.WxEnterpriseQwDTO;
import com.gic.haoban.manage.api.dto.moment.QwMomentPlanAttendDTO;
import com.gic.haoban.manage.api.enums.NoticeMessageTypeEnum;
import com.gic.haoban.manage.api.service.HaobanCommonMQApiService;
import com.gic.haoban.manage.api.service.HaobanTaskNoticeApiService;
import com.gic.haoban.manage.service.dao.mapper.HaobanTaskNoticeMapper;
import com.gic.haoban.manage.service.dao.mapper.StaffMapper;
import com.gic.haoban.manage.service.dao.mapper.chat.GroupChatPlanMapper;
import com.gic.haoban.manage.service.dao.mapper.chat.GroupChatPlanOwnerLogMapper;
import com.gic.haoban.manage.service.dao.mapper.moment.QwMomentPlanAttendMapper;
import com.gic.haoban.manage.service.dao.mapper.moment.QwMomentPlanMapper;
import com.gic.haoban.manage.service.entity.TabHaobanStaff;
import com.gic.haoban.manage.service.entity.TabHaobanTaskNotice;
import com.gic.haoban.manage.service.entity.chat.TabGroupChatPlan;
import com.gic.haoban.manage.service.entity.chat.TabGroupChatPlanOwnerLog;
import com.gic.haoban.manage.service.entity.moment.TabQwMomentPlan;
import com.gic.haoban.manage.service.service.StaffClerkRelationService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.redis.data.util.RedisUtil;
import com.gic.wechat.api.dto.qywx.ItemDTO;
import com.gic.wechat.api.dto.qywx.QywxXcxSendMessageDTO;
import com.gic.wechat.api.service.qywx.QywxSuiteApiService;
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.stream.Collectors;

@Service("haobanTaskNoticeApiService")
public class HaobanTaskNoticeApiServiceImpl implements HaobanTaskNoticeApiService {
    private static final Logger logger = LogManager.getLogger(HaobanTaskNoticeApiService.class);
    // 每次成员数
    private int pageSize = 1000;
    @Autowired
    private HaobanTaskNoticeMapper haobanTaskNoticeMapper;
    @Autowired
    private QywxSuiteApiService qywxSuiteApiService;
    @Autowired
    private WxEnterpriseService wxEnterpriseService;
    @Autowired
    private QwMomentPlanMapper qwMomentPlanMapper ;
    @Autowired
    private QwMomentPlanAttendMapper qwMomentPlanAttendMapper ;
    @Autowired
    private StaffClerkRelationService staffClerkRelationService ;
    @Autowired
    private StaffMapper staffMapper;
    @Autowired
    private ClerkService clerkService ;
    @Autowired
    private GroupChatPlanMapper groupChatPlanMapper ;
    @Autowired
    private GroupChatPlanOwnerLogMapper groupChatPlanOwnerLogMapper ;
    @Autowired
    private HaobanCommonMQApiService haobanCommonMQApiService ;

    int maxNum = 1 ;
    @Override
    public ServiceResponse<Void> save(HaobanTaskNoticeDTO notice) {
        Date start = DateUtil.getStartTimeOfDay() ;
        Date end = DateUtil.getEndTimeOfDay() ;
        int num = this.haobanTaskNoticeMapper.listByPlanId(notice.getPlanId(), start, end) ;
        if(num >= maxNum) {
            return ServiceResponse.failure("9999", "一天最多提醒"+maxNum+"次");
        }
        String key ="hbNotice"+ notice.getPlanId() ;
        RedisUtil.lock(key, 3L);
        try {
            if(num + 1 > maxNum) {
                return ServiceResponse.failure("9999", "一天最多提醒"+maxNum+"次");
            }
            TabHaobanTaskNotice entity = EntityUtil.changeEntityByJSON(TabHaobanTaskNotice.class, notice) ;
            entity.setId(UniqueIdUtils.uniqueLong());
            this.haobanTaskNoticeMapper.save(entity) ;
        }finally {
            RedisUtil.unlock(key);
        }
        return ServiceResponse.success();
    }

    @Override
    public HaobanTaskNoticeDTO getById(Long id) {
        TabHaobanTaskNotice notice = this.haobanTaskNoticeMapper.getById(id) ;
        if(null != notice) {
            return EntityUtil.changeEntityByJSON(HaobanTaskNoticeDTO.class, notice) ;
        }
        return null;
    }

    @Override
    public ServiceResponse<Void> sendTimer(String params) {
        List<TabHaobanTaskNotice> noticeList =  this.haobanTaskNoticeMapper.listForTimer() ;
        if(CollectionUtils.isEmpty(noticeList)) {
            return null ;
        }
        Set<String> planIdSet = new HashSet<>() ;
        this.haobanTaskNoticeMapper.updateStatus(noticeList.stream().map(o->o.getId()).collect(Collectors.toList())) ;
        for(TabHaobanTaskNotice notice :noticeList) {
            try {
                if (planIdSet.contains(notice.getPlanId())) {
                    continue;
                }
                planIdSet.add(notice.getPlanId());
                // 1群发2话务3社群4朋友圈
                if (notice.getPlanType() == 1 || notice.getPlanType() == 2) {
                    CommonMQDTO dto = new CommonMQDTO();
                    Map<String, String> map = new HashMap<>();
                    map.put("id", notice.getId() + "");
                    dto.setParams(map);
                    dto.setType(19+notice.getPlanType());
                    this.haobanCommonMQApiService.putCommonMessage(dto);
                } else if (notice.getPlanType() == 3) {
                    this.chatSend(notice);
                } else if (notice.getPlanType() == 4) {
                    this.momentSend(notice);
                }
            }catch (Exception e) {
                logger.error("发送计划任务异常",e);
            }
        }
        return null;
    }


    private void chatSend(TabHaobanTaskNotice notice) {
        Long planId = Long.parseLong(notice.getPlanId()) ;
        TabGroupChatPlan plan = this.groupChatPlanMapper.selectById(planId) ;
        if(null == plan ||plan.getStatusFlag()!=1 ||plan.getEndTime().getTime() <= System.currentTimeMillis()) {
            logger.info("任务已结束={}", planId);
            return;
        }
        int pageNum = 0;
        List<TabGroupChatPlanOwnerLog> ownerList = null;
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(plan.getWxEnterpriseId()) ;
        while (true) {
            ownerList = this.groupChatPlanOwnerLogMapper.listForDoPlan(planId, pageNum * pageSize, pageSize);
            if (CollectionUtils.isEmpty(ownerList)) {
                break;
            }
            pageNum++;
            for (TabGroupChatPlanOwnerLog ownerLog : ownerList) {
                try {
                    String clerkId = ownerLog.getClerkId() ;
                    String staffId = ownerLog.getStaffId() ;
                    String wxUserId = this.getQwUserId(qwDTO, staffId ,clerkId) ;
                    if(StringUtils.isBlank(wxUserId)) {
                        logger.info("wxUserid is null {}",clerkId);
                        continue;
                    }
                    String appUrl = NoticeMessageTypeEnum.GROUP_CHAT_PLAN.getPageUrl() + NoticeMessageTypeEnum.GROUP_CHAT_PLAN.getPageType();
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("planId",planId) ;
                    jsonObject.put("ownerLogId",ownerLog.getOwnerLogId()) ;
                    ClerkDTO clerk = this.clerkService.getclerkById(clerkId) ;
                    if(null != clerk) {
                        jsonObject.put("storeId", clerk.getStoreId());
                    }
                    appUrl += "&data=" + jsonObject.toJSONString();
                    this.send(qwDTO, wxUserId, appUrl , plan.getName() ,notice);
                }catch (Exception e) {
                    logger.error("异常",e.getMessage());
                }
            }
        }
    }
    private void momentSend(TabHaobanTaskNotice notice) {
        Long planId = Long.parseLong(notice.getPlanId()) ;
        TabQwMomentPlan plan = this.qwMomentPlanMapper.getById(planId) ;
        if(null == plan ||plan.getStatusFlag() !=1 || plan.getEndDate().getTime() <= System.currentTimeMillis()) {
            logger.info("任务已结束={}", planId);
            return;
        }
        // 判断计划
        List<QwMomentPlanAttendDTO> list = this.qwMomentPlanAttendMapper.listClerk(planId , 1);
        if (CollectionUtils.isEmpty(list)) {
            logger.info("任务已结束={}", planId);
            return;
        }
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(plan.getWxEnterpriseId()) ;
        for (QwMomentPlanAttendDTO dto : list) {
            if(dto.getTaskStatus()!=1) {
                continue;
            }
            try {
                String clerkId = dto.getClerkId();
                String wxUserId = this.getQwUserId(qwDTO, dto.getStaffId(), clerkId);
                if (StringUtils.isBlank(wxUserId)) {
                    logger.info("wxUserId is null={}", clerkId);
                    continue;
                }
                String appUrl = NoticeMessageTypeEnum.hbapp_canvas_friend_circle_task.getPageUrl() + NoticeMessageTypeEnum.hbapp_canvas_friend_circle_task.getPageType();
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("planId", planId);
                jsonObject.put("clerkId", clerkId);
                ClerkDTO clerk = this.clerkService.getclerkById(clerkId);
                if (null != clerk) {
                    jsonObject.put("storeId", clerk.getStoreId());
                }
                appUrl += "&data=" + jsonObject.toJSONString();
                this.send(qwDTO, wxUserId, appUrl, plan.getTitle(), notice);
            }catch (Exception e) {
                logger.info("发送企微通知失败：{}", e.getMessage(), e);
            }
        }
    }

    private void send(WxEnterpriseQwDTO qwDTO , String wxUserId , String appUrl , String title , TabHaobanTaskNotice notice) {
        QywxXcxSendMessageDTO xcx = new QywxXcxSendMessageDTO() ;
        xcx.setTitle("任务执行提醒");
        xcx.setAppid(qwDTO.getHbWxaAppid());
        xcx.setUserIds(Arrays.asList(wxUserId));
        xcx.setPage(appUrl);
        xcx.setItems(this.getItems(notice,title));
        this.qywxSuiteApiService.sendMessage(qwDTO.getThirdCorpid(), qwDTO.getSelf3thSecret(), xcx, qwDTO.isSelf(), qwDTO.getUrlHost());
    }


    private List<ItemDTO> getItems(TabHaobanTaskNotice notice , String title) {
        List<ItemDTO> items = new ArrayList<>() ;
        ItemDTO paramItem1 = new ItemDTO();
        paramItem1.setKey("任务类型");
        if(notice.getPlanType()==3) {
            paramItem1.setValue("社群群发");
        }
        if(notice.getPlanType()==4) {
            paramItem1.setValue("企微朋友圈");
        }
        items.add(paramItem1) ;

        ItemDTO paramItem2 = new ItemDTO();
        paramItem2.setKey("任务名称");
        paramItem2.setValue(title);
        items.add(paramItem2) ;

        if(StringUtils.isNotBlank(notice.getRemark())) {
            ItemDTO paramItem3 = new ItemDTO();
            paramItem3.setKey("执行说明");
            paramItem3.setValue(notice.getRemark());
            items.add(paramItem3);
        }
        return items;
    }


    private String getQwUserId(WxEnterpriseQwDTO qwDTO ,String staffId , String clerkId) {
        if(StringUtils.isBlank(staffId) && StringUtils.isBlank(clerkId)) {
            return null ;
        }
        if(StringUtils.isBlank(staffId)) {
            StaffClerkRelationDTO clerkRelationDTO = staffClerkRelationService.getByClerkId(clerkId);
            if(clerkRelationDTO == null) {
                return null ;
            }
            staffId = clerkRelationDTO.getStaffId() ;
        }
        TabHaobanStaff staff = this.staffMapper.selectByPrimaryKey(staffId) ;
        if(null == staff) {
            return null ;
        }
         String wxUserId = staff.getWxUserId();
        if (qwDTO.needOpenUserId3th()) {
            wxUserId = staff.getWxOpenUseId();
        }
        return wxUserId ;
    }

}
