package com.ycwl.basic.integration.profitshare.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ycwl.basic.integration.kafka.config.KafkaIntegrationProperties;
import com.ycwl.basic.integration.profitshare.dto.message.OrderMessage;
import com.ycwl.basic.integration.profitshare.dto.message.RefundMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.CompletableFuture;

/**
 * 分账Kafka消息生产者
 *
 * @author Claude Code
 * @date 2025-01-11
 */
@Slf4j
@Service
@RequiredArgsConstructor
@ConditionalOnProperty(name = "kafka.enabled", havingValue = "true")
public class ProfitShareKafkaProducer {

    public static final String DEFAULT_PROFITSHARE_TOPIC = "zt-profitshare";
    public static final String DEFAULT_REFUND_TOPIC = "zt-profitshare-refund";

    private final KafkaTemplate<String, String> kafkaTemplate;
    private final ObjectMapper objectMapper;
    private final KafkaIntegrationProperties kafkaProps;

    /**
     * 发送分账消息（订单支付成功后调用）
     */
    public void sendProfitShareMessage(OrderMessage message) {
        validate(message);
        String topic = kafkaProps != null && StringUtils.isNotBlank(kafkaProps.getProfitShareTopic())
                ? kafkaProps.getProfitShareTopic()
                : DEFAULT_PROFITSHARE_TOPIC;
        String key = message.getOrderId();
        String payload = toJson(message);

        log.info("[PROFIT-SHARE] producing to topic={}, key={}, orderId={}, scenicId={}, amount={}",
                topic, key, message.getOrderId(), message.getScenicId(), message.getTotalAmount());

        kafkaTemplate.send(topic, key, payload).whenComplete((metadata, ex) -> {
            if (ex != null) {
                log.error("[PROFIT-SHARE] produce failed: orderId={}, error={}", message.getOrderId(), ex.getMessage(), ex);
            } else if (metadata != null) {
                log.info("[PROFIT-SHARE] produced: orderId={}, partition={}, offset={}",
                        message.getOrderId(), metadata.getRecordMetadata().partition(), metadata.getRecordMetadata().offset());
            }
        });
    }

    /**
     * 发送退款消息（订单退款成功后调用）
     */
    public CompletableFuture<SendResult<String, String>> sendRefundMessage(RefundMessage message) {
        validateRefund(message);
        String topic = kafkaProps != null && StringUtils.isNotBlank(kafkaProps.getRefundTopic())
                ? kafkaProps.getRefundTopic()
                : DEFAULT_REFUND_TOPIC;
        String key = message.getOriginalOrderId();
        String payload = toJson(message);

        log.info("[REFUND] producing to topic={}, key={}, refundOrderId={}, originalOrderId={}, amount={}, type={}",
                topic, key, message.getRefundOrderId(), message.getOriginalOrderId(), message.getRefundAmount(), message.getRefundType());

        return kafkaTemplate.send(topic, key, payload).whenComplete((metadata, ex) -> {
            if (ex != null) {
                log.error("[REFUND] produce failed: refundOrderId={}, error={}", message.getRefundOrderId(), ex.getMessage(), ex);
            } else if (metadata != null) {
                log.info("[REFUND] produced: refundOrderId={}, partition={}, offset={}",
                        message.getRefundOrderId(), metadata.getRecordMetadata().partition(), metadata.getRecordMetadata().offset());
            }
        });
    }

    private void validate(OrderMessage msg) {
        if (msg == null) {
            throw new IllegalArgumentException("OrderMessage is null");
        }
        if (StringUtils.isBlank(msg.getOrderId())) {
            throw new IllegalArgumentException("orderId is required");
        }
        if (msg.getScenicId() == null || msg.getScenicId() <= 0) {
            throw new IllegalArgumentException("scenicId is required and must be positive");
        }
        if (msg.getTotalAmount() == null || msg.getTotalAmount() <= 0) {
            throw new IllegalArgumentException("totalAmount is required and must be positive");
        }
        if (StringUtils.isBlank(msg.getPaymentSystem())) {
            throw new IllegalArgumentException("paymentSystem is required");
        }
        if (StringUtils.isBlank(msg.getPaymentOrderId())) {
            throw new IllegalArgumentException("paymentOrderId is required");
        }
    }

    private void validateRefund(RefundMessage msg) {
        if (msg == null) {
            throw new IllegalArgumentException("RefundMessage is null");
        }
        if (StringUtils.isBlank(msg.getRefundOrderId())) {
            throw new IllegalArgumentException("refundOrderId is required");
        }
        if (StringUtils.isBlank(msg.getOriginalOrderId())) {
            throw new IllegalArgumentException("originalOrderId is required");
        }
        if (msg.getRefundAmount() == null || msg.getRefundAmount() <= 0) {
            throw new IllegalArgumentException("refundAmount is required and must be positive");
        }
        if (StringUtils.isBlank(msg.getRefundType())) {
            throw new IllegalArgumentException("refundType is required");
        }
        if (StringUtils.isBlank(msg.getPaymentSystem())) {
            throw new IllegalArgumentException("paymentSystem is required");
        }
    }

    private String toJson(Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new IllegalArgumentException("failed to serialize message", e);
        }
    }
}
