{%- import "cloudevents.jinja.include" as cloudEvents -%}
{%- import "kafka.jinja.include" as kafka -%}
{%- import "util.jinja.include" as util -%}
{{ util.CommonFileHeader() }}

{%- set messagegroups = root.messagegroups %}
{%- set package_name = project_name | lower | replace('-', '_') %}

package {{ package_name }};

import org.junit.jupiter.api.*;
import org.testcontainers.containers.KafkaContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.ByteArrayDeserializer;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

import java.net.URI;
import java.time.Duration;
import java.util.*;

import static org.junit.jupiter.api.Assertions.*;

/**
 * Integration tests for Kafka producer using Testcontainers
 */
@Testcontainers
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class {{ class_name | strip_namespace }} {
    private static final Logger logger = LogManager.getLogger({{ class_name | strip_namespace }}.class);
    
    @Container
    private static final KafkaContainer kafkaContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.5.0"))
        .withEmbeddedZookeeper();
    
    private List<URI> bootstrapServers;
    
    @BeforeAll
    public void setUp() {
        String bootstrapServer = kafkaContainer.getBootstrapServers();
        bootstrapServers = List.of(URI.create("kafka://" + bootstrapServer.replace("PLAINTEXT://", "")));
        logger.info("Kafka container started at: {}", bootstrapServers.get(0));
    }
    
    private KafkaConsumer<byte[], byte[]> createConsumer(String topic) {
        Properties props = new Properties();
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaContainer.getBootstrapServers());
        props.put(ConsumerConfig.GROUP_ID_CONFIG, "test-group-" + UUID.randomUUID());
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class.getName());
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class.getName());
        props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
        
        KafkaConsumer<byte[], byte[]> consumer = new KafkaConsumer<>(props);
        consumer.subscribe(Collections.singletonList(topic));
        return consumer;
    }
    
    {%- for messagegroupid, messagegroup in messagegroups.items() %}
    {%- set pascal_group_name = messagegroupid | pascal %}
    {%- set producer_class = (pascal_group_name | strip_namespace) + "Producer" %}
    {%- set group_package = (package_name ~ "." ~ messagegroupid) | lower | replace('-', '_') %}
    
    {%- for messageid, message in messagegroup.messages.items() %}
    {%- set messagename = messageid | pascal | strip_namespace %}
    {%- set message_body_type = util.get_data_type(data_project_name, root, message) %}
    {%- set topic = kafka.get_topic(message) or messageid %}
    
    @Test
    @DisplayName("Test {{ messagename }} message production")
    public void test{{ messagename }}Message() throws Exception {
        logger.info("Starting test{{ messagename }}Message");
        
        // Create producer
        {{ group_package }}.{{ producer_class }} producer = {{ group_package }}.{{ producer_class }}.create(bootstrapServers);
        
        try {
            // Create test data
            {%- if message_body_type == "byte[]" %}
            {{ message_body_type }} testData = new byte[0];
            {%- else %}
            {{ message_body_type }} testData = new {{ message_body_type }}();
            {%- endif %}
            {%- set schemaObj = schema_object(root, message.get('dataschemauri') or message.get('dataschema')) %}
            {%- if schemaObj %}
                {#- Get the actual schema from the versions structure -#}
                {%- if schemaObj.versions %}
                    {%- set version_key = schemaObj.defaultversionid if schemaObj.defaultversionid else (schemaObj.versions.keys() | list | last) %}
                    {%- set avroSchema = schemaObj.versions[version_key].schema %}
                {%- elif schemaObj.schema %}
                    {%- set avroSchema = schemaObj.schema %}
                {%- else %}
                    {%- set avroSchema = schemaObj %}
                {%- endif %}
                {#- Now process the Avro schema fields -#}
                {%- if avroSchema and avroSchema.type == "record" and avroSchema.fields %}
                    {%- for field in avroSchema.fields %}
                        {%- set fieldtype = field.type if field.type is string else field.type.type if field.type is mapping and field.type.type is defined else "unknown" %}
                        {%- if fieldtype == "string" %}
            testData.set{{ field.name | pascal }}("test-{{ field.name }}");
                        {%- elif fieldtype == "int" or fieldtype == "integer" %}
            testData.set{{ field.name | pascal }}(42);
                        {%- elif fieldtype == "long" %}
            testData.set{{ field.name | pascal }}(42L);
                        {%- elif fieldtype == "boolean" %}
            testData.set{{ field.name | pascal }}(true);
                        {%- elif fieldtype == "double" %}
            testData.set{{ field.name | pascal }}(42.0);
                        {%- elif fieldtype == "float" %}
            testData.set{{ field.name | pascal }}(42.0f);
                        {%- elif fieldtype == "enum" %}
                            {%- set enum_namespace = field.type.namespace if field.type.namespace else avroSchema.namespace %}
                            {%- set normalized_namespace = (data_project_name | lower | replace('-', '_')) + '.' + (enum_namespace | lower | replace('.', '.') if enum_namespace else '') %}
            testData.set{{ field.name | pascal }}({{ normalized_namespace }}.{{ field.type.name }}.{{ field.type.symbols[0] | upper }});
                        {%- endif %}
                    {%- endfor %}
                {%- endif %}
            {%- endif %}
            
            // Send 5 messages to test proper message handling
            for (int i = 0; i < 5; i++) {
                producer.send{{ messagename }}(testData).get();
            }
            producer.flush();
            
            logger.info("5 messages sent, waiting for consumption");
            
            // Consume and verify all 5 messages
            KafkaConsumer<byte[], byte[]> consumer = createConsumer("{{ topic }}");
            try {
                int messagesReceived = 0;
                int attempts = 0;
                
                while (messagesReceived < 5 && attempts < 15) {
                    ConsumerRecords<byte[], byte[]> records = consumer.poll(Duration.ofSeconds(2));
                    if (!records.isEmpty()) {
                        for (ConsumerRecord<byte[], byte[]> record : records) {
                            logger.info("Received message {} from topic {} partition {} offset {}", 
                                messagesReceived, record.topic(), record.partition(), record.offset());
                            
                            assertNotNull(record.value(), "Message value should not be null");
                            assertTrue(record.value().length > 0, "Message should have content");
                            messagesReceived++;
                        }
                    }
                    attempts++;
                }
                
                assertEquals(5, messagesReceived, "Should receive all 5 {{ messagename }} messages");
                logger.info("All 5 {{ messagename }} messages test completed successfully");
                
            } finally {
                consumer.close();
            }
        } finally {
            producer.close();
        }
    }
    
    {% endfor %}
    {% endfor %}
}
