"""Tests for _parse module."""

from __future__ import annotations

import pytest

from db_test_helpers.core._parse import parse_yaml


@pytest.fixture
def yaml_file(tmp_path):
    def _write(content: str) -> str:
        p = tmp_path / "test.yaml"
        p.write_text(content)
        return str(p)

    return _write


class TestParseYamlBasic:
    def test_single_group_single_record(self, yaml_file):
        path = yaml_file(
            """\
users:
  - name: "Alice"
    age: 30
"""
        )
        result = parse_yaml(path)
        assert len(result) == 1
        assert result[0].name == "users"
        assert len(result[0].records) == 1
        assert result[0].records[0].fields == {"name": "Alice", "age": 30}
        assert result[0].records[0].children is None

    def test_single_group_multiple_records(self, yaml_file):
        path = yaml_file(
            """\
users:
  - name: "Alice"
  - name: "Bob"
"""
        )
        result = parse_yaml(path)
        assert len(result[0].records) == 2
        assert result[0].records[0].fields == {"name": "Alice"}
        assert result[0].records[1].fields == {"name": "Bob"}

    def test_multiple_groups(self, yaml_file):
        path = yaml_file(
            """\
users:
  - name: "Alice"
posts:
  - title: "Hello"
"""
        )
        result = parse_yaml(path)
        assert len(result) == 2
        assert result[0].name == "users"
        assert result[1].name == "posts"


class TestParseYamlChildren:
    def test_children_separated(self, yaml_file):
        path = yaml_file(
            """\
users:
  - name: "Alice"
    __children__:
      posts:
        - title: "Hello"
"""
        )
        result = parse_yaml(path)
        record = result[0].records[0]
        assert "name" in record.fields
        assert "__children__" not in record.fields
        assert record.children is not None
        assert "posts" in record.children
        assert len(record.children["posts"]) == 1
        assert record.children["posts"][0].fields == {"title": "Hello"}

    def test_nested_children(self, yaml_file):
        path = yaml_file(
            """\
users:
  - name: "Alice"
    __children__:
      posts:
        - title: "Hello"
          __children__:
            comments:
              - body: "Nice!"
"""
        )
        result = parse_yaml(path)
        post = result[0].records[0].children["posts"][0]
        assert post.fields == {"title": "Hello"}
        assert post.children is not None
        comment = post.children["comments"][0]
        assert comment.fields == {"body": "Nice!"}

    def test_no_children(self, yaml_file):
        path = yaml_file(
            """\
users:
  - name: "Alice"
"""
        )
        result = parse_yaml(path)
        assert result[0].records[0].children is None


class TestParseYamlValidation:
    def test_top_level_not_dict(self, yaml_file):
        path = yaml_file("- item1\n- item2\n")
        with pytest.raises(ValueError, match="top-level"):
            parse_yaml(path)

    def test_group_value_not_list(self, yaml_file):
        path = yaml_file("users:\n  name: Alice\n")
        with pytest.raises(ValueError, match="list"):
            parse_yaml(path)

    def test_record_not_dict(self, yaml_file):
        path = yaml_file("users:\n  - just a string\n")
        with pytest.raises(ValueError, match="dict"):
            parse_yaml(path)

    def test_empty_file(self, yaml_file):
        path = yaml_file("")
        with pytest.raises(ValueError, match="empty"):
            parse_yaml(path)

    def test_children_not_dict(self, yaml_file):
        path = yaml_file('users:\n  - name: "Alice"\n    __children__: "not-a-dict"\n')
        with pytest.raises(ValueError, match="__children__.*dict"):
            parse_yaml(path)

    def test_path_object(self, tmp_path):
        p = tmp_path / "test.yaml"
        p.write_text('users:\n  - name: "Alice"\n')
        result = parse_yaml(p)
        assert len(result) == 1
