"""Tests for Result and Record classes."""

import pytest

from piggie.result import Record, Result, _expand_row
from piggie.types import Edge, Vertex


class TestRecord:
    def test_keyed_access(self):
        r = Record(["name", "age"], ("Alice", 30))
        assert r["name"] == "Alice"
        assert r["age"] == 30

    def test_positional_access(self):
        r = Record(["name", "age"], ("Alice", 30))
        assert r[0] == "Alice"
        assert r[1] == 30

    def test_get_with_default(self):
        r = Record(["name"], ("Alice",))
        assert r.get("name") == "Alice"
        assert r.get("missing", "default") == "default"

    def test_keys_values_items(self):
        r = Record(["a", "b"], (1, 2))
        assert r.keys() == ["a", "b"]
        assert r.values() == [1, 2]
        assert r.items() == [("a", 1), ("b", 2)]

    def test_len(self):
        r = Record(["a", "b", "c"], (1, 2, 3))
        assert len(r) == 3

    def test_repr(self):
        r = Record(["x"], (42,))
        assert "42" in repr(r)


class TestResult:
    def test_empty_result(self):
        res = Result([], ["col1"])
        assert len(res) == 0
        assert not res
        assert res.columns == ["col1"]

    def test_to_dicts(self):
        res = Result([(1, "Alice"), (2, "Bob")], ["id", "name"])
        dicts = res.to_dicts()
        assert dicts == [
            {"id": 1, "name": "Alice"},
            {"id": 2, "name": "Bob"},
        ]

    def test_single(self):
        res = Result([(42,)], ["val"])
        rec = res.single()
        assert rec["val"] == 42

    def test_single_raises_on_empty(self):
        res = Result([], ["val"])
        with pytest.raises(ValueError, match="Expected exactly 1"):
            res.single()

    def test_single_raises_on_multiple(self):
        res = Result([(1,), (2,)], ["val"])
        with pytest.raises(ValueError, match="Expected exactly 1"):
            res.single()

    def test_records(self):
        res = Result([(1, "a"), (2, "b")], ["id", "name"])
        recs = res.records
        assert len(recs) == 2
        assert recs[0]["id"] == 1
        assert recs[1]["name"] == "b"

    def test_iteration(self):
        res = Result([(1,), (2,), (3,)], ["v"])
        vals = [r["v"] for r in res]
        assert vals == [1, 2, 3]

    def test_bool(self):
        assert Result([(1,)], ["v"])
        assert not Result([], ["v"])

    def test_to_df(self):
        pytest.importorskip("pandas")
        res = Result([(1, "Alice"), (2, "Bob")], ["id", "name"])
        df = res.to_df()
        assert list(df.columns) == ["id", "name"]
        assert len(df) == 2
        assert df["name"].tolist() == ["Alice", "Bob"]

    def test_to_df_empty(self):
        pytest.importorskip("pandas")
        res = Result([], ["id", "name"])
        df = res.to_df()
        assert list(df.columns) == ["id", "name"]
        assert len(df) == 0

    def test_to_arrow(self):
        pytest.importorskip("pyarrow")
        res = Result([(1, "Alice"), (2, "Bob")], ["id", "name"])
        table = res.to_arrow()
        assert table.num_rows == 2
        assert table.column_names == ["id", "name"]

    def test_repr(self):
        res = Result([(1,)], ["v"])
        assert "rows=1" in repr(res)


class TestExpandRow:
    def test_expand_vertex(self):
        v = Vertex(id=1, label="Person", properties={"name": "Alice", "age": 30})
        row = {"n": v}
        expanded = _expand_row(row)
        assert expanded == {
            "n._id": 1,
            "n._label": "Person",
            "n.name": "Alice",
            "n.age": 30,
        }

    def test_expand_edge(self):
        e = Edge(id=10, label="KNOWS", start_id=1, end_id=2, properties={"since": 2020})
        row = {"r": e}
        expanded = _expand_row(row)
        assert expanded["r._id"] == 10
        assert expanded["r._label"] == "KNOWS"
        assert expanded["r._start_id"] == 1
        assert expanded["r._end_id"] == 2
        assert expanded["r.since"] == 2020

    def test_expand_scalar(self):
        row = {"count": 42}
        assert _expand_row(row) == {"count": 42}

    def test_to_df_expand(self):
        pytest.importorskip("pandas")
        v = Vertex(id=1, label="Person", properties={"name": "Alice"})
        res = Result([(v,)], ["n"])
        df = res.to_df(expand=True)
        assert "n.name" in df.columns
        assert df["n.name"].tolist() == ["Alice"]
