package com.kiisoo.ic.job.behavior;

import com.kiisoo.ic.config.WxCpConfiguration;
import com.kiisoo.ic.employee.mapper.PrivilageCpUserDOMapper;
import com.kiisoo.ic.generalize.mapper.PoiCustomerContactDataStatMapper;
import com.kiisoo.ic.store.mapper.PrivilageCpUserStoreDOMapper;
import com.kiisoo.ic.store.mapper.StorePromotionDataDOMapper;
import com.kiisoo.ic.system.entity.SysTaskDO;
import com.kiisoo.ic.system.mapper.SysTaskDOMapper;
import com.kiisoo.ic.utils.DateUtils;
import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceOkHttpImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.kiisoo.ic.config.WxCpConfiguration.APPLICATIONID;
import static com.kiisoo.ic.system.constant.SysTaskConstant.TASK_STATUS_FINISHED;

/**
 * Disruptor多个消费者不重复处理生产者发送过来的消息
 */
@Service
@Slf4j
public class CustomerBehaviorJob {


    // 指定 ring buffer字节大小，必需为2的N次方(能将求模运算转为位运算提高效率 )，否则影响性能
    private static final int BUFFER_SIZE = 1024 * 1024;
    //固定线程数
    private static final int THREAD_NUMBERS = 40;


    @Autowired
    private PrivilageCpUserDOMapper privilageCpUserDOMapper;
    @Autowired
    private PrivilageCpUserStoreDOMapper privilageCpUserStoreDOMapper;
    @Autowired
    private PoiCustomerContactDataStatMapper poiCustomerContactDataStatMapper;
    @Autowired
    private StorePromotionDataDOMapper storePromotionDataDOMapper;
    @Autowired
    private SysTaskDOMapper sysTaskDOMapper;


    public void handle(Date startDate, Date endDate, SysTaskDO sysTaskDO) throws WxErrorException {

        //创建线程池
        ExecutorService executors = Executors.newFixedThreadPool(THREAD_NUMBERS);
        // 创建缓冲池
        Disruptor<BehaviorDTOMessage> disruptor = new Disruptor<>(new BehaviorCountDTOMessageFactory(), BUFFER_SIZE, executors,
                ProducerType.SINGLE, new BlockingWaitStrategy());
        RingBuffer<BehaviorDTOMessage> ringBuffer = disruptor.getRingBuffer();

        // 创建100个消费者来处理同一个生产者发的消息(这100个消费者不重复消费消息)
        BehaviorDTOMessageGroupConsumer[] consumers = new BehaviorDTOMessageGroupConsumer[THREAD_NUMBERS];
        for (int i = 0; i < consumers.length; i++) {
            consumers[i] = new BehaviorDTOMessageGroupConsumer();
        }

        disruptor.handleEventsWithWorkerPool(consumers);

        disruptor.start();

        BehaviorDTOMessageEventProducer producer = new BehaviorDTOMessageEventProducer(ringBuffer, privilageCpUserStoreDOMapper,poiCustomerContactDataStatMapper,storePromotionDataDOMapper,privilageCpUserDOMapper);


        WxCpServiceOkHttpImpl wxCpService = WxCpConfiguration.getCpService(APPLICATIONID);
        WxCpExternalContactService externalContactService = wxCpService.getExternalContactService();
        //查询企业微信已配置联系我的用户
        List<String> cpUserIds = externalContactService.listFollowers();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        int index =0;
        if (sdf.format(startDate).equals(sdf.format(endDate))){
            for (String cpUserId : cpUserIds) {
                producer.produceData(index,cpUserId,DateUtils.formatHourMinuteAndSecondToZero(startDate));
                index++;
            }
        }else{
            List<Date> dates = DateUtils.getdays(startDate, endDate);
            for (Date date:dates){
                for (String cpUserId : cpUserIds) {
                    producer.produceData(index,cpUserId,date);
                    index++;
                }
            }
        }



        disruptor.shutdown();

        if (sysTaskDO !=null){
            sysTaskDO.setStatus(TASK_STATUS_FINISHED);
            sysTaskDO.setUpdateTime(new Date());
            sysTaskDOMapper.updateById(sysTaskDO);
            System.out.println(sysTaskDO);
        }
    }
}
