
from g_gremlin import repair


def test_extract_row():
    assert repair.extract_row("A1") == 1
    assert repair.extract_row("Z99") == 99
    assert repair.extract_row("AA100") == 100
    assert repair.extract_row("Sheet1!B12") == 12


def test_extract_col():
    assert repair.extract_col("A1") == "A"
    assert repair.extract_col("Z99") == "Z"
    assert repair.extract_col("AA100") == "AA"
    assert repair.extract_col("Orion_FY26!J6") == "J"


def test_extract_sheet_refs():
    refs = repair.extract_sheet_refs("='Sheet 1'!$B$10 + Sheet2!A1")
    assert ("Sheet 1", "$B$10") in refs
    assert ("Sheet2", "A1") in refs


def test_detect_column_pattern():
    cells = [
        {"a1": "J14", "formula": "=IFERROR(OFFSET(J4,0,-2),0)"},
        {"a1": "J16", "formula": "=IFERROR(OFFSET(J6,0,-2),0)"},
        {"a1": "J17", "formula": "=IFERROR(OFFSET(J7,0,-2),0)"},
    ]
    pattern = repair.detect_column_pattern(cells)
    assert pattern is not None
    assert pattern["confidence"] >= 0.6


def test_find_ref_errors():
    cells = [
        {"a1": "J15", "formula": "=IFERROR(OFFSET(#REF!,0,-2),0)", "value": "#REF!"},
        {"a1": "J16", "formula": "=IFERROR(OFFSET(J6,0,-2),0)", "value": 5},
    ]
    issues = repair.find_ref_errors(cells)
    assert len(issues) == 1
    assert issues[0].cell == "J15"
    assert issues[0].type == "ref_error"


def test_health_score():
    cells = [{"a1": f"A{i}", "formula": f"=A{i-1}+1"} for i in range(2, 102)]
    score = repair.calculate_health_score(cells, [])
    assert score >= 90

    issues = [
        repair.Issue(
            id=f"err_{i}",
            cell=f"A{i}",
            type="ref_error",
            severity="error",
            current_formula="",
            current_value="#REF!",
            diagnosis="broken",
        )
        for i in range(20)
    ]
    score = repair.calculate_health_score(cells, issues)
    assert score < 50


def test_health_grade():
    assert repair.health_grade(95) == "A+"
    assert repair.health_grade(85) == "B+"
    assert repair.health_grade(65) == "D"
    assert repair.health_grade(50) == "F"


def test_infer_stub_value_known_cells():
    result = repair.infer_stub_value("MH 2026", "B10", [], [])
    assert result is not None
    assert result["value"] == 0.25

    result = repair.infer_stub_value("MH 2026", "E2", [], [])
    assert result is not None
    assert result["value"] == 0.15


def test_pattern_anomalies_ignore_empty_cells():
    cells = [
        {"a1": "J1", "value": "", "formula": ""},
        {"a1": "J2", "value": "", "formula": ""},
        {"a1": "J3", "value": "", "formula": ""},
        {"a1": "J4", "value": "", "formula": "=A4+1"},
        {"a1": "J5", "value": "", "formula": "=A5+1"},
        {"a1": "J6", "value": "", "formula": "=A6+1"},
    ]
    issues, summary = repair.find_pattern_anomalies(cells)
    assert issues == []
    assert summary == []


def test_pattern_anomalies_respect_bands():
    cells = [
        {"a1": "J5", "value": "", "formula": "=A5*'FY26_Assumptions'!$B$11"},
        {"a1": "K5", "value": "", "formula": "=A5*'FY26_Assumptions'!$B$11"},
        {"a1": "N5", "value": "", "formula": "=A5*'FY27_Assumptions'!$B$11"},
    ]
    bands = {"J": "FY26_Assumptions", "K": "FY26_Assumptions", "N": "FY27_Assumptions"}
    issues, summary = repair.find_pattern_anomalies(cells, expected_sheet_map=bands)
    assert issues == []
    assert summary == []
