package com.liquidnet.service.consumer.base.receiver;

import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.HttpUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.OrderCloseMapping;
import com.liquidnet.service.base.ResponseDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.connection.stream.MapRecord;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.stream.StreamListener;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.util.HashMap;

@Slf4j
public abstract class AbstractOptOrderTransferOverTimeRedisReceiver implements StreamListener<String, MapRecord<String, String, String>> {
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Value("${liquidnet.service.kylin.url}")
    private String kylinUrl;
    @Override
    public void onMessage(MapRecord<String, String, String> message) {
        String redisStreamKey = this.getRedisStreamKey();
        log.debug("CONSUMER MSG[streamKey:{},messageId:{},stream:{},body:{}]", redisStreamKey, message.getId(), message.getStream(), message.getValue());
        boolean result = this.consumerMessageHandler(message.getValue().get("message"));
        log.info("CONSUMER MSG RESULT:{} ==> [{}]MESSAGE_ID:{}", result, redisStreamKey, message.getId());

        try {
            stringRedisTemplate.opsForStream().acknowledge(getRedisStreamGroup(), message);
        } catch (Exception e) {
            log.error("#CONSUMER MSG EX_ACK ==> [{}]RESULT:{},MESSAGE:{}", redisStreamKey, result, message.getValue(), e);
        }
        try {
            stringRedisTemplate.opsForStream().delete(redisStreamKey, message.getId());
        } catch (Exception e) {
            log.error("#CONSUMER MSG EX_DEL ==> [{}]RESULT:{},MESSAGE:{}", redisStreamKey, result, message.getValue(), e);
        }
    }

    private boolean consumerMessageHandler(String msg) {
        boolean aBoolean = false;
        try {
            OrderCloseMapping.orderCloseMessage mqMessage = JsonUtils.fromJson(msg, OrderCloseMapping.orderCloseMessage.class);
            if (mqMessage == null) {

            } else {
                for (int x = 0; x < mqMessage.getOrderTicketIds().size(); x++) {
                    String orderTicketId = mqMessage.getOrderTicketIds().get(x);
                    MultiValueMap<String, String> params = new LinkedMultiValueMap();
                    params.add("orderId", orderTicketId);
                    MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
                    headers.add("Accept", "application/json;charset=UTF-8");
                    String returnData = HttpUtil.post(kylinUrl + "/inner/consumer/orderTransferOverTime", params, headers);
                    ResponseDto<Boolean> rsp = JsonUtils.fromJson(returnData, new TypeReference<ResponseDto<Boolean>>() {});
                }
            }
            aBoolean = true;
        } catch (Exception e) {
            log.error("CONSUMER MSG EX_HANDLE ==> [{}]:{}", this.getRedisStreamKey(), msg, e);
        } finally {
            if (!aBoolean) {
                HashMap<String, String> map = CollectionUtil.mapStringString();
                map.put("message", msg);
                stringRedisTemplate.opsForStream().add(StreamRecords.mapBacked(map).withStreamKey(this.getRedisStreamKey()));
            }
        }
        return aBoolean;
    }

    protected abstract String getRedisStreamKey();

    protected abstract String getRedisStreamGroup();
}
