import pytest
from acmg_calculator import calculate_pathogenicity, metadata, VALID_CODES

# Metadata tests
def test_metadata_completeness():
    data = metadata()
    for code in VALID_CODES:
        assert code in data, f"Code {code} missing from metadata"
    assert len(data) == len(VALID_CODES)

# Pathogenic rules
def test_pathogenic_pvs1_ps1():
    # 1 Very Strong (PVS1) AND ≥1 Strong (PS1-PS4)
    assert calculate_pathogenicity(['PVS1', 'PS1']) == "Pathogenic"

def test_pathogenic_pvs1_pm_pm():
    # 1 Very Strong (PVS1) AND ≥2 Moderate (PM1-PM6)
    assert calculate_pathogenicity(['PVS1', 'PM1', 'PM2']) == "Pathogenic"

def test_pathogenic_pvs1_pm_pp():
    # 1 Very Strong (PVS1) AND 1 Moderate (PM1-PM6) AND 1 Supporting (PP1-PP5)
    assert calculate_pathogenicity(['PVS1', 'PM1', 'PP1']) == "Pathogenic"

def test_pathogenic_pvs1_pp_pp():
    # 1 Very Strong (PVS1) AND ≥2 Supporting (PP1-PP5)
    assert calculate_pathogenicity(['PVS1', 'PP1', 'PP2']) == "Pathogenic"

def test_pathogenic_ps_ps():
    # ≥2 Strong (PS1-PS4)
    assert calculate_pathogenicity(['PS1', 'PS2']) == "Pathogenic"

def test_pathogenic_ps_pm_pm_pm():
    # 1 Strong (PS1-PS4) AND ≥3 Moderate (PM1-PM6)
    assert calculate_pathogenicity(['PS1', 'PM1', 'PM2', 'PM3']) == "Pathogenic"

def test_pathogenic_ps_pm_pm_pp_pp():
    # 1 Strong (PS1-PS4) AND 2 Moderate (PM1-PM6) AND ≥2 Supporting (PP1-PP5)
    assert calculate_pathogenicity(['PS1', 'PM1', 'PM2', 'PP1', 'PP2']) == "Pathogenic"

def test_pathogenic_ps_pm_pp_pp_pp_pp():
    # 1 Strong (PS1-PS4) AND 1 Moderate (PM1-PM6) AND ≥4 Supporting (PP1-PP5)
    assert calculate_pathogenicity(['PS1', 'PM1', 'PP1', 'PP2', 'PP3', 'PP4']) == "Pathogenic"

# Likely Pathogenic rules
def test_likely_pathogenic_pvs1_pm1():
    # 1 Very Strong (PVS1) AND 1 Moderate (PM1-PM6)
    assert calculate_pathogenicity(['PVS1', 'PM1']) == "Likely Pathogenic"

def test_likely_pathogenic_ps1_pm1():
    # 1 Strong (PS1-PS4) AND 1-2 Moderate (PM1-PM6)
    assert calculate_pathogenicity(['PS1', 'PM1']) == "Likely Pathogenic"
    assert calculate_pathogenicity(['PS1', 'PM1', 'PM2']) == "Likely Pathogenic"

def test_likely_pathogenic_ps1_pp_pp():
    # 1 Strong (PS1-PS4) AND ≥2 Supporting (PP1-PP5)
    assert calculate_pathogenicity(['PS1', 'PP1', 'PP2']) == "Likely Pathogenic"

def test_likely_pathogenic_pm_pm_pm():
    # ≥3 Moderate (PM1-PM6)
    assert calculate_pathogenicity(['PM1', 'PM2', 'PM3']) == "Likely Pathogenic"

def test_likely_pathogenic_pm_pm_pp_pp():
    # 2 Moderate (PM1-PM6) AND ≥2 Supporting (PP1-PP5)
    assert calculate_pathogenicity(['PM1', 'PM2', 'PP1', 'PP2']) == "Likely Pathogenic"

def test_likely_pathogenic_pm_pp_pp_pp_pp():
    # 1 Moderate (PM1-PM6) AND ≥4 Supporting (PP1-PP5)
    assert calculate_pathogenicity(['PM1', 'PP1', 'PP2', 'PP3', 'PP4']) == "Likely Pathogenic"

# Benign rules
def test_benign_ba1():
    # 1 Stand-alone (BA1)
    assert calculate_pathogenicity(['BA1']) == "Benign"

def test_benign_bs_bs():
    # ≥2 Strong (BS1-BS4)
    assert calculate_pathogenicity(['BS1', 'BS2']) == "Benign"

# Likely Benign rules
def test_likely_benign_bs_bp():
    # 1 Strong (BS1-BS4) and 1 Supporting (BP1-BP7)
    assert calculate_pathogenicity(['BS1', 'BP1']) == "Likely Benign"

def test_likely_benign_bp_bp():
    # ≥2 Supporting (BP1-BP7)
    assert calculate_pathogenicity(['BP1', 'BP2']) == "Likely Benign"

# Uncertain Significance (VUS)
def test_uncertain_vus_no_criteria():
    assert calculate_pathogenicity([]) == "Uncertain Significance"

def test_uncertain_vus_insufficient_pathogenic():
    assert calculate_pathogenicity(['PM1', 'PM2']) == "Uncertain Significance"
    assert calculate_pathogenicity(['PS1']) == "Uncertain Significance"
    assert calculate_pathogenicity(['PP1', 'PP2', 'PP3']) == "Uncertain Significance"

def test_uncertain_vus_insufficient_benign():
    assert calculate_pathogenicity(['BS1']) == "Uncertain Significance"
    assert calculate_pathogenicity(['BP1']) == "Uncertain Significance"

def test_uncertain_vus_conflicting():
    # Conflicting evidence defaults to VUS
    assert calculate_pathogenicity(['PS1', 'BS1']) == "Uncertain Significance"

# Errors
def test_invalid_code():
    with pytest.raises(ValueError):
        calculate_pathogenicity(['INVALID'])
