"""
Tests for the code_checker_pytest report parsing functionality.
"""

from mcp_tools_py.code_checker_pytest import PytestReport, parse_pytest_report

from .test_code_checker_pytest_common import SAMPLE_JSON


def test_parse_report() -> None:
    """Test that pytest JSON report is correctly parsed into a PytestReport object."""
    report = parse_pytest_report(SAMPLE_JSON)

    assert isinstance(report, PytestReport)
    assert report.duration == 0.1235666275024414
    assert report.exitcode == 1
    assert report.summary.total == 10
    assert report.summary.passed == 2
    assert report.summary.failed == 3

    assert report.collectors is not None
    assert len(report.collectors) == 3
    assert report.collectors[0].nodeid == ""
    assert report.collectors[1].nodeid == "test_foo.py"
    assert report.collectors[2].nodeid == "test_bar.py"

    assert report.tests is not None
    assert len(report.tests) == 2
    assert report.tests[0].nodeid == "test_foo.py::test_fail"
    assert report.tests[1].nodeid == "test_bar.py::test_error"

    assert report.tests[0].call is not None
    assert report.tests[0].call.duration > 0
    assert report.tests[0].call.outcome == "failed"

    assert report.tests[0].call.crash is not None
    assert (
        report.tests[0].call.crash.message
        == "TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'"
    )

    assert report.tests[0].call.traceback is not None
    assert len(report.tests[0].call.traceback) == 4
    assert report.tests[0].call.traceback[0].message == ""

    assert report.warnings is not None
    assert len(report.warnings) == 1
    assert report.warnings[0].nodeid == "test_foo.py::TestFoo"


def test_parse_report_no_collectors() -> None:
    """Test parsing a report without collectors."""
    json_no_collectors = """
    {
        "created": 1518371686.7981803,
        "duration": 0.1235666275024414,
        "exitcode": 1,
        "root": "/path/to/tests",
        "environment": {
        "Python": "3.6.4",
        "Platform": "Linux-4.56.78-9-ARCH-x86_64-with-arch",
        "Packages": {
            "pytest": "3.4.0",
            "py": "1.5.2",
            "pluggy": "0.6.0"
        },
        "Plugins": {
            "json-report": "0.4.1",
            "xdist": "1.22.0",
            "metadata": "1.5.1",
            "forked": "0.2",
            "cov": "2.5.1"
        },
        "foo": "bar"
    },
    "summary": {
        "collected": 10,
        "passed": 2,
        "failed": 3,
        "xfailed": 1,
        "xpassed": 1,
        "error": 2,
        "skipped": 1,
        "total": 10
    },
        "tests": [],
        "warnings": []
    }
    """
    report = parse_pytest_report(json_no_collectors)
    assert isinstance(report, PytestReport)
    assert report.collectors is None


def test_parse_report_no_tests() -> None:
    """Test parsing a report without tests."""
    json_no_tests = """
    {
        "created": 1518371686.7981803,
        "duration": 0.1235666275024414,
        "exitcode": 1,
        "root": "/path/to/tests",
        "environment": {
        "Python": "3.6.4",
        "Platform": "Linux-4.56.78-9-ARCH-x86_64-with-arch",
        "Packages": {
            "pytest": "3.4.0",
            "py": "1.5.2",
            "pluggy": "0.6.0"
        },
        "Plugins": {
            "json-report": "0.4.1",
            "xdist": "1.22.0",
            "metadata": "1.5.1",
            "forked": "0.2",
            "cov": "2.5.1"
        },
        "foo": "bar"
    },
    "summary": {
        "collected": 10,
        "passed": 2,
        "failed": 3,
        "xfailed": 1,
        "xpassed": 1,
        "error": 2,
        "skipped": 1,
        "total": 10
    },
       "collectors": [],
        "warnings": []
    }
    """
    report = parse_pytest_report(json_no_tests)
    assert isinstance(report, PytestReport)
    assert report.tests is None


