from unittest.mock import Mock

import pytest

from revedaEditor.gui.schematicEditor import schematicEditor, \
    xyceNetlist  # adjust import path as needed


class TestRecursiveNetlisting:
    @pytest.fixture
    def mock_schematic(qtbot):
        schematic = schematicEditor()
        qtbot.addWidget(schematic)
        return schematic

    @pytest.fixture
    def mock_cir_file(self):
        return Mock()

    def test_recursive_netlisting_basic_flow(self, mock_schematic, mock_cir_file):
        # Arrange
        netlister = xyceNetlist()  # replace with your actual class
        mock_scene = mock_schematic.centralW.scene

        # Setup return values
        mock_scene.findSceneSymbolSet.return_value = [Mock(), Mock()]  # two dummy symbols

        # Act
        netlister.recursiveNetlisting(mock_schematic, mock_cir_file)

        # Assert
        # Verify all required methods were called in correct order
        mock_scene.nameSceneNets.assert_called_once()
        mock_scene.findSceneSymbolSet.assert_called_once()
        mock_scene.generatePinNetMap.assert_called_once()

        # Verify processElementSymbol was called for each symbol
        assert mock_scene.findSceneSymbolSet.return_value
        assert netlister.processElementSymbol.call_count == 2

    def test_recursive_netlisting_empty_schematic(self, mock_schematic, mock_cir_file):
        # Arrange
        netlister = xyceNetlist()
        mock_scene = mock_schematic.centralW.scene
        mock_scene.findSceneSymbolSet.return_value = []

        # Act
        netlister.recursiveNetlisting(mock_schematic, mock_cir_file)

        # Assert
        mock_scene.nameSceneNets.assert_called_once()
        mock_scene.findSceneSymbolSet.assert_called_once()
        mock_scene.generatePinNetMap.assert_called_once()
        assert not netlister.processElementSymbol.called

    def test_recursive_netlisting_error_handling(self, mock_schematic, mock_cir_file):
        # Arrange
        netlister = xyceNetlist()
        mock_scene = mock_schematic.centralW.scene
        mock_scene.nameSceneNets.side_effect = Exception("Test error")

        # Act & Assert
        with pytest.raises(Exception) as exc_info:
            netlister.recursiveNetlisting(mock_schematic, mock_cir_file)
        assert str(exc_info.value) == "Test error"

    @pytest.mark.parametrize("symbol_count", [1, 3, 5])
    def test_recursive_netlisting_multiple_symbols(self, mock_schematic, mock_cir_file,
                                                   symbol_count):
        # Arrange
        netlister = xyceNetlist()
        mock_scene = mock_schematic.centralW.scene
        mock_symbols = [Mock() for _ in range(symbol_count)]
        mock_scene.findSceneSymbolSet.return_value = mock_symbols

        # Act
        netlister.recursiveNetlisting(mock_schematic, mock_cir_file)

        # Assert
        assert netlister.processElementSymbol.call_count == symbol_count
        for symbol in mock_symbols:
            netlister.processElementSymbol.assert_any_call(symbol, mock_schematic,
                                                           mock_cir_file)
