import asyncio
import logging
from unittest.mock import AsyncMock, MagicMock, patch

import pytest

from cintes import gestiona_cinta  # Ajusta el nom del mòdul segons la teva estructura

@pytest.mark.asyncio
async def test_gestiona_cinta_respon_ok_per_linia():
    """Test que verifica que gestiona_cinta respon 'OK' per cada línia llegida."""
    # Configuració del mock de StreamReader
    reader = AsyncMock()
    reader.readline = AsyncMock(side_effect=[
        "primera línia\n".encode(),
        "segona línia\n".encode(),
        b"",  # Senyal d'EOF
    ])

    # Configuració del mock de StreamWriter
    writer = MagicMock()
    writer.write = MagicMock()
    writer.drain = AsyncMock()
    writer.close = MagicMock()
    writer.wait_closed = AsyncMock()

    # Execució de la corutina
    await gestiona_cinta(reader, writer)

    # Verificacions
    assert writer.write.call_count == 2  # Una vegada per línia
    calls = writer.write.call_args_list
    assert calls[0][0][0] == b"OK\n"  # Primera resposta
    assert calls[1][0][0] == b"OK\n"  # Segona resposta

    # Verificar que s'ha cridat drain després de cada write
    assert writer.drain.call_count == 2

    # Verificar tancament del writer
    writer.close.assert_called_once()
    writer.drain.assert_called()  # Comprovació addicional que drain es crida abans de close

@pytest.mark.asyncio
async def test_gestiona_cinta_tanca_writer_en_excepcio():
    """Test que verifica que gestiona_cinta tanca el writer en cas d'excepció."""
    # Configuració del mock de StreamReader per llançar una excepció
    reader = AsyncMock()
    reader.readline = AsyncMock(side_effect=Exception("Error de lectura"))

    # Configuració del mock de StreamWriter
    writer = MagicMock()
    writer.write = MagicMock()
    writer.drain = AsyncMock()
    writer.close = MagicMock()
    writer.wait_closed = AsyncMock()

    # Mock del registre d'excepcions
    with patch('logging.exception') as mock_log:
        await gestiona_cinta(reader, writer)

    # Verificacions
    writer.close.assert_called_once()
    mock_log.assert_called_once_with("Excepció en gestiona_cinta", exc_info=True)

