"""Tests for CASE expressions."""

import pytest
import networkx as nx

from nxcypher import NXCypher


def get_case_result(res):
    """Helper to get the CASE expression result from the result dict."""
    for key in res.keys():
        if key.startswith("CASE_"):
            return res[key]
    return None


class TestSearchedCase:
    """Tests for searched CASE expressions (CASE WHEN condition THEN result)."""

    def test_case_when_single_condition(self):
        """CASE with a single WHEN condition."""
        host = nx.MultiDiGraph()
        host.add_node("Alice", name="Alice", age=30)
        host.add_node("Bob", name="Bob", age=25)
        host.add_edge("Alice", "Bob", __labels__={"KNOWS"})

        qry = """
        MATCH (n)
        RETURN n.name, CASE WHEN n.age > 28 THEN "old" ELSE "young" END
        """
        res = NXCypher(host).run(qry)

        names = res["n.name"]
        case_results = get_case_result(res)

        alice_idx = names.index("Alice")
        bob_idx = names.index("Bob")

        assert case_results[alice_idx] == "old"
        assert case_results[bob_idx] == "young"

    def test_case_when_multiple_conditions(self):
        """CASE with multiple WHEN conditions."""
        host = nx.MultiDiGraph()
        host.add_node("Alice", name="Alice", age=15)
        host.add_node("Bob", name="Bob", age=35)
        host.add_node("Charlie", name="Charlie", age=70)
        host.add_edge("Alice", "Bob", __labels__={"KNOWS"})
        host.add_edge("Bob", "Charlie", __labels__={"KNOWS"})

        qry = """
        MATCH (n)
        RETURN n.name, CASE WHEN n.age < 18 THEN "minor" WHEN n.age < 65 THEN "adult" ELSE "senior" END
        """
        res = NXCypher(host).run(qry)

        names = res["n.name"]
        case_results = get_case_result(res)

        alice_idx = names.index("Alice")
        bob_idx = names.index("Bob")
        charlie_idx = names.index("Charlie")

        assert case_results[alice_idx] == "minor"
        assert case_results[bob_idx] == "adult"
        assert case_results[charlie_idx] == "senior"

    def test_case_when_no_else(self):
        """CASE without ELSE returns None when no condition matches."""
        host = nx.MultiDiGraph()
        host.add_node("Alice", name="Alice", age=30)
        host.add_edge("Alice", "Bob", __labels__={"KNOWS"})

        qry = """
        MATCH (n {name: "Alice"})
        RETURN n.name, CASE WHEN n.age > 100 THEN "centenarian" END
        """
        res = NXCypher(host).run(qry)

        assert res["n.name"] == ["Alice"]
        case_results = get_case_result(res)
        assert case_results[0] is None

    def test_case_with_equality_condition(self):
        """CASE with equality condition."""
        host = nx.MultiDiGraph()
        host.add_node("Alice", name="Alice", status="active")
        host.add_node("Bob", name="Bob", status="inactive")
        host.add_edge("Alice", "Bob", __labels__={"KNOWS"})

        qry = """
        MATCH (n)
        RETURN n.name, CASE WHEN n.status = "active" THEN "enabled" ELSE "disabled" END
        """
        res = NXCypher(host).run(qry)

        names = res["n.name"]
        case_results = get_case_result(res)

        alice_idx = names.index("Alice")
        bob_idx = names.index("Bob")

        assert case_results[alice_idx] == "enabled"
        assert case_results[bob_idx] == "disabled"


class TestSimpleCase:
    """Tests for simple CASE expressions (CASE expr WHEN value THEN result)."""

    def test_simple_case_string_match(self):
        """Simple CASE matching string values."""
        host = nx.MultiDiGraph()
        host.add_node("Alice", name="Alice", role="admin")
        host.add_node("Bob", name="Bob", role="user")
        host.add_node("Charlie", name="Charlie", role="guest")
        host.add_edge("Alice", "Bob", __labels__={"KNOWS"})
        host.add_edge("Bob", "Charlie", __labels__={"KNOWS"})

        qry = """
        MATCH (n)
        RETURN n.name, CASE n.role WHEN "admin" THEN "full" WHEN "user" THEN "limited" ELSE "none" END
        """
        res = NXCypher(host).run(qry)

        names = res["n.name"]
        case_results = get_case_result(res)

        alice_idx = names.index("Alice")
        bob_idx = names.index("Bob")
        charlie_idx = names.index("Charlie")

        assert case_results[alice_idx] == "full"
        assert case_results[bob_idx] == "limited"
        assert case_results[charlie_idx] == "none"

    def test_simple_case_numeric_match(self):
        """Simple CASE matching numeric values."""
        host = nx.MultiDiGraph()
        host.add_node("Alice", name="Alice", level=1)
        host.add_node("Bob", name="Bob", level=2)
        host.add_node("Charlie", name="Charlie", level=3)
        host.add_edge("Alice", "Bob", __labels__={"KNOWS"})
        host.add_edge("Bob", "Charlie", __labels__={"KNOWS"})

        qry = """
        MATCH (n)
        RETURN n.name, CASE n.level WHEN 1 THEN "beginner" WHEN 2 THEN "intermediate" ELSE "advanced" END
        """
        res = NXCypher(host).run(qry)

        names = res["n.name"]
        case_results = get_case_result(res)

        alice_idx = names.index("Alice")
        bob_idx = names.index("Bob")
        charlie_idx = names.index("Charlie")

        assert case_results[alice_idx] == "beginner"
        assert case_results[bob_idx] == "intermediate"
        assert case_results[charlie_idx] == "advanced"


class TestCaseWithRelationships:
    """Tests for CASE expressions with relationships."""

    def test_case_with_relationship_match(self):
        """CASE expression in query with relationship."""
        host = nx.MultiDiGraph()
        host.add_node("Alice", name="Alice", age=30)
        host.add_node("Bob", name="Bob", age=25)
        host.add_edge("Alice", "Bob", __labels__={"KNOWS"})

        qry = """
        MATCH (a)-[:KNOWS]->(b)
        RETURN a.name, b.name, CASE WHEN a.age > b.age THEN "older" ELSE "younger" END
        """
        res = NXCypher(host).run(qry)

        assert res["a.name"] == ["Alice"]
        assert res["b.name"] == ["Bob"]
        case_results = get_case_result(res)
        assert case_results[0] == "older"


class TestCaseEdgeCases:
    """Edge case tests for CASE expressions."""

    def test_case_with_null_value(self):
        """CASE handling null property values."""
        host = nx.MultiDiGraph()
        host.add_node("Alice", name="Alice")  # No age property
        host.add_edge("Alice", "Bob", __labels__={"KNOWS"})

        qry = """
        MATCH (n {name: "Alice"})
        RETURN n.name, CASE WHEN n.age > 30 THEN "old" ELSE "unknown" END
        """
        res = NXCypher(host).run(qry)

        assert res["n.name"] == ["Alice"]
        case_results = get_case_result(res)
        assert case_results[0] == "unknown"

    def test_case_returning_property_value(self):
        """CASE returning a property value instead of literal."""
        host = nx.MultiDiGraph()
        host.add_node("Alice", name="Alice", nickname="Ali", formalname="Mrs. Alice")
        host.add_edge("Alice", "Bob", __labels__={"KNOWS"})

        # This test verifies the CASE can reference node properties in result
        qry = """
        MATCH (n {name: "Alice"})
        RETURN CASE WHEN n.name = "Alice" THEN n.nickname ELSE n.formalname END
        """
        res = NXCypher(host).run(qry)

        case_results = get_case_result(res)
        assert case_results[0] == "Ali"
