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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.Page;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.clerk.api.dto.ClerkDTO;
import com.gic.clerk.api.service.ClerkService;
import com.gic.clerk.api.service.PowerService;
import com.gic.commons.util.*;
import com.gic.enterprise.api.dto.EnterpriseSettingDTO;
import com.gic.enterprise.api.dto.StoreSearchDTO;
import com.gic.enterprise.api.service.EnterpriseService;
import com.gic.enterprise.api.service.StoreService;
import com.gic.enterprise.api.service.StoreWidgetService;
import com.gic.haoban.manage.api.dto.ContentMaterialDTO;
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.dto.moment.QwMomentPlanDTO;
import com.gic.haoban.manage.api.dto.moment.QwMomentPlanWxaDTO;
import com.gic.haoban.manage.api.enums.NoticeMessageTypeEnum;
import com.gic.haoban.manage.api.qdto.moment.PlanListWxaQDTO;
import com.gic.haoban.manage.api.qdto.moment.QwMomentPlanQDTO;
import com.gic.haoban.manage.api.qdto.moment.TaskNumQDTO;
import com.gic.haoban.manage.api.service.StaffClerkRelationApiService;
import com.gic.haoban.manage.api.util.notify.NoticeMessageUtil;
import com.gic.haoban.manage.service.dao.mapper.StaffMapper;
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.moment.TabQwMomentPlan;
import com.gic.haoban.manage.service.entity.moment.TabQwMomentPlanAttend;
import com.gic.haoban.manage.service.service.QywxSendService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.haoban.manage.service.service.moment.QwMomentPlanAttendService;
import com.gic.haoban.manage.service.service.moment.QwMomentPlanDataService;
import com.gic.haoban.manage.service.service.moment.QwMomentPlanService;
import com.gic.mq.sdk.GicMQClient;
import com.gic.quartz.api.dto.QuartzTaskDTO;
import com.gic.quartz.api.service.QuartzService;
import com.gic.wechat.api.dto.qywx.moment.MomentResultDTO;
import com.gic.wechat.api.service.qywx.QywxExternalUserService;
import com.github.pagehelper.PageHelper;
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("qwMomentPlanService")
public class QwMomentPlanServiceImpl implements QwMomentPlanService {

    private final Logger logger = LogManager.getLogger(this.getClass());
    @Autowired
    private QwMomentPlanMapper qwMomentPlanMapper ;
    @Autowired
    private QwMomentPlanAttendService qwMomentPlanAttendService ;
    @Autowired
    private QwMomentPlanAttendMapper qwMomentPlanAttendMapper ;
    @Autowired
    private QuartzService quartzService;
    @Autowired
    private ClerkService clerkService ;
    @Autowired
    private EnterpriseService enterpriseService ;
    @Autowired
    private StoreService storeService ;
    @Autowired
    private StaffClerkRelationApiService staffClerkRelationApiService;
    @Autowired
    private PowerService powerService ;
    @Autowired
    private StoreWidgetService storeWidgetService ;
    @Autowired
    private QywxSendService qywxSendService ;
    @Autowired
    private QywxExternalUserService qywxExternalUserService;
    @Autowired
    private WxEnterpriseService wxEnterpriseService ;
    @Autowired
    private StaffMapper staffMapper ;
    @Autowired
    private QwMomentPlanDataService qwMomentPlanDataService ;

    private GicMQClient clientInstance = GICMQClientUtil.getClientInstance();

    @Override
    public ServiceResponse<Page<QwMomentPlanDTO>> planList(QwMomentPlanQDTO qdto) {
        PageHelper.startPage(qdto);
        if(StringUtils.isNotEmpty(qdto.getNameParams())) {
            qdto.setNameParamsLike("%"+qdto.getNameParams()+"%");
        }
        if(StringUtils.isBlank(qdto.getSortColumn())) {
            qdto.setSortColumn("create_time");
        }
        if(StringUtils.isBlank(qdto.getSortType())) {
            qdto.setSortType("desc");
        }
        List<TabQwMomentPlan> list = this.qwMomentPlanMapper.list(qdto);
        Page<QwMomentPlanDTO> retPage = PageHelperUtils.changePageHelperToCurrentPage(list, QwMomentPlanDTO.class);
        return ServiceResponse.success(retPage);
    }


