from __future__ import annotations

import pytest

from codeflash_python.analysis._code_utils import validate_python_code
from codeflash_python.context.models import CodeString, CodeStringsMarkdown


def test_python_string():
    """CodeString stores a plain Python snippet."""
    code = CodeString(code="print('Hello, World!')")
    assert "print('Hello, World!')" == code.code


def test_valid_python_code():
    """validate_python_code accepts valid Python without errors."""
    valid_code = "x = 1\ny = x + 2\nprint(y)"
    result = validate_python_code(valid_code)
    assert valid_code == result


def test_invalid_python_code_syntax():
    """validate_python_code raises ValueError for syntax errors."""
    invalid_code = "x = 1\nprint(x"
    with pytest.raises(ValueError, match="Invalid Python code:"):
        validate_python_code(invalid_code)


def test_invalid_python_code_name_error():
    """compile does not catch runtime NameErrors -- only syntax errors."""
    invalid_runtime_code = "print(undefined_variable)"
    result = validate_python_code(invalid_runtime_code)
    assert invalid_runtime_code == result


def test_empty_code_string():
    """Empty code is syntactically valid."""
    empty_code = ""
    result = validate_python_code(empty_code)
    assert empty_code == result


def test_whitespace_only():
    """Whitespace-only code is syntactically valid."""
    whitespace_code = "    "
    result = validate_python_code(whitespace_code)
    assert whitespace_code == result


def test_parse_markdown_rejects_invalid_syntax():
    """parse_markdown_code still parses invalid syntax into CodeStrings."""
    code = """```python:file.py
print name
```"""
    parsed = CodeStringsMarkdown.parse_markdown_code(code)
    assert 1 == len(parsed.code_strings)
    assert "print name" == parsed.code_strings[0].code
    with pytest.raises(ValueError, match="Invalid Python code:"):
        validate_python_code(parsed.code_strings[0].code)


def test_parse_markdown_accepts_valid_code():
    """parse_markdown_code extracts valid code and its file path."""
    code = """```python:file.py
print('Hello, World!')
```"""
    parsed = CodeStringsMarkdown.parse_markdown_code(code)
    assert 1 == len(parsed.code_strings)
    assert "print('Hello, World!')" == parsed.code_strings[0].code
    assert "file.py" == parsed.code_strings[0].file_path.as_posix()
