"""YAML parser with __children__ separation."""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Any

import yaml


@dataclass
class ParsedRecord:
    fields: dict[str, Any]
    children: dict[str, list[ParsedRecord]] | None


@dataclass
class ParsedGroup:
    name: str
    records: list[ParsedRecord]


def parse_yaml(filepath: str | Path) -> list[ParsedGroup]:
    """Parse a YAML fixture file into a list of groups.

    The YAML top-level must be a dict mapping group names to lists of
    records.  The reserved key ``__children__`` is separated from
    regular fields and stored in ``ParsedRecord.children``.

    Args:
        filepath: Path to the YAML fixture file.

    Raises:
        ValueError: If the file is empty, not a dict, or has invalid
            structure.
    """
    with open(filepath) as f:
        data = yaml.safe_load(f)

    if data is None:
        raise ValueError("YAML file is empty")
    if not isinstance(data, dict):
        raise ValueError(f"YAML top-level must be a dict, got {type(data).__name__}")

    groups: list[ParsedGroup] = []
    for group_name, records_data in data.items():
        if not isinstance(records_data, list):
            raise ValueError(f"Group '{group_name}' must be a list, got {type(records_data).__name__}")
        records = [_parse_record(group_name, i, r) for i, r in enumerate(records_data)]
        groups.append(ParsedGroup(name=group_name, records=records))

    return groups


def _parse_record(group_name: str, index: int, data: Any) -> ParsedRecord:
    if not isinstance(data, dict):
        raise ValueError(f"Record {group_name}[{index}] must be a dict, got {type(data).__name__}")

    children_raw = data.get("__children__")
    fields = {k: v for k, v in data.items() if k != "__children__"}

    children: dict[str, list[ParsedRecord]] | None = None
    if children_raw is not None:
        if not isinstance(children_raw, dict):
            raise ValueError(
                f"Record {group_name}[{index}].__children__ must be a dict, got {type(children_raw).__name__}"
            )
        children = {}
        for child_group, child_records in children_raw.items():
            children[child_group] = [_parse_record(child_group, i, r) for i, r in enumerate(child_records)]

    return ParsedRecord(fields=fields, children=children)
