"""Subgroup KPI: perioperative / steroid / TPN-PN / ER immediate glycemia.

References (참고):
  - NICE-SUGAR (NEJM 2009) — IV insulin target 144-180 in critically ill
  - DIGAMI / GIK protocols — perioperative glycemia in cardiac
  - ADA perioperative recommendation 140-180

이 모듈은 참고용·연구용.
"""
from __future__ import annotations

from collections import defaultdict
from dataclasses import dataclass
from typing import Dict, Iterable, List

from .ingest import Patient, POCTReading


@dataclass
class SubgroupKPI:
    subgroup: str               # "perioperative" / "steroid" / "TPN-PN" / "ER"
    n_patients: int
    n_readings: int
    mean_bg: float
    pct_in_140_180: float
    pct_hypo_l1: float
    pct_hyper_250: float
    protocol_label: str
    protocol_compliance_pct: float


def _mean(xs):
    return sum(xs) / len(xs) if xs else 0.0


def _build_groups(patients: List[Patient]) -> Dict[str, List[str]]:
    groups: Dict[str, List[str]] = defaultdict(list)
    for p in patients:
        if p.perioperative:
            groups["perioperative"].append(p.patient_id)
        if p.steroid_exposure:
            groups["steroid"].append(p.patient_id)
        if p.tpn_pn:
            groups["TPN-PN"].append(p.patient_id)
        if p.ward == "ER":
            groups["ER"].append(p.patient_id)
    return groups


def compute_subgroups(patients: Iterable[Patient],
                      poct: Iterable[POCTReading]) -> List[SubgroupKPI]:
    patients = list(patients)
    poct = list(poct)
    groups = _build_groups(patients)

    by_pid_readings: Dict[str, List[POCTReading]] = defaultdict(list)
    for r in poct:
        by_pid_readings[r.patient_id].append(r)

    protocol_labels = {
        "perioperative": "ADA perioperative 140-180 / DIGAMI",
        "steroid": "ADA steroid-induced glycemia 140-180",
        "TPN-PN": "ADA TPN/PN 140-180 (IV insulin add-on or sep.)",
        "ER": "ER immediate glycemia 140-180 / NICE-SUGAR",
    }

    out: List[SubgroupKPI] = []
    for grp, pids in groups.items():
        readings = [r for pid in pids for r in by_pid_readings.get(pid, [])]
        vals = [r.glucose_mg_dl for r in readings]
        n = len(vals) or 1
        in_band = sum(1 for v in vals if 140 <= v <= 180)
        hypo = sum(1 for v in vals if v < 70)
        hyper = sum(1 for v in vals if v > 250)
        pct_in = 100 * in_band / n
        # compliance heuristic — must keep in-band ≥ 50%, hypo < 5%, severe hyper < 10%
        compliant = pct_in >= 50 and (100 * hypo / n) < 5 and (100 * hyper / n) < 10
        out.append(SubgroupKPI(
            subgroup=grp,
            n_patients=len(pids),
            n_readings=len(vals),
            mean_bg=round(_mean(vals), 1),
            pct_in_140_180=round(pct_in, 1),
            pct_hypo_l1=round(100 * hypo / n, 2),
            pct_hyper_250=round(100 * hyper / n, 1),
            protocol_label=protocol_labels.get(grp, ""),
            protocol_compliance_pct=100.0 if compliant else round(pct_in, 1),
        ))
    return sorted(out, key=lambda x: x.subgroup)
