"""Tests for Data Transformation Density (Go)."""

from vibelexity.analyzers.go import analyze_source


def _dtd(code: str) -> int:
    """Return DTD of the first function in code."""
    result = analyze_source(code)
    assert result.functions, f"No functions found in:\n{code}"
    dtd_val = result.functions[0].dtd
    assert dtd_val is not None
    return dtd_val


def _dtds(code: str) -> dict[str, int]:
    """Return {name: dtd} for all functions in code."""
    result = analyze_source(code)
    return {f.name: f.dtd for f in result.functions if f.dtd is not None}


# --- Empty ---


def test_empty_function():
    code = "package main\nfunc f() {}"
    assert _dtd(code) == 0


# --- Struct literal ---


def test_struct_literal():
    code = """
package main

type Point struct {
    X int
    Y int
}

func f() Point {
    return Point{X: 1, Y: 2}
}
"""
    # composite_literal at depth 1, 2 keyed_elements x 1 = 2
    assert _dtd(code) == 2


# --- Slice literal ---


def test_slice_literal():
    code = """
package main

func f() []int {
    return []int{1, 2, 3}
}
"""
    # composite_literal at depth 1, 3 literal_elements x 1 = 3
    assert _dtd(code) == 3


# --- Map literal ---


def test_map_literal():
    code = """
package main

func f() map[string]int {
    return map[string]int{"a": 1, "b": 2}
}
"""
    # composite_literal at depth 1, 2 keyed_elements x 1 = 2
    assert _dtd(code) == 2


# --- Nested composite ---


def test_nested_composite():
    code = """
package main

type Inner struct {
    Value int
}

type Outer struct {
    Items []Inner
}

func f() Outer {
    return Outer{
        Items: []Inner{
            Inner{Value: 1},
            Inner{Value: 2},
        },
    }
}
"""
    # Outer composite at depth 1: keyed_element "Items: ..." -> 1
    # []Inner{} composite at depth 2 (nested in the value of the keyed_element)
    # 2 literal_elements at depth 2 -> 4
    # Each Inner{} composite at depth 3: keyed_element at depth 3 -> 3 each -> 6
    # total = 1 + 4 + 6 = 11
    assert _dtd(code) == 11


# --- Nested named closure ---


def test_nested_named_closure():
    code = """
package main

func outer() {
    x := map[string]int{"a": 1}
    inner := func() {
        y := []int{1, 2, 3}
    }
    _ = inner
    _ = x
}
"""
    dtds = _dtds(code)
    assert dtds["outer"] == 1  # only map[string]int{"a": 1} -> 1 keyed_element x 1
    assert dtds["inner"] == 3  # []int{1, 2, 3} -> 3 literal_elements x 1
