"""Tests for drc module: design rule checks on schematic objects."""



from mcltspice.drc import (
    DRCResult,
    DRCViolation,
    Severity,
    _check_duplicate_names,
    _check_ground,
    _check_simulation_directive,
)
from mcltspice.schematic import Schematic, write_schematic


def _run_single_check(check_fn, schematic: Schematic) -> DRCResult:
    """Run a single DRC check function and return results."""
    result = DRCResult()
    check_fn(schematic, result)
    return result


class TestGroundCheck:
    def test_missing_ground_detected(self, schematic_no_ground):
        result = _run_single_check(_check_ground, schematic_no_ground)
        assert not result.passed
        assert any(v.rule == "NO_GROUND" for v in result.violations)

    def test_ground_present(self, valid_schematic):
        result = _run_single_check(_check_ground, valid_schematic)
        assert result.passed
        assert len(result.violations) == 0


class TestSimDirectiveCheck:
    def test_missing_sim_directive_detected(self, schematic_no_sim):
        result = _run_single_check(_check_simulation_directive, schematic_no_sim)
        assert not result.passed
        assert any(v.rule == "NO_SIM_DIRECTIVE" for v in result.violations)

    def test_sim_directive_present(self, valid_schematic):
        result = _run_single_check(_check_simulation_directive, valid_schematic)
        assert result.passed


class TestDuplicateNameCheck:
    def test_duplicate_names_detected(self, schematic_duplicate_names):
        result = _run_single_check(_check_duplicate_names, schematic_duplicate_names)
        assert not result.passed
        assert any(v.rule == "DUPLICATE_NAME" for v in result.violations)

    def test_unique_names_pass(self, valid_schematic):
        result = _run_single_check(_check_duplicate_names, valid_schematic)
        assert result.passed


class TestDRCResult:
    def test_passed_when_no_errors(self):
        result = DRCResult()
        result.violations.append(
            DRCViolation(rule="TEST", severity=Severity.WARNING, message="warning only")
        )
        assert result.passed  # Warnings don't cause failure

    def test_failed_when_errors(self):
        result = DRCResult()
        result.violations.append(
            DRCViolation(rule="TEST", severity=Severity.ERROR, message="error")
        )
        assert not result.passed

    def test_summary_no_violations(self):
        result = DRCResult(checks_run=5)
        assert "passed" in result.summary().lower()

    def test_summary_with_errors(self):
        result = DRCResult(checks_run=5)
        result.violations.append(
            DRCViolation(rule="TEST", severity=Severity.ERROR, message="error")
        )
        assert "FAILED" in result.summary()

    def test_to_dict(self):
        result = DRCResult(checks_run=3)
        result.violations.append(
            DRCViolation(rule="NO_GROUND", severity=Severity.ERROR, message="No ground")
        )
        d = result.to_dict()
        assert d["passed"] is False
        assert d["error_count"] == 1
        assert len(d["violations"]) == 1

    def test_errors_and_warnings_properties(self):
        result = DRCResult()
        result.violations.append(
            DRCViolation(rule="E1", severity=Severity.ERROR, message="err")
        )
        result.violations.append(
            DRCViolation(rule="W1", severity=Severity.WARNING, message="warn")
        )
        result.violations.append(
            DRCViolation(rule="I1", severity=Severity.INFO, message="info")
        )
        assert len(result.errors) == 1
        assert len(result.warnings) == 1


class TestFullDRC:
    """Integration test: write a schematic to disk and run the full DRC pipeline."""

    def test_valid_schematic_passes(self, valid_schematic, tmp_path):
        """A valid schematic should pass DRC with no errors."""
        from mcltspice.drc import run_drc

        path = tmp_path / "valid.asc"
        write_schematic(valid_schematic, path)
        result = run_drc(path)
        # May have warnings (floating nodes etc) but no errors
        assert len(result.errors) == 0

    def test_no_ground_fails(self, schematic_no_ground, tmp_path):
        from mcltspice.drc import run_drc

        path = tmp_path / "no_ground.asc"
        write_schematic(schematic_no_ground, path)
        result = run_drc(path)
        assert any(v.rule == "NO_GROUND" for v in result.errors)
