"""Tests for YAMLLoader."""

from pathlib import Path

import pytest

from local_deep_research.document_loaders.yaml_loader import (
    YAMLLoader,
    extract_text_from_yaml,
)


class TestYAMLLoader:
    """Tests for YAMLLoader class."""

    def test_load_simple_yaml(self, tmp_path: Path) -> None:
        """Test loading a simple YAML file."""
        yaml_file = tmp_path / "test.yaml"
        yaml_file.write_text("name: test\nvalue: 123\n")

        loader = YAMLLoader(yaml_file)
        docs = loader.load()

        assert len(docs) == 1
        assert "name: test" in docs[0].page_content
        assert "value: 123" in docs[0].page_content
        assert docs[0].metadata["source"] == str(yaml_file)
        assert docs[0].metadata["file_type"] == "yaml"

    def test_load_nested_yaml(self, tmp_path: Path) -> None:
        """Test loading nested YAML structure."""
        yaml_content = """
database:
  host: localhost
  port: 5432
  credentials:
    username: admin
    password: secret
"""
        yaml_file = tmp_path / "nested.yaml"
        yaml_file.write_text(yaml_content)

        loader = YAMLLoader(yaml_file)
        docs = loader.load()

        assert len(docs) == 1
        assert "database:" in docs[0].page_content
        assert "host: localhost" in docs[0].page_content
        assert "credentials:" in docs[0].page_content

    def test_load_yaml_with_list(self, tmp_path: Path) -> None:
        """Test loading YAML with list values."""
        yaml_content = """
fruits:
  - apple
  - banana
  - cherry
"""
        yaml_file = tmp_path / "list.yaml"
        yaml_file.write_text(yaml_content)

        loader = YAMLLoader(yaml_file)
        docs = loader.load()

        assert len(docs) == 1
        assert "apple" in docs[0].page_content
        assert "banana" in docs[0].page_content

    def test_load_invalid_yaml_returns_raw_content(
        self, tmp_path: Path
    ) -> None:
        """Test that invalid YAML returns raw content with parse_error flag."""
        yaml_file = tmp_path / "invalid.yaml"
        yaml_file.write_text("invalid: yaml: content: [")

        loader = YAMLLoader(yaml_file)
        docs = loader.load()

        assert len(docs) == 1
        assert docs[0].metadata.get("parse_error") is True
        assert "invalid: yaml: content:" in docs[0].page_content

    def test_load_empty_yaml(self, tmp_path: Path) -> None:
        """Test loading empty YAML file skips the document."""
        yaml_file = tmp_path / "empty.yaml"
        yaml_file.write_text("")

        loader = YAMLLoader(yaml_file)
        docs = loader.load()

        # Empty YAML files should produce no documents
        assert len(docs) == 0

    def test_load_yaml_with_unicode(self, tmp_path: Path) -> None:
        """Test loading YAML with unicode characters."""
        yaml_content = "greeting: こんにちは\nemoji: 🎉\n"
        yaml_file = tmp_path / "unicode.yaml"
        yaml_file.write_text(yaml_content, encoding="utf-8")

        loader = YAMLLoader(yaml_file)
        docs = loader.load()

        assert len(docs) == 1
        assert "こんにちは" in docs[0].page_content
        assert "🎉" in docs[0].page_content

    def test_lazy_load(self, tmp_path: Path) -> None:
        """Test lazy_load returns an iterator."""
        yaml_file = tmp_path / "test.yaml"
        yaml_file.write_text("key: value\n")

        loader = YAMLLoader(yaml_file)
        result = loader.lazy_load()

        # Should be an iterator
        assert hasattr(result, "__iter__")
        assert hasattr(result, "__next__")

        # Should yield documents
        docs = list(result)
        assert len(docs) == 1

    def test_file_not_found_raises_error(self) -> None:
        """Test that missing file raises appropriate error."""
        loader = YAMLLoader("/nonexistent/path/file.yaml")

        with pytest.raises(Exception):
            loader.load()

    def test_load_multi_document_yaml(self, tmp_path: Path) -> None:
        """YAML files can contain multiple documents separated by ---"""
        yaml_file = tmp_path / "multi.yaml"
        yaml_file.write_text("name: doc1\n---\nname: doc2")

        loader = YAMLLoader(yaml_file)
        docs = loader.load()

        # Should load first document (PyYAML safe_load behavior)
        assert len(docs) >= 1
        assert "doc1" in docs[0].page_content

    def test_load_yaml_with_anchors(self, tmp_path: Path) -> None:
        """YAML supports &anchor and *alias references."""
        yaml_content = """defaults: &defaults
  timeout: 30
production:
  <<: *defaults
  host: prod.example.com
"""
        yaml_file = tmp_path / "anchors.yaml"
        yaml_file.write_text(yaml_content)

        loader = YAMLLoader(yaml_file)
        docs = loader.load()

        assert len(docs) == 1
        # Anchors should be resolved - production should have timeout from defaults
        assert "timeout" in docs[0].page_content
        assert "30" in docs[0].page_content


class TestExtractTextFromYaml:
    """Tests for extract_text_from_yaml function."""

    def test_extract_simple_yaml(self) -> None:
        """Test extracting text from simple YAML bytes."""
        content = b"name: test\nvalue: 123"
        result = extract_text_from_yaml(content)

        assert "name: test" in result
        assert "value: 123" in result

    def test_extract_nested_yaml(self) -> None:
        """Test extracting text from nested YAML bytes."""
        content = b"parent:\n  child: value\n  number: 42"
        result = extract_text_from_yaml(content)

        assert "parent:" in result
        assert "child: value" in result

    def test_extract_invalid_yaml_returns_raw(self) -> None:
        """Test that invalid YAML returns raw content."""
        content = b"invalid: yaml: [unclosed"
        result = extract_text_from_yaml(content)

        # Should return the raw content
        assert "invalid:" in result

    def test_extract_with_encoding_errors(self) -> None:
        """Test handling of encoding errors."""
        # Invalid UTF-8 bytes
        content = b"name: test\xff\xfe"
        result = extract_text_from_yaml(content)

        # Should still return something (with errors ignored)
        assert "name" in result

    def test_extract_empty_yaml(self) -> None:
        """Test extracting from empty YAML."""
        content = b""
        result = extract_text_from_yaml(content)

        assert result == ""
