package com.sino.mci.send.mq;

import com.sino.mci.mq.config.MqConfig;
import com.sino.mci.policy.engine.RetryConfig;
import com.sino.mci.send.entity.SendRecord;
import com.sino.mci.send.repository.SendRecordMapper;
import com.sino.mci.send.service.SendCallbackService;
import com.sino.mci.send.service.SendService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Slf4j
@Component
@RequiredArgsConstructor
public class SendMessageConsumer {

    private static final int SEND_STATUS_SUCCESS = 2;
    private static final int SEND_STATUS_FAILED = 3;

    private final SendRecordMapper sendRecordMapper;
    private final SendService sendService;
    private final SendMessageProducer sendMessageProducer;
    private final SendCallbackService sendCallbackService;

    @RabbitListener(queues = MqConfig.SEND_QUEUE)
    public void handle(SendRecordMessage message) {
        log.info("收到异步发送消息: recordId={}, attempt={}", message.getRecordId(), message.getAttempt());
        SendRecord record = sendRecordMapper.selectById(message.getRecordId());
        if (record == null) {
            log.warn("发送记录不存在: recordId={}", message.getRecordId());
            return;
        }

        if (record.getSendStatus() != null && record.getSendStatus() == SEND_STATUS_SUCCESS) {
            sendCallbackService.sendCallback(record);
            return;
        }

        if (record.getSendStatus() != null && record.getSendStatus() == SEND_STATUS_FAILED) {
            sendCallbackService.sendCallback(record);
            return;
        }

        int attempt = message.getAttempt();
        int maxRetry = record.getMaxRetry() != null ? record.getMaxRetry() : 0;
        int currentRetry = record.getRetryCount() != null ? record.getRetryCount() : 0;

        if (attempt < currentRetry) {
            log.warn("丢弃过期重试消息: recordId={}, attempt={}, currentRetry={}",
                    record.getId(), attempt, currentRetry);
            return;
        }

        if (attempt > maxRetry) {
            record.setSendStatus(SEND_STATUS_FAILED);
            record.setFinishTime(LocalDateTime.now());
            sendRecordMapper.updateById(record);
            sendCallbackService.sendCallback(record);
            return;
        }

        try {
            sendService.dispatchRecord(record);

            record = sendRecordMapper.selectById(record.getId());
            if (record == null) {
                return;
            }

            if (record.getSendStatus() != null && record.getSendStatus() == SEND_STATUS_SUCCESS) {
                sendCallbackService.sendCallback(record);
            } else if (record.getSendStatus() != null && record.getSendStatus() == SEND_STATUS_FAILED) {
                handleRetry(record, message);
            }
        } catch (Exception e) {
            log.error("异步发送处理异常: recordId={}", message.getRecordId(), e);
        }
    }

    private void handleRetry(SendRecord record, SendRecordMessage message) {
        int currentRetry = record.getRetryCount() != null ? record.getRetryCount() : 0;
        int maxRetry = record.getMaxRetry() != null ? record.getMaxRetry() : 0;
        if (currentRetry >= maxRetry) {
            sendCallbackService.sendCallback(record);
            return;
        }

        int attempt = message.getAttempt() + 1;
        int delaySeconds = resolveDelaySeconds(message.getRetryPlan(), attempt);
        SendRecordMessage retryMessage = SendRecordMessage.builder()
                .recordId(message.getRecordId())
                .taskId(message.getTaskId())
                .tenantCode(message.getTenantCode())
                .attempt(attempt)
                .retryPlan(message.getRetryPlan())
                .build();

        record.setRetryCount(attempt);
        record.setNextRetryTime(LocalDateTime.now().plusSeconds(delaySeconds));
        sendRecordMapper.updateById(record);

        sendMessageProducer.publishRetryMessage(retryMessage, delaySeconds);
    }

    private int resolveDelaySeconds(RetryConfig retryPlan, int attempt) {
        if (retryPlan != null && retryPlan.getIntervals() != null && !retryPlan.getIntervals().isEmpty()) {
            int index = Math.min(attempt - 1, retryPlan.getIntervals().size() - 1);
            return retryPlan.getIntervals().get(index);
        }
        return 5;
    }
}
