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

from vibelexity.analyzers.typescript 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 = """
function f() {
    return 1;
}
"""
    mi = _mi(code)
    assert mi > 50, f"Trivial function should have high MI, got {mi}"


def test_simple_add():
    code = """
function add(a: number, b: number): number {
    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 = """
function process(data: any[], flag: boolean, mode: boolean, opt: boolean, extra: boolean) {
    let result: any[] = [];
    let total = 0;
    let count = 0;
    for (let item of data) {
        if (flag && mode) {
            if (item > 0) {
                for (let sub of item) {
                    if (sub < 100) {
                        if (opt || extra) {
                            result.push(sub * 2 + total);
                            count += 1;
                        } else {
                            result.push(sub - 1);
                        }
                    } else if (sub > 200) {
                        total += sub;
                        count -= 1;
                    }
                }
            } else if (item < 0) {
                try {
                    const val = parseInt(item);
                    if (val > 0 && val < 50) {
                        result.push(val);
                    } else if (val >= 50 || val === 0) {
                        result.push(-val);
                    }
                } catch (e) {
                    result.push(0);
                }
            }
        } else if (mode || opt) {
            for (let sub of data) {
                if (sub !== item) {
                    result.push(sub + item);
                    total += sub;
                }
            }
        }
    }
    if (count > 0) {
        return result.slice(0, 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 = """
function noop() {}
"""
    mi = _mi(code)
    # With empty/minimal body, MI should be high
    assert mi > 50, f"Empty body function should have high MI, got {mi}"


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


def test_no_operators():
    code = """
function f() {
    const x = 1;
}
"""
    mi = _mi(code)
    assert mi > 50, f"No-operator function should have high MI, got {mi}"


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


def test_mi_range():
    code = """
function f(x: boolean) {
    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 = """
function simple() {
    return 42;
}

function moderate(x: number, y: number) {
    if (x > y) {
        return x;
    } else if (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}"
    )