    @Override
    public ServiceResponse<Page<QwMomentPlanWxaDTO>> planListWxa(PlanListWxaQDTO qdto) {
        PageHelper.startPage(qdto);
        if(StringUtils.isNotEmpty(qdto.getName())) {
            qdto.setNameLike("%"+qdto.getName()+"%");
        }
        List<QwMomentPlanWxaDTO> list = this.qwMomentPlanMapper.planListWxa(qdto);
        Page<QwMomentPlanWxaDTO> retPage = PageHelperUtils.changePageHelperToCurrentPage(list, QwMomentPlanWxaDTO.class);
        return ServiceResponse.success(retPage);
    }

    @Override
    public ServiceResponse<QwMomentPlanDTO> save(QwMomentPlanDTO dto) {
        logger.info("保存朋友圈活动={}", JSONObject.toJSONString(dto));
        String enterpriseId = dto.getEnterpriseId() ;
        String wxEnterpriseId = dto.getWxEnterpriseId() ;
        Long planId = dto.getPlanId() ;
        boolean publishNow = dto.getPublishType()==1 ;
        TabQwMomentPlan plan = EntityUtil.changeEntity(TabQwMomentPlan.class,dto) ;
        Date now = new Date() ;
        plan.setUpdateTime(now);
        // 1立即发布2定时发布
        if(publishNow) {
            plan.setPublishTime(now);
        }
        boolean createFlag = false ;
        boolean publishFlag = false ;
        plan.setBeginDate(plan.getPublishTime());
        Date endTime = DateUtil.getEndTimeOfDay(DateUtil.addDay(plan.getBeginDate(), plan.getExpireDays()));
        plan.setEndDate(endTime);
        if(null == planId) {
            createFlag = true ;
            planId = UniqueIdUtils.uniqueLong();
            dto.setPlanId(planId);
            plan.setPlanId(planId);
            plan.setCreateTime(now);
            plan.setStatusFlag(1);
            this.qwMomentPlanMapper.insert(plan);
        }else {
            TabQwMomentPlan oldPlan = this.qwMomentPlanMapper.getById(planId) ;
            // 更新为立即发布
            if(oldPlan.getPublishType()==2 && publishNow) {
                publishFlag = true ;
            }
            this.qwMomentPlanMapper.update(plan);
        }
        // 参与导购
        if(dto.getPlanClerkType()==1) {
            if (createFlag) {
                this.qwMomentPlanAttendService.saveClerk(wxEnterpriseId,enterpriseId, planId,dto.getSelectClerkIdList());
            } else {
                List<String> oldList = this.qwMomentPlanAttendMapper.listClerk(planId).stream().map(o -> o.getClerkId()).collect(Collectors.toList());
                List<String> newList = dto.getSelectClerkIdList();
                List<String> addList = newList.stream().filter(o -> !oldList.contains(o)).distinct().collect(Collectors.toList());
                List<String> delList = oldList.stream().filter(o -> !newList.contains(o)).distinct().collect(Collectors.toList());
                this.qwMomentPlanAttendService.saveClerk(wxEnterpriseId,enterpriseId, planId , addList);
                if (CollectionUtils.isNotEmpty(delList)) {
                    this.qwMomentPlanAttendMapper.delClerks(planId, delList);
                }
            }
        }
        if(!publishNow) {
            this.addOrDelTimer(planId, plan.getPublishTime(), 1);
        }else {
            this.addOrDelTimer(planId, new Date(), 0);
            if(createFlag || publishFlag) {
               JSONObject jsonObject = new JSONObject() ;
                jsonObject.put("planId",planId) ;
                try {
                    // initTaskClerk
                    logger.info("立即开始执行");
                    this.initTaskClerk(jsonObject.toJSONString());
                   // clientInstance.sendMessage("qwMomentInitClerkMQ", jsonObject.toJSONString(),10);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return ServiceResponse.success(dto);
    }

    private void sendTaskToClerk(String clerkId, TabQwMomentPlan plan) {
        String enterpriseId = plan.getEnterpriseId() ;
        Long planId = plan.getPlanId() ;
        String planName = plan.getTitle() ;
        String invalidTime = DateUtil.dateToStr(plan.getEndDate(),"yyyy-MM-dd HH:mm:ss") ;
        logger.info("发送任务通知,clerkId={}",clerkId);
        Map<String, String> map = new HashMap<>();
        map.put("taskName",planName) ;
        map.put("invalidTime",invalidTime) ;
        int messageType =  NoticeMessageTypeEnum.hbapp_canvas_friend_circle_task.getType();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("planId",planId) ;
        jsonObject.put("clerkId",clerkId) ;
        NoticeMessageUtil.sendNoticeMessage(enterpriseId,clerkId,messageType,null,map,jsonObject);
    }


    @Override
    public ServiceResponse<Void> del(Long planId) {
        this.qwMomentPlanMapper.del(planId);
        return ServiceResponse.success();
    }

    @Override
    public ServiceResponse<Void> stop(Long planId) {
        TabQwMomentPlan plan = this.qwMomentPlanMapper.getById(planId) ;
        this.qwMomentPlanMapper.stop(planId);
        if(plan.getExecType()==0 && StringUtils.isNotBlank(plan.getMomentId())) {
            String wxEnterpriseId = plan.getWxEnterpriseId() ;
            WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId) ;
            logger.info("取消发送={},{}",planId,plan.getMomentId());
            this.qywxExternalUserService.cancelMomentTask(qwDTO.getThirdCorpid(),
                    qwDTO.getSelf3thSecret(), plan.getMomentId() ,qwDTO.isSelf(),qwDTO.getUrlHost()) ;
        }
        return ServiceResponse.success();
    }

    @Override
    public ServiceResponse<QwMomentPlanDTO> detail(Long planId) {
        TabQwMomentPlan plan = this.qwMomentPlanMapper.getById(planId);
        QwMomentPlanDTO dto = EntityUtil.changeEntityByJSON(QwMomentPlanDTO.class,plan) ;
        // 获取参与导购
        if(dto.getPlanClerkType()==1) {
            List<QwMomentPlanAttendDTO> clerkList = this.qwMomentPlanAttendMapper.listClerk(planId) ;
            dto.setClerkList(clerkList);
        }
        return ServiceResponse.success(dto);
    }

    private void addOrDelTimer(Long planId, Date sendTime, int status) {
        logger.info("添加1/删除0定时,{},{}", status, planId);
        QuartzTaskDTO quartzTask = new QuartzTaskDTO();
        quartzTask.setTaskStatus(status);
        String taskTimeInfo = this.getTaskTime(sendTime);
        quartzTask.setTaskTimeInfo(taskTimeInfo);
        quartzTask.setTaskService("com.gic.haoban.manage.api.service.moment.QwMomentApiService");
        quartzTask.setTaskMethod("sendPlanNoticeTimer");
        quartzTask.setTaskParam(planId + "");
        quartzTask.setReferId(planId + "");
        try {
            quartzService.addOrUpdateQuartzTask(quartzTask);
        } catch (Exception e) {
            logger.warn("提交定时任务异常", e);
        }
    }

    private String getTaskTime(Date date) {
        String timeInfo = DateUtil.dateToStr(date, "yyyyMMddHHmmss");
        String year = timeInfo.substring(0, 4);
        int month = Integer.parseInt(timeInfo.substring(4, 6));
        int day = Integer.parseInt(timeInfo.substring(6, 8));
        int hour = Integer.parseInt(timeInfo.substring(8, 10));
        int minute = Integer.parseInt(timeInfo.substring(10, 12));
        int second = Integer.parseInt(timeInfo.substring(12, 14));
        String time = new StringBuilder().append(second).append(" ").append(minute).append(" ").append(hour).append(" ")
                .append(day).append(" ").append(month).append(" ").append(year).toString();
        return time;
    }


    private void saveAttendClerkForTask(TabQwMomentPlan plan) {
        Long planId = plan.getPlanId() ;
        String creatorId = plan.getCreatorId() ;
        String enterpriseId = plan.getEnterpriseId() ;
        ClerkDTO clerkDTO = this.clerkService.getclerkById(creatorId) ;
        EnterpriseSettingDTO enterpriseSetting = enterpriseService.getEnterpriseSettingByEnterpriseId(enterpriseId);
        List<String> storeIdList = null ;
        if(clerkDTO.getClerkType()==3 || !(enterpriseSetting.getEnableAccessControl() != null && enterpriseSetting.getEnableAccessControl() == 1)) {
            logger.info("超管");
            StoreSearchDTO searchDTO = new StoreSearchDTO() ;
            searchDTO.setEnterpriseId(plan.getEnterpriseId());
            searchDTO.setStatus("2");
            storeIdList = this.storeService.listStoreIds(searchDTO) ;
        }else {
            storeIdList = this.getStoreIdList(clerkDTO) ;
        }
        List<StaffClerkRelationDTO> list = this.staffClerkRelationApiService.listByStoreIds(null , storeIdList) ;
        List<String> clerkIdList = list.stream().map(o->o.getClerkId()).collect(Collectors.toList()) ;
        Page<ClerkDTO> userPage = this.clerkService.pageUserBySearchName(plan.getEnterpriseId(),null,1,1000) ;
        List<String> userIdList = userPage.getResult().stream().map(o->o.getClerkId()).collect(Collectors.toList());
        logger.info("管理员列表={}",userIdList);
        clerkIdList.stream().filter(o->!userIdList.contains(o)).collect(Collectors.toList()) ;
        logger.info("导购数量={}",clerkIdList.size());
        this.qwMomentPlanAttendService.saveClerk(plan.getWxEnterpriseId(),plan.getEnterpriseId(),planId, clerkIdList);
        this.qwMomentPlanMapper.updateClerkNum(planId,clerkIdList.size(),-1,-1);
    }

    private List<String> getStoreIdList(ClerkDTO clerkDTO) {
        String clerkId = clerkDTO.getClerkId();
        String enterpriseId = clerkDTO.getEnterpriseId();
        String storeWidgetId = this.powerService.getStoreWidgetId(null, clerkId);
        // 门店id列表
        List<String> storeIdList = storeWidgetService.getStoreWidgetStore(storeWidgetId, enterpriseId, null, null, 2);
        logger.info("组件id={},上线数量:{}", storeWidgetId,storeIdList.size());
        if (CollectionUtils.isEmpty(storeIdList)) {
            return Collections.emptyList();
        }
        return storeIdList;
    }

    @Override
    public void initTaskClerk(String params) {
        logger.info("创建立即执行朋友圈={}",params);
        JSONObject json = JSONObject.parseObject(params) ;
        Long planId = json.getLong("planId") ;
        TabQwMomentPlan plan = this.qwMomentPlanMapper.getById(planId) ;
        this.send(plan);
    }

    @Override
    public void sendPlanNoticeTimer(String params) {
        logger.info("定时发布任务发送通知={}",params);
        Long planId = Long.valueOf(params) ;
        TabQwMomentPlan plan = this.qwMomentPlanMapper.getById(planId) ;
        this.send(plan);
    }

    private void send(TabQwMomentPlan plan) {
        // 0全部导购 1部分导购
        if(plan.getPlanClerkType()==0) {
            this.saveAttendClerkForTask(plan) ;
        }
        this.sendPlanNotice(plan);
    }

    // 发送活动通知
    private void sendPlanNotice(TabQwMomentPlan plan) {
        if(plan.getPublishType()==1 || plan.getPublishTime().getTime() <= System.currentTimeMillis()) {
            long planId = plan.getPlanId();
            if(plan.getExecType()==1) {
                // 好办小程序
                List<QwMomentPlanAttendDTO> list = this.qwMomentPlanAttendMapper.listClerk(planId);
                if (CollectionUtils.isNotEmpty(list)) {
                    for (QwMomentPlanAttendDTO dto : list) {
                        this.sendTaskToClerk(dto.getClerkId(),plan);
                    }
                }
            }else {
                // 企微下发任务
                this.sendToQiwei(plan);
            }
        }
    }

    private void sendToQiwei(TabQwMomentPlan plan) {
        List<ContentMaterialDTO> imageList = new ArrayList<>() ;
        String json = plan.getMediaInfo() ;
        JSONArray arr = JSONArray.parseArray(json) ;
        String msg = null ;
        for(int i=0;i<arr.size();i++) {
            JSONObject obj  = arr.getJSONObject(i) ;
            ContentMaterialDTO vo = new ContentMaterialDTO();
            vo.setMaterialType(obj.getInteger("materialType"));
            vo.setImgUrl(obj.getString("imgUrl"));
            if(vo.getMaterialType()==4) {
                vo.setLink(obj.getString("videoUrl"));
            }
            if(vo.getMaterialType()==3) {
                vo.setLink(obj.getString("link"));
            }
            vo.setMaterialTitle(obj.getString("title"));
            if(vo.getMaterialType()==1) {
                msg = obj.getString("contentText") ;
                continue;
            }
            vo.setMaterialDesc(obj.getString("contentText"));
            imageList.add(vo);
        }
        ServiceResponse<String> resp = this.qywxSendService.share(plan.getWxEnterpriseId(),Arrays.asList("b2ef17cce11f476b996d0b27ebadf7fb"),msg,imageList) ;
        logger.info("发企微朋友={}",JSONObject.toJSONString(resp));
        String jobId = resp.getResult() ;
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(plan.getWxEnterpriseId());
        ServiceResponse<Object> resp2 = this.qywxExternalUserService.getMomentTaskResult(qwDTO.getThirdCorpid(),
                qwDTO.getSelf3thSecret(), jobId,qwDTO.isSelf(),qwDTO.getUrlHost()) ;
        logger.info("获取moment_id={}",JSONObject.toJSONString(resp2));
        String moment_id = resp2.getResult().toString() ;
    }

    @Override
    public ServiceResponse<Integer> getTaskNum(TaskNumQDTO qdto) {
        int count = this.qwMomentPlanMapper.getTaskNum(qdto);
        return ServiceResponse.success(count);
    }

    @Override
    public void getQwData(TabQwMomentPlanAttend task) {
        MomentResultDTO dto = this.getQwData(task.getStaffId(),task.getMomentId(),task.getWxEnterpriseId()) ;
        this.qwMomentPlanDataService.save(task,dto) ;
    }

    private MomentResultDTO getQwData(String staffId , String momentId ,  String wxEnterpriseId) {
        WxEnterpriseQwDTO qwDTO = this.wxEnterpriseService.getQwInfo(wxEnterpriseId) ;
        return this.getData(staffId,momentId,qwDTO);
    }

    private MomentResultDTO getData(String staffId , String momentId , WxEnterpriseQwDTO qwDTO) {
        TabHaobanStaff staff =  this.staffMapper.selectByPrimaryKey(staffId) ;
        String wxUserId = staff.getWxUserId() ;
        if(qwDTO.needOpenUserId3th()) {
            wxUserId = staff.getWxOpenUseId() ;
        }
        ServiceResponse<MomentResultDTO> resp = this.qywxExternalUserService.getMomentComments(qwDTO.getThirdCorpid(),
                qwDTO.getSelf3thSecret(), momentId,wxUserId,qwDTO.isSelf(),qwDTO.getUrlHost()) ;
        MomentResultDTO dto  = resp.getResult() ;
        return dto ;
    }
}
