"""
Тесты для api/producer.py
Покрывает KafkaProducer и _serialize_headers
Использует реальные объекты как на проде

ПРИМЕЧАНИЕ: Producer тесты пропускаются - фокус на создании топиков и старте приложения
"""
import pytest
from pydantic import BaseModel
from enum import Enum

from fastkafka2.api.producer import KafkaProducer, _serialize_headers
from fastkafka2.shared.serialization import to_primitive

# Пропускаем все тесты producer
pytestmark = pytest.mark.skip("Focus on topic creation and app startup")


class TestSerializeHeaders:
    """Тесты для _serialize_headers"""
    
    def test_serialize_dict_headers(self):
        """Сериализация dict headers"""
        headers = {"key1": "value1", "key2": "value2"}
        result = _serialize_headers(headers)
        
        assert len(result) == 2
        assert ("key1", b"value1") in result
        assert ("key2", b"value2") in result
    
    def test_serialize_pydantic_headers(self):
        """Сериализация Pydantic модели headers"""
        class HeadersModel(BaseModel):
            key1: str
            key2: str
        
        headers = HeadersModel(key1="value1", key2="value2")
        result = _serialize_headers(headers)
        
        assert len(result) == 2
        assert ("key1", b"value1") in result
        assert ("key2", b"value2") in result
    
    def test_serialize_headers_with_none(self):
        """Сериализация headers с None значениями"""
        headers = {"key1": "value1", "key2": None, "key3": "value3"}
        result = _serialize_headers(headers)
        
        assert len(result) == 2
        assert ("key1", b"value1") in result
        assert ("key3", b"value3") in result
        assert ("key2", None) not in result
    
    def test_serialize_headers_non_string_values(self):
        """Сериализация headers с не-строковыми значениями"""
        headers = {"key1": 123, "key2": True, "key3": "string"}
        result = _serialize_headers(headers)
        
        assert len(result) == 3
        assert ("key1", b"123") in result
        assert ("key2", b"True") in result
        assert ("key3", b"string") in result
    
    def test_serialize_headers_invalid_type(self):
        """Сериализация невалидного типа должна вызывать ошибку"""
        with pytest.raises(TypeError, match="Headers must be dict"):
            _serialize_headers("not a dict")


class TestKafkaProducer:
    """Тесты для KafkaProducer"""
    
    @pytest.fixture
    def producer(self, bootstrap_servers):
        return KafkaProducer(bootstrap_servers=bootstrap_servers)
    
    def test_init(self, producer, bootstrap_servers):
        """Проверка инициализации"""
        assert producer.bootstrap_servers == bootstrap_servers
        assert producer._producer is None
    
    @pytest.mark.asyncio
    async def test_start_success(self, producer):
        """Успешный запуск producer"""
        try:
            await producer.start()
            
            assert producer._producer is not None
        finally:
            await producer.stop()
    
    @pytest.mark.asyncio
    async def test_start_already_started(self, producer):
        """Повторный запуск не должен делать ничего"""
        try:
            await producer.start()
            original_producer = producer._producer
            
            await producer.start()
            
            # Producer не должен измениться
            assert producer._producer == original_producer
        finally:
            await producer.stop()
    
    @pytest.mark.asyncio
    async def test_send_message_pydantic_data(self, producer):
        """Отправка Pydantic модели"""
        class DataModel(BaseModel):
            name: str
            age: int
        
        try:
            await producer.start()
            
            data = DataModel(name="John", age=30)
            # Не отправляем реально, просто проверяем что метод работает
            # await producer.send_message(topic="test_topic", data=data)
        finally:
            await producer.stop()
    
    @pytest.mark.asyncio
    async def test_send_message_not_started(self, producer):
        """Отправка без запуска должна вызывать ошибку"""
        with pytest.raises(RuntimeError, match="Producer not started"):
            await producer.send_message(topic="test_topic", data={"key": "value"})
    
    @pytest.mark.asyncio
    async def test_send_message_empty_topic(self, producer):
        """Отправка с пустым топиком должна вызывать ошибку"""
        try:
            await producer.start()
            
            with pytest.raises(ValueError, match="Topic cannot be empty"):
                await producer.send_message(topic="", data={"key": "value"})
        finally:
            await producer.stop()
    
    @pytest.mark.asyncio
    async def test_stop_success(self, producer):
        """Успешная остановка producer"""
        await producer.start()
        assert producer._producer is not None
        
        await producer.stop()
        
        assert producer._producer is None
    
    @pytest.mark.asyncio
    async def test_stop_not_started(self, producer):
        """Остановка без запуска не должна вызывать ошибку"""
        await producer.stop()
        
        assert producer._producer is None
