package com.tsi.comm.server.kafka;

import org.apache.kafka.clients.producer.ProducerConfig;
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
import org.springframework.kafka.core.KafkaTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class KafkaProducerFactory {

    public static <K,V> KafkaTemplate<K, V> createByteArrayTemplate(String bootstrapServers, List<Map<String, String>> props) {
        Map<String, Object> configs = new HashMap<>();
        // 브로커 3대 모두 등록된 bootstrapServers 사용
        configs.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
        // 최신 데이터만 의미 있으므로 idempotence 불필요
        configs.put("enable.idempotence", false);
        // 지연 최소화: 브로커 응답 기다리지 않음 (최신 데이터만 의미 있음)
        configs.put(ProducerConfig.ACKS_CONFIG, "0");
        // 재시도 불필요
        configs.put(ProducerConfig.RETRIES_CONFIG, 0);
        // 즉시 전송 (배치 효과 없음)
        configs.put(ProducerConfig.LINGER_MS_CONFIG, 0);
        // 메시지가 작으므로 batch.size는 기본값(16KB) 또는 32KB 정도면 충분
//        configs.put(ProducerConfig.BATCH_SIZE_CONFIG, 32768);
        // 압축은 작은 메시지에서는 효과 없음 → 비활성화, default none
        configs.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "none");
        // 타임아웃 설정
        configs.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 3000);
        configs.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, 4000);
        configs.put(ProducerConfig.TRANSACTION_TIMEOUT_CONFIG, 5000);
        //configs.put("queue.buffering.max.messages", 10000000);
        //configs.put("queue.buffering.max.kbytes", 2147483647);
        //configs.put("queue.buffering.max.ms", 0);
        //configs.put("api.version.request", false);
        configs.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, org.apache.kafka.common.serialization.StringSerializer.class);
        configs.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, org.apache.kafka.common.serialization.ByteArraySerializer.class);

        for (Map<String, String> prop : props) {
            for (Map.Entry<String, String> elem : prop.entrySet()) {
                String key = elem.getKey();
                String val = elem.getValue();
                if (val != null) {
                    if (val.equals("true") || val.equals("false")) {
                        configs.put(key, val.equals("true"));
                    } else {
                        configs.put(key, val);
                    }
                }
            }
        }

        DefaultKafkaProducerFactory<K, V> defaultKafkaProducerFactory = new DefaultKafkaProducerFactory<>(configs);
        return new KafkaTemplate<>(defaultKafkaProducerFactory);
    }

    public static <K,V> KafkaTemplate<K, V> createProducerTemplate(Map<String, Object> props) {
        DefaultKafkaProducerFactory<K, V> defaultKafkaProducerFactory = new DefaultKafkaProducerFactory<>(props);
        return new KafkaTemplate<>(defaultKafkaProducerFactory);
    }

    public static Properties getProperties(String bootstrapServers, List<Map<String, String>> props) {
        Properties properties  = new Properties();
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
        properties.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, false);    // 최신 데이터만 의미 있으므로 불필요
        properties.put(ProducerConfig.ACKS_CONFIG, "0");    // 최대 속도, 안정성 필요시 "1"
        properties.put(ProducerConfig.RETRIES_CONFIG, 0);   // 재시도 불필요
        properties.put(ProducerConfig.LINGER_MS_CONFIG, 0); // 즉시 전송, 1ms 도 괜찮음
//        properties.put(ProducerConfig.BATCH_SIZE_CONFIG, 65536); // 64KB, 네트워크 효율 개선, 기본값 16KB
//        properties.put(ProducerConfig.BATCH_SIZE_CONFIG, 32768);
//        properties.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "lz4"); // 빠른 압축, 패킷크기가 작기때문에 압축하지 않음
        properties.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "none"); // defalut none
        properties.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 3000);
        properties.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, 4000);
        properties.put(ProducerConfig.TRANSACTION_TIMEOUT_CONFIG, 5000);
        //properties.put("queue.buffering.max.messages", 10000000);
        //properties.put("queue.buffering.max.kbytes", 2147483647);
        //properties.put("queue.buffering.max.ms", 0);
        //properties.put("api.version.request", false);
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, org.apache.kafka.common.serialization.StringSerializer.class);
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, org.apache.kafka.common.serialization.ByteArraySerializer.class);
        for (Map<String, String> prop : props) {
            for (Map.Entry<String, String> elem : prop.entrySet()) {
                String key = elem.getKey();
                String val = elem.getValue();
                if (val != null) {
                    if (val.equals("true") || val.equals("false")) {
                        properties.put(key, val.equals("true"));
                    } else {
                        properties.put(key, val);
                    }
                }
            }
        }
        return properties ;
    }
}
