"""Tests for Maintainability Index (Python)."""

from vibelexity.analyzers.python import analyze_source


def _mi(code: str) -> int | float:
    """Return MI of the first function in code."""
    result = analyze_source(code)
    assert result.functions, f"No functions found in:\n{code}"
    mi_val = result.functions[0].mi
    assert mi_val is not None
    return mi_val


# --- Trivial function (high MI) ---


def test_trivial_function():
    code = """
def f():
    return 1
"""
    mi = _mi(code)
    assert mi > 50, f"Trivial function should have high MI, got {mi}"


def test_simple_add():
    code = """
def add(a, b):
    return a + b
"""
    mi = _mi(code)
    assert mi > 50, f"Simple function should have high MI, got {mi}"


# --- Complex function (low MI) ---


def test_complex_function():
    code = """
def process(data, flag, mode, opt, extra):
    result = []
    total = 0
    count = 0
    for item in data:
        if flag and mode:
            if item > 0:
                for sub in item:
                    if sub < 100:
                        if opt or extra:
                            result.append(sub * 2 + total)
                            count += 1
                        else:
                            result.append(sub - 1)
                    elif sub > 200:
                        total += sub
                        count -= 1
            elif item < 0:
                try:
                    val = int(item)
                    if val > 0 and val < 50:
                        result.append(val)
                    elif val >= 50 or val == 0:
                        result.append(-val)
                except Exception:
                    result.append(0)
        elif mode or opt:
            for sub in data:
                if sub != item:
                    result.append(sub + item)
                    total += sub
    if count > 0:
        return result[:count]
    return result
"""
    mi = _mi(code)
    assert mi < 50, f"Complex function should have low MI, got {mi}"


# --- Edge case: empty body ---


def test_empty_body():
    code = """
def noop():
    pass
"""
    mi = _mi(code)
    assert mi > 50, f"Empty body function should have high MI, got {mi}"


# --- Edge case: no operators ---


def test_no_operators():
    code = """
def f():
    x = 1
"""
    mi = _mi(code)
    # With minimal halstead volume, MI should be high
    assert mi > 50, f"No-operator function should have high MI, got {mi}"


# --- MI is in valid range ---


def test_mi_range():
    code = """
def f(x):
    if x:
        return 1
    return 0
"""
    mi = _mi(code)
    assert 0 <= mi <= 100, f"MI should be in [0, 100], got {mi}"


# --- Multiple functions ---


def test_multiple_functions():
    code = """
def simple():
    return 42

def moderate(x, y):
    if x > y:
        return x
    elif x < y:
        return y
    else:
        return x + y
"""
    result = analyze_source(code)
    assert len(result.functions) == 2
    mi_simple = result.functions[0].mi
    mi_moderate = result.functions[1].mi
    assert mi_simple is not None and mi_moderate is not None
    assert mi_simple > mi_moderate, (
        f"Simple function should have higher MI: {mi_simple} vs {mi_moderate}"
    )
