"""TDD tests for axm_bib.storage — FileSystemStorage. Written BEFORE implementation."""

from __future__ import annotations

from pathlib import Path

from axm_bib.storage import FileSystemStorage


class TestFileSystemStorage:
    """FileSystemStorage with tmp_path."""

    def test_default_output_dir(self) -> None:
        """Default output_dir is ~/axm/papers/."""
        storage = FileSystemStorage()
        assert storage.output_dir == Path.home() / "axm" / "papers"

    def test_custom_output_dir(self, tmp_path: Path) -> None:
        """Custom output_dir is respected."""
        storage = FileSystemStorage(output_dir=tmp_path / "custom")
        assert storage.output_dir == tmp_path / "custom"

    def test_save_creates_pdf(self, tmp_path: Path) -> None:
        """save() creates a file at the expected path."""
        storage = FileSystemStorage(output_dir=tmp_path)
        pdf_bytes = b"%PDF-1.4 fake content"

        path = storage.save(
            doi="10.1145/123",
            pdf_bytes=pdf_bytes,
            bib_key="smith2024deep",
        )

        assert Path(path).exists()
        assert Path(path).read_bytes() == pdf_bytes

    def test_save_naming_convention(self, tmp_path: Path) -> None:
        """Filename = {bib_key}/{bib_key}.pdf."""
        storage = FileSystemStorage(output_dir=tmp_path)
        path = storage.save(
            doi="10.1145/123",
            pdf_bytes=b"content",
            bib_key="smith2024deep",
        )
        assert Path(path).name == "smith2024deep.pdf"
        assert Path(path).parent.name == "smith2024deep"

    def test_exists_true_after_save(self, tmp_path: Path) -> None:
        """exists() returns True after saving."""
        storage = FileSystemStorage(output_dir=tmp_path)
        storage.save(doi="10.1145/123", pdf_bytes=b"c", bib_key="key2024x")
        assert storage.exists("key2024x") is True

    def test_exists_false_before_save(self, tmp_path: Path) -> None:
        """exists() returns False for unsaved key."""
        storage = FileSystemStorage(output_dir=tmp_path)
        assert storage.exists("nonexistent2024x") is False

    def test_save_creates_subdirs(self, tmp_path: Path) -> None:
        """Parent directories created automatically."""
        deep_path = tmp_path / "a" / "b" / "c"
        storage = FileSystemStorage(output_dir=deep_path)
        path = storage.save(doi="10.1145/123", pdf_bytes=b"c", bib_key="k2024x")
        assert Path(path).exists()

    def test_save_returns_absolute_path(self, tmp_path: Path) -> None:
        """Returned path is absolute."""
        storage = FileSystemStorage(output_dir=tmp_path)
        path = storage.save(doi="10.1145/123", pdf_bytes=b"c", bib_key="k2024x")
        assert Path(path).is_absolute()

    def test_overwrite_existing(self, tmp_path: Path) -> None:
        """Second save overwrites without error."""
        storage = FileSystemStorage(output_dir=tmp_path)
        storage.save(doi="10.1145/123", pdf_bytes=b"old", bib_key="k2024x")
        path = storage.save(doi="10.1145/123", pdf_bytes=b"new", bib_key="k2024x")
        assert Path(path).read_bytes() == b"new"


class TestFileSystemStorageFolderLayout:
    """Tests for folder-per-paper layout: {output_dir}/{key}/{key}.pdf."""

    def test_save_creates_subfolder(self, tmp_path: Path) -> None:
        """save() stores PDF inside {key}/ subfolder."""
        storage = FileSystemStorage(output_dir=tmp_path)
        path = storage.save(
            doi="10.1145/123",
            pdf_bytes=b"%PDF-1.4 content",
            bib_key="smith2024deep",
        )
        # PDF should be at {tmp_path}/smith2024deep/smith2024deep.pdf
        assert Path(path).parent.name == "smith2024deep"
        assert Path(path).name == "smith2024deep.pdf"

    def test_paper_dir_returns_folder_path(self, tmp_path: Path) -> None:
        """paper_dir() returns the folder for a given key."""
        storage = FileSystemStorage(output_dir=tmp_path)
        paper_dir = storage.paper_dir("smith2024deep")
        assert paper_dir == tmp_path / "smith2024deep"

    def test_save_bibtex_writes_file(self, tmp_path: Path) -> None:
        """save_bibtex() writes paper.bib inside the paper folder."""
        storage = FileSystemStorage(output_dir=tmp_path)
        raw_bib = "@article{smith2024deep,\n  title={Deep},\n  author={Smith}\n}"
        path = storage.save_bibtex(bib_key="smith2024deep", raw_bibtex=raw_bib)

        assert Path(path).exists()
        assert Path(path).name == "paper.bib"
        assert Path(path).read_text() == raw_bib
        assert Path(path).parent.name == "smith2024deep"

    def test_save_bibtex_creates_folder(self, tmp_path: Path) -> None:
        """save_bibtex() creates the paper folder if it doesn't exist."""
        storage = FileSystemStorage(output_dir=tmp_path)
        storage.save_bibtex(bib_key="newpaper2024", raw_bibtex="@article{...}")
        assert (tmp_path / "newpaper2024").is_dir()

    def test_exists_checks_folder(self, tmp_path: Path) -> None:
        """exists() returns True when the paper folder exists."""
        storage = FileSystemStorage(output_dir=tmp_path)
        storage.save(doi="10.1145/123", pdf_bytes=b"c", bib_key="k2024x")
        assert storage.exists("k2024x") is True
        assert storage.exists("nonexistent") is False
