"""Tests for file manager module."""

import tempfile
from pathlib import Path

import pytest

from anki_sync.models import Note
from anki_sync.file_manager import FileManager


class TestFileManager:
    """Tests for the FileManager class."""

    @pytest.fixture
    def temp_dir(self):
        """Create a temporary directory for testing."""
        with tempfile.TemporaryDirectory() as tmpdir:
            yield tmpdir

    @pytest.fixture
    def file_manager(self, temp_dir):
        """Create a FileManager with temporary directory."""
        return FileManager(temp_dir)

    def test_sanitize_filename(self, file_manager):
        """Test filename sanitization."""
        filename = file_manager.sanitize_filename("What is Python?", 12345)

        assert filename.endswith("_12345.yaml")
        assert "?" not in filename
        assert "what" in filename

    def test_sanitize_filename_special_chars(self, file_manager):
        """Test sanitization with special characters."""
        text = "Hello@World#2024!!"
        filename = file_manager.sanitize_filename(text, 999)

        assert "@" not in filename
        assert "#" not in filename
        assert "!" not in filename
        assert "helloworld2024" in filename

    def test_save_and_load_note(self, file_manager):
        """Test saving and loading a note."""
        original = Note(
            id=555,
            type="Basic",
            deck="Parent::Child",
            tags=["test"],
            fields={"Front": "Question", "Back": "Answer"},
        )

        filename = file_manager.save_note(original)
        loaded = file_manager.load_note(filename)

        assert loaded is not None
        assert loaded.id == original.id
        assert loaded.type == original.type
        assert loaded.deck == original.deck
        assert loaded.fields == original.fields
        assert filename.startswith("Parent/Child/")

    def test_get_all_yaml_files(self, file_manager):
        """Test retrieving all YAML files."""
        note1 = Note(id=1, type="Basic", deck="Top", fields={"F": "1"})
        note2 = Note(id=2, type="Basic", deck="Top::Sub", fields={"F": "2"})

        file_manager.save_note(note1)
        file_manager.save_note(note2)

        files = file_manager.get_all_yaml_files()
        assert len(files) == 2
        assert any(f.startswith("Top/") for f in files)
        assert any(f.startswith("Top/Sub/") for f in files)

    def test_get_all_notes(self, file_manager):
        """Test loading all notes."""
        notes = [
            Note(id=1, type="Basic", deck="Top", fields={"F": "Q1"}),
            Note(id=2, type="Cloze", deck="Top::Sub", fields={"T": "C1"}),
        ]

        for note in notes:
            file_manager.save_note(note)

        loaded = file_manager.get_all_notes()
        assert len(loaded) == 2
        assert any(n.id == 1 for n in loaded)
        assert any(n.id == 2 for n in loaded)
        assert any(n.deck == "Top" for n in loaded)
        assert any(n.deck == "Top::Sub" for n in loaded)

    def test_note_file_exists(self, file_manager):
        """Test checking if note file exists."""
        note = Note(id=777, type="Basic", fields={"F": "Q"})
        file_manager.save_note(note)

        assert file_manager.note_file_exists(777)
        assert not file_manager.note_file_exists(888)

    def test_update_note_id_in_file(self, file_manager):
        """Test updating note ID in file."""
        note = Note(id=100, type="Basic", deck="Top::Sub", fields={"F": "Q"})
        filename = file_manager.save_note(note)

        success = file_manager.update_note_id_in_file(filename, 200)
        assert success

        loaded = file_manager.load_note(filename)
        assert loaded.id == 200

    def test_load_note_infers_deck_from_path(self, file_manager):
        """Test loading a note with missing deck infers from path."""
        note = Note(id=300, type="Basic", deck="Top::Sub", fields={"F": "Q"})
        filename = file_manager.save_note(note)

        file_path = Path(file_manager.base_dir) / filename
        contents = file_path.read_text()
        contents = (
            "\n".join(
                line for line in contents.splitlines() if not line.startswith("deck:")
            )
            + "\n"
        )
        file_path.write_text(contents)

        loaded = file_manager.load_note(filename)
        assert loaded is not None
        assert loaded.deck == "Top::Sub"
