"""
Tests for the PyFile class (Milestone 5).
"""

from pathlib import Path

from nblite.core.pyfile import PyFile, PyFileCell


class TestPyFileCreation:
    def test_load_regular_file(self, tmp_path: Path) -> None:
        """Test loading non-autogenerated Python file."""
        content = "def foo(): pass"
        py_path = tmp_path / "manual.py"
        py_path.write_text(content)

        pyfile = PyFile.from_file(py_path)

        assert pyfile.path == py_path
        assert pyfile.content == content
        assert pyfile.is_autogenerated is False
        assert pyfile.source_notebook is None

    def test_load_autogenerated_file(self, tmp_path: Path) -> None:
        """Test loading autogenerated Python file."""
        content = """# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/utils.ipynb

# %% ../nbs/utils.ipynb 0
def foo():
    pass
"""
        py_path = tmp_path / "utils.py"
        py_path.write_text(content)

        pyfile = PyFile.from_file(py_path)

        assert pyfile.is_autogenerated is True
        assert pyfile.source_notebook == Path("../nbs/utils.ipynb")

    def test_load_with_package_root(self, tmp_path: Path) -> None:
        """Test loading file with package root."""
        py_path = tmp_path / "utils.py"
        py_path.write_text("def foo(): pass")

        pyfile = PyFile.from_file(py_path, package_root=tmp_path)

        assert pyfile.package_root == tmp_path


class TestPyFileAutogenerated:
    def test_autogen_header_variations(self, tmp_path: Path) -> None:
        """Test various autogenerated header formats."""
        # Standard format
        content = "# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/utils.ipynb\n"
        py_path = tmp_path / "utils.py"
        py_path.write_text(content)
        pyfile = PyFile.from_file(py_path)
        assert pyfile.is_autogenerated is True
        assert pyfile.source_notebook == Path("nbs/utils.ipynb")

    def test_not_autogenerated_similar_comment(self, tmp_path: Path) -> None:
        """Test file with similar but different comment."""
        content = "# This is not an autogenerated file\n"
        py_path = tmp_path / "manual.py"
        py_path.write_text(content)
        pyfile = PyFile.from_file(py_path)
        assert pyfile.is_autogenerated is False


class TestPyFileCells:
    def test_parse_percent_cells(self, tmp_path: Path) -> None:
        """Test parsing cells from percent-style file."""
        content = """# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/utils.ipynb

# %% ../nbs/utils.ipynb 0
def foo():
    pass

# %% ../nbs/utils.ipynb 2
def bar():
    pass
"""
        py_path = tmp_path / "utils.py"
        py_path.write_text(content)

        pyfile = PyFile.from_file(py_path)

        assert len(pyfile.cells) == 2
        assert pyfile.cells[0].source_cell_index == 0
        assert pyfile.cells[1].source_cell_index == 2

    def test_cell_source_content(self, tmp_path: Path) -> None:
        """Test cell source content extraction."""
        content = """# %% test.ipynb 0
def foo():
    return 42

# %% test.ipynb 1
class Bar:
    pass
"""
        py_path = tmp_path / "test.py"
        py_path.write_text(content)

        pyfile = PyFile.from_file(py_path)

        assert len(pyfile.cells) == 2
        assert "def foo():" in pyfile.cells[0].source
        assert "return 42" in pyfile.cells[0].source
        assert "class Bar:" in pyfile.cells[1].source

    def test_no_cells_in_regular_file(self, tmp_path: Path) -> None:
        """Test that regular files have no cells."""
        content = "def foo(): pass"
        py_path = tmp_path / "manual.py"
        py_path.write_text(content)

        pyfile = PyFile.from_file(py_path)

        assert len(pyfile.cells) == 0

    def test_cell_source_path(self, tmp_path: Path) -> None:
        """Test cell source path extraction."""
        content = """# %% ../nbs/api/utils.ipynb 0
def foo():
    pass
"""
        py_path = tmp_path / "utils.py"
        py_path.write_text(content)

        pyfile = PyFile.from_file(py_path)

        assert pyfile.cells[0].source_path == "../nbs/api/utils.ipynb"


class TestPyFileModulePath:
    def test_module_path(self, tmp_path: Path) -> None:
        """Test module path calculation."""
        pkg_dir = tmp_path / "mypackage" / "utils"
        pkg_dir.mkdir(parents=True)
        py_path = pkg_dir / "helpers.py"
        py_path.write_text("def foo(): pass")

        pyfile = PyFile.from_file(py_path, package_root=tmp_path / "mypackage")

        assert pyfile.module_path == "mypackage.utils.helpers"

    def test_module_path_top_level(self, tmp_path: Path) -> None:
        """Test module path at package top level."""
        pkg_dir = tmp_path / "mypackage"
        pkg_dir.mkdir()
        py_path = pkg_dir / "core.py"
        py_path.write_text("def foo(): pass")

        pyfile = PyFile.from_file(py_path, package_root=pkg_dir)

        assert pyfile.module_path == "mypackage.core"

    def test_module_path_init(self, tmp_path: Path) -> None:
        """Test module path for __init__.py."""
        pkg_dir = tmp_path / "mypackage" / "utils"
        pkg_dir.mkdir(parents=True)
        py_path = pkg_dir / "__init__.py"
        py_path.write_text("")

        pyfile = PyFile.from_file(py_path, package_root=tmp_path / "mypackage")

        assert pyfile.module_path == "mypackage.utils"

    def test_module_path_no_package_root(self, tmp_path: Path) -> None:
        """Test module path without package root."""
        py_path = tmp_path / "utils.py"
        py_path.write_text("def foo(): pass")

        pyfile = PyFile.from_file(py_path)

        assert pyfile.module_path is None


class TestPyFileRepr:
    def test_repr_regular_file(self, tmp_path: Path) -> None:
        """Test repr for regular file."""
        py_path = tmp_path / "utils.py"
        py_path.write_text("def foo(): pass")

        pyfile = PyFile.from_file(py_path)
        repr_str = repr(pyfile)

        assert "utils.py" in repr_str
        assert "autogenerated=False" in repr_str

    def test_repr_autogenerated(self, tmp_path: Path) -> None:
        """Test repr for autogenerated file."""
        content = "# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/utils.ipynb\n"
        py_path = tmp_path / "utils.py"
        py_path.write_text(content)

        pyfile = PyFile.from_file(py_path)
        repr_str = repr(pyfile)

        assert "autogenerated=True" in repr_str


class TestPyFileCell:
    def test_pyfile_cell_creation(self) -> None:
        """Test PyFileCell creation."""
        cell = PyFileCell(
            source="def foo(): pass",
            source_path="../nbs/utils.ipynb",
            source_cell_index=0,
        )
        assert cell.source == "def foo(): pass"
        assert cell.source_path == "../nbs/utils.ipynb"
        assert cell.source_cell_index == 0
