"""Protocol-adherence rules for decompensation types.

References (built-in, offline):
- Baveno VII (variceal bleeding, pre-emptive TIPS)
- AASLD 2021 / EASL 2018 (decompensated cirrhosis)
- KASL 2023 (decompensated cirrhosis Korean guideline)
- ICA-AKI / HRS-AKI consensus 2015/2019

For research / QI use only.
"""
from __future__ import annotations
from typing import Dict, Optional


DECOMP_TYPES = ["ascites", "VB", "HE", "HRS-AKI", "SBP", "ACLF", "other"]


def check_ascites(diuretic: bool, albumin_given: bool,
                  large_volume_paracentesis: bool, refractory: bool,
                  tips_considered: bool) -> Dict[str, object]:
    """Ascites refractory: diuretic + LVP + albumin (8 g/L removed) + TIPS evaluation."""
    items = {
        "diuretic_protocol": diuretic,
        "albumin_with_LVP": albumin_given if large_volume_paracentesis else True,
        "TIPS_evaluation_if_refractory": tips_considered if refractory else True,
    }
    score = sum(items.values()) / len(items)
    return {"items": items, "adherence": round(score, 3)}


def check_vb(EBL_done: bool, terlipressin: bool, octreotide: bool,
             nsbb_started: bool, baveno7_pretips: bool,
             high_risk: bool) -> Dict[str, object]:
    """Variceal bleeding: endoscopic band ligation + vasoactive + NSBB +
    Baveno VII pre-emptive TIPS if high risk (Child-B w/ active bleeding or Child-C 10-13)."""
    vasoactive = terlipressin or octreotide
    items = {
        "EBL_within_12h": EBL_done,
        "vasoactive_3_5d": vasoactive,
        "NSBB_secondary_prophylaxis": nsbb_started,
        "preemptive_TIPS_if_highrisk": baveno7_pretips if high_risk else True,
    }
    score = sum(items.values()) / len(items)
    return {"items": items, "adherence": round(score, 3)}


def check_he(west_haven: int, lactulose: bool, rifaximin: bool,
             precipitant_identified: bool) -> Dict[str, object]:
    """HE: lactulose + rifaximin (overt HE >=II) + precipitant search."""
    items = {
        "lactulose": lactulose,
        "rifaximin_if_overt": rifaximin if west_haven >= 2 else True,
        "precipitant_workup": precipitant_identified,
    }
    score = sum(items.values()) / len(items)
    return {"items": items, "adherence": round(score, 3)}


def check_hrs_aki(terlipressin: bool, albumin: bool, vasoactive_alt: bool,
                  kdigo_stage: int) -> Dict[str, object]:
    """HRS-AKI: terlipressin (or norepinephrine) + albumin + KDIGO staging."""
    items = {
        "terlipressin_or_norepi": terlipressin or vasoactive_alt,
        "albumin_1g_per_kg": albumin,
        "KDIGO_staged": kdigo_stage in (1, 2, 3),
    }
    score = sum(items.values()) / len(items)
    return {"items": items, "adherence": round(score, 3)}


def check_sbp(empirical_abx: bool, albumin: bool,
              prophylaxis_started: bool) -> Dict[str, object]:
    """SBP: empirical 3rd-gen cephalosporin + albumin (1.5/1.0 g/kg) + secondary prophylaxis."""
    items = {
        "empirical_abx_within_6h": empirical_abx,
        "albumin_for_renal_protection": albumin,
        "secondary_prophylaxis": prophylaxis_started,
    }
    score = sum(items.values()) / len(items)
    return {"items": items, "adherence": round(score, 3)}


def check_aclf(grade: str, lt_evaluation: bool,
               plasma_exchange: bool, escalation_icu: bool) -> Dict[str, object]:
    """ACLF: LT evaluation; consider plasma exchange/MARS for ACLF-2/3; ICU for ACLF-2/3."""
    needs_lt = grade in ("ACLF-1", "ACLF-2", "ACLF-3")
    high_grade = grade in ("ACLF-2", "ACLF-3")
    items = {
        "LT_evaluation": lt_evaluation if needs_lt else True,
        "ICU_escalation_if_high": escalation_icu if high_grade else True,
        "PE_or_MARS_considered": plasma_exchange if high_grade else True,
    }
    score = sum(items.values()) / len(items)
    return {"items": items, "adherence": round(score, 3)}


def overall_adherence(checks: Dict[str, Dict[str, object]]) -> float:
    """Return mean adherence across non-empty checks."""
    vals = [c["adherence"] for c in checks.values() if c]
    if not vals:
        return 0.0
    return round(sum(vals) / len(vals), 3)
