package com.ycwl.basic.integration.message.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.message.dto.ZtMessage;
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.stereotype.Service;

import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
@ConditionalOnProperty(name = "kafka.enabled", havingValue = "true")
public class ZtMessageProducerService {

    public static final String DEFAULT_TOPIC = "zt-message";

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

    public void send(ZtMessage msg) {
        validate(msg);
        
        // Generate messageId if not present
        if (StringUtils.isBlank(msg.getMessageId())) {
            msg.setMessageId(java.util.UUID.randomUUID().toString());
        }
        
        String topic = kafkaProps != null && StringUtils.isNotBlank(kafkaProps.getZtMessageTopic())
                ? kafkaProps.getZtMessageTopic()
                : DEFAULT_TOPIC;
        String key = msg.getChannelId();
        String payload = toJson(msg);

        log.info("[ZT-MESSAGE] producing to topic={}, key={}, messageId={}, title={}", topic, key, msg.getMessageId(), msg.getTitle());
        kafkaTemplate.send(topic, key, payload).whenComplete((metadata, ex) -> {
            if (ex != null) {
                log.error("[ZT-MESSAGE] produce failed: messageId={}, error={}", msg.getMessageId(), ex.getMessage(), ex);
            } else if (metadata != null) {
                log.info("[ZT-MESSAGE] produced: messageId={}, partition={}, offset={}", msg.getMessageId(), metadata.getRecordMetadata().partition(), metadata.getRecordMetadata().offset());
            }
        });
    }

    private void validate(ZtMessage msg) {
        if (msg == null) throw new IllegalArgumentException("message is null");
        if (StringUtils.isBlank(msg.getChannelId())) throw new IllegalArgumentException("channelId is required");
        if (StringUtils.isBlank(msg.getTitle())) throw new IllegalArgumentException("title is required");
        if (StringUtils.isBlank(msg.getContent())) throw new IllegalArgumentException("content is required");
        if (StringUtils.isBlank(msg.getTarget())) throw new IllegalArgumentException("target is required");
        if (msg.getExtra() != null && !(msg.getExtra() instanceof Map)) {
            throw new IllegalArgumentException("extra must be a Map");
        }
    }

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