package net.northking.cctp.scriptcase.bus;


import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.northking.cctp.common.exception.PlatformRuntimeException;
import net.northking.cctp.scriptcase.api.casedesign.service.MqSynchronizeTaskApiService;
import net.northking.cctp.scriptcase.db.entity.MqSynchronizeTask;
import net.northking.cctp.scriptcase.db.entity.ReBusComponentInfo;
import net.northking.cctp.scriptcase.dto.casedesign.MqSynchronizeTaskAddDto;
import net.northking.cctp.scriptcase.enums.ErrorMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

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

@Component
public class SyncData2DwPublisher {

    /**
     * 日志
     */
    private final static Logger logger = LoggerFactory.getLogger(SyncData2DwPublisher.class);

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private MqSynchronizeTaskApiService mqSynchronizeTaskApiService;
    @Autowired
    private RedisLockRegistry redisLockRegistry;

    @Scheduled(fixedDelay =2*60* 1000L)
    public void syncAtuScriptInfo() {
        Lock lock = redisLockRegistry.obtain("syncAtuScriptInfo");
        try {
            boolean b = lock.tryLock(10, TimeUnit.SECONDS);
            if (b){
                byte[] json;
                //查询
                List<MqSynchronizeTask> mqSynchronizeTasks= mqSynchronizeTaskApiService.findByTypes(Arrays.asList(1,3,4));
                //处理推送数据
                if (mqSynchronizeTasks.size()!=0){
                    //删除
                    List<Object> ids = mqSynchronizeTasks.stream().map(MqSynchronizeTask::getId).collect(Collectors.toList());
                    mqSynchronizeTaskApiService.deleteBatch(ids);
                    //处理数据
                    List<MqSynchronizeTaskAddDto> mqSynchronizeTaskAddDtos=new ArrayList<>();
                    for (MqSynchronizeTask mqSynchronizeTask: mqSynchronizeTasks) {
                        MqSynchronizeTaskAddDto mqSynchronizeTaskAddDto = JSONObject.parseObject(mqSynchronizeTask.getTaskInfo(), MqSynchronizeTaskAddDto.class);
                        mqSynchronizeTaskAddDtos.add(mqSynchronizeTaskAddDto);
                    }
                    // 分包发送
                    int count = 20;
                    Integer num = mqSynchronizeTaskAddDtos.size();
                    for (int i = 0; i < num / count + 1; i++) {
                        if (i * count == num) {
                            break;
                        }
                        int stop = (i + 1) * count > num ? num : (i + 1) * count;
                        List<MqSynchronizeTaskAddDto> subMqSynchronizeTaskAddDtos = mqSynchronizeTaskAddDtos.subList(i * count, stop);

                        json = objectMapper.writeValueAsBytes(subMqSynchronizeTaskAddDtos);
                        MessageBuilder mb = MessageBuilder.withBody(json);
                        mb.setContentType(MediaType.APPLICATION_JSON_VALUE);
                        rabbitTemplate.send("Dw.AtuScriptInfo.Insert.REQ", mb.build());
                    }
                }
            }

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new PlatformRuntimeException(new ErrorMessage(e.getMessage()));
        } catch (JsonProcessingException e) {
            throw new PlatformRuntimeException(new ErrorMessage("同步脚本数据以及脚本版本消息发送失败！！！"));
        }finally {
            lock.unlock();
        }
    }
    //同步已发布业务组件数据
    @Scheduled(fixedDelay =2*60* 1000L)
    public void syncBusComponentInfo(){
        Lock lock = redisLockRegistry.obtain("syncBusComponentInfo");
        try {
            boolean b = lock.tryLock(10, TimeUnit.SECONDS);
            if (b){
                byte[] json;
                //查询
                List<MqSynchronizeTask> mqSynchronizeTasks= mqSynchronizeTaskApiService.findByTypes(Collections.singletonList(2));
                //处理推送数据
                if (mqSynchronizeTasks.size()!=0){
                    //删除
                    List<Object> ids = mqSynchronizeTasks.stream().map(MqSynchronizeTask::getId).collect(Collectors.toList());
                    mqSynchronizeTaskApiService.deleteBatch(ids);
                    //处理数据
                    List<ReBusComponentInfo> reBusComponentInfos=new ArrayList<>();
                    for (MqSynchronizeTask mqSynchronizeTask: mqSynchronizeTasks) {
                        ReBusComponentInfo reBusComponentInfo = JSONObject.parseObject(mqSynchronizeTask.getTaskInfo(), ReBusComponentInfo.class);
                        reBusComponentInfos.add(reBusComponentInfo);
                    }
                    //根据更新时间获取相同id最新的更新记录
                    List<String> idList = reBusComponentInfos.stream().map(ReBusComponentInfo::getId).distinct().collect(Collectors.toList());
                    Map<String, List<ReBusComponentInfo>> map = reBusComponentInfos.stream().collect(Collectors.groupingBy(ReBusComponentInfo::getId));
                    List<ReBusComponentInfo> reBusComponentInfoList=new ArrayList<>();
                    for (String id:idList) {
                        List<ReBusComponentInfo> reBusComponentInfosTmp = map.get(id);
                        List<ReBusComponentInfo> collect = reBusComponentInfosTmp.stream().sorted(Comparator.comparing(ReBusComponentInfo::getUpdatedTime).reversed()).collect(Collectors.toList());
                        reBusComponentInfoList.add(collect.get(0));
                    }
                    // 分包发送
                    int count = 20;
                    Integer num = reBusComponentInfoList.size();
                    for (int i = 0; i < num / count + 1; i++) {
                        if (i * count == num) {
                            break;
                        }
                        int stop = (i + 1) * count > num ? num : (i + 1) * count;
                        List<ReBusComponentInfo> subReBusComponentInfos = reBusComponentInfoList.subList(i * count, stop);

                        json = objectMapper.writeValueAsBytes(subReBusComponentInfos);
                        MessageBuilder mb = MessageBuilder.withBody(json);
                        mb.setContentType(MediaType.APPLICATION_JSON_VALUE);
                        rabbitTemplate.send("Dw.ReBusComponent.Insert.REQ", mb.build());
                    }
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new PlatformRuntimeException(new ErrorMessage(e.getMessage()));
        } catch (JsonProcessingException e) {
            throw new PlatformRuntimeException(new ErrorMessage("同步已发布业务组件消息发送失败！！！"));
        } finally {
            lock.unlock();
        }
    }
}