def test_parse_report_with_log() -> None:
    """Test parsing a report with log entries."""
    json_with_log = """
    {
        "created": 1518371686.7981803,
        "duration": 0.1235666275024414,
        "exitcode": 1,
        "root": "/path/to/tests",
        "environment": {
        "Python": "3.6.4",
        "Platform": "Linux-4.56.78-9-ARCH-x86_64-with-arch",
        "Packages": {
            "pytest": "3.4.0",
            "py": "1.5.2",
            "pluggy": "0.6.0"
        },
        "Plugins": {
            "json-report": "0.4.1",
            "xdist": "1.22.0",
            "metadata": "1.5.1",
            "forked": "0.2",
            "cov": "2.5.1"
        },
        "foo": "bar"
    },
    "summary": {
        "collected": 10,
        "passed": 2,
        "failed": 3,
        "xfailed": 1,
        "xpassed": 1,
        "error": 2,
        "skipped": 1,
        "total": 10
    },
        "collectors": [],
        "tests": [{
            "nodeid": "test_foo.py::test_fail",
            "lineno": 50,
            "keywords": [
            "test_fail",
            "test_foo.py",
            "test_foo0"
            ],
            "outcome": "failed",
            "setup": {
            "duration": 0.00018835067749023438,
            "outcome": "passed"
            },
            "call": {
            "duration": 0.00018835067749023438,
            "outcome": "failed",
            "crash": {
                "path": "/path/to/tests/test_foo.py",
                "lineno": 54,
                "message": "TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'"
            },
            "traceback": [
                {
                "path": "test_foo.py",
                "lineno": 65,
                "message": ""
                },
                {
                "path": "test_foo.py",
                "lineno": 63,
                "message": "in foo"
                },
                {
                "path": "test_foo.py",
                "lineno": 63,
                "message": "in <listcomp>"
                },
                {
                "path": "test_foo.py",
                "lineno": 54,
                "message": "TypeError"
                }
            ],
            "stdout": "foo\\nbar\\n",
            "stderr": "baz\\n",
             "log": [{
                "name": "root",
                "msg": "This is a warning.",
                "args": null,
                "levelname": "WARNING",
                "levelno": 30,
                "pathname": "/path/to/tests/test_foo.py",
                "filename": "test_foo.py",
                "module": "test_foo",
                "exc_info": null,
                "exc_text": null,
                "stack_info": null,
                "lineno": 8,
                "funcName": "foo",
                "created": 1519772464.291738,
                "msecs": 291.73803329467773,
                "relativeCreated": 332.90839195251465,
                "thread": 140671803118912,
                "threadName": "MainThread",
                "processName": "MainProcess",
                "process": 31481
            }]
            },
            "teardown": {
            "duration": 0.00018835067749023438,
            "outcome": "passed"
            }
        }],
        "warnings": []
    }
    """
    report = parse_pytest_report(json_with_log)
    assert isinstance(report, PytestReport)
    assert report.tests is not None
    assert len(report.tests) == 1
    assert report.tests[0].call is not None
    assert report.tests[0].call.log is not None
    assert report.tests[0].call.log.logs is not None
    assert report.tests[0].call.log.logs[0].msg == "This is a warning."


def test_parse_report_with_extra_log_fields() -> None:
    """Test parsing log records with extra fields from logging extra parameter."""
    json_with_extra_fields = """
    {
        "created": 1518371686.7981803,
        "duration": 0.1235666275024414,
        "exitcode": 0,
        "root": "/path/to/tests",
        "environment": {
            "Python": "3.6.4",
            "Platform": "Linux-4.56.78-9-ARCH-x86_64-with-arch",
            "Packages": {
                "pytest": "3.4.0",
                "py": "1.5.2",
                "pluggy": "0.6.0"
            },
            "Plugins": {
                "json-report": "0.4.1"
            },
            "foo": "bar"
        },
        "summary": {
            "collected": 1,
            "passed": 1,
            "failed": 0,
            "total": 1
        },
        "collectors": [],
        "tests": [{
            "nodeid": "test_example.py::test_with_extra_logging",
            "lineno": 10,
            "keywords": ["test_with_extra_logging", "test_example.py"],
            "outcome": "passed",
            "setup": {
                "duration": 0.001,
                "outcome": "passed"
            },
            "call": {
                "duration": 0.002,
                "outcome": "passed",
                "log": [{
                    "name": "my_logger",
                    "msg": "Looking for data file",
                    "args": null,
                    "levelname": "DEBUG",
                    "levelno": 10,
                    "pathname": "/path/to/file.py",
                    "filename": "file.py",
                    "module": "file",
                    "exc_info": null,
                    "exc_text": null,
                    "stack_info": null,
                    "lineno": 42,
                    "funcName": "find_file",
                    "created": 1519772464.291738,
                    "msecs": 291.73803329467773,
                    "relativeCreated": 332.90839195251465,
                    "thread": 140671803118912,
                    "threadName": "MainThread",
                    "processName": "MainProcess",
                    "process": 31481,
                    "package_name": "my_package",
                    "relative_path": "file.txt"
                }]
            },
            "teardown": {
                "duration": 0.001,
                "outcome": "passed"
            }
        }],
        "warnings": []
    }
    """
    report = parse_pytest_report(json_with_extra_fields)

    assert isinstance(report, PytestReport)
    assert report.tests is not None
    assert len(report.tests) == 1
    assert report.tests[0].call is not None
    assert report.tests[0].call.log is not None
    assert report.tests[0].call.log.logs is not None

    log_record = report.tests[0].call.log.logs[0]

    # Verify standard fields are parsed correctly
    assert log_record.name == "my_logger"
    assert log_record.msg == "Looking for data file"
    assert log_record.levelname == "DEBUG"
    assert log_record.levelno == 10
    assert log_record.pathname == "/path/to/file.py"
    assert log_record.filename == "file.py"
    assert log_record.lineno == 42
    assert log_record.funcName == "find_file"

    # Verify extra fields are captured in the extra dict
    assert log_record.extra is not None
    assert log_record.extra == {
        "package_name": "my_package",
        "relative_path": "file.txt",
    }

    # Verify standard fields are NOT in the extra dict
    assert "name" not in log_record.extra
    assert "msg" not in log_record.extra
    assert "levelname" not in log_record.extra
