"""
species_reference.py
====================
RodentCGMTel — species/model 특이적 혈당 reference range 라이브러리.

각 모델별로 일반적인 fasted/fed/random 혈당 범위(mg/dL) 및 TIR(time-in-range) 정의용
타겟 범위를 보유한다. 값은 동물실험 IACUC 데이터 사후분석을 위한 참고 기준이며,
연구실/스트레인 배치별로 달라질 수 있으므로 사용자가 UI에서 overlay/override 가능하다.

출처(참고):
- Andrikopoulos et al., Am J Physiol Endocrinol Metab 2008 (mouse GTT 권고)
- Berglund et al., Diabetes 2008 (C57BL/6 표준)
- Leiter, Diabetes 1981 (db/db, ob/ob)
- Hummel et al., Science 1966 (db/db)
- Hayashi et al., Endocrinology 2002 (KK-Ay)
- Ueda et al., Metabolism 1995 (NZO)
- Furman, Curr Protoc Pharmacol 2015 (STZ T1DM 모델)
- Goto et al., Proc Japan Acad 1975 (GK rat)
- Clark et al., Proc Soc Exp Biol Med 1983 (ZDF)
- Speakman, Cell Metab 2019 (DIO HFD)

DISCLAIMER: 연구·참고용. 임상의사결정용 아님. IACUC 승인 동물실험 데이터 사후 분석용.
"""

# 단위: mg/dL. CGM telemetry는 ISF 기반이므로 본 라이브러리는 동물용 CGM 보정값(plasma equivalent) 기준이다.
# TIR target range: (low, high). hypo cut-off는 mouse 70, rat 60 mg/dL이 통상이며 모델별로 override 한다.

SPECIES_REFERENCE = {
    "C57BL/6J": {
        "species": "mouse",
        "strain_type": "control_lean",
        "fasted_bg": (80, 110),
        "fed_bg": (140, 180),
        "random_bg": (110, 180),
        "tir_target": (80, 180),
        "hypo_threshold": 70,
        "severe_hypo": 50,
        "hyper_threshold": 250,
        "severe_hyper": 300,
        "notes": "표준 야생형 대조. dawn phenomenon 약하게 관찰. nocturnal feeder.",
        "expected_cv_pct": (10, 20),
    },
    "db/db (BKS.Cg-Dock7m+/+ Leprdb)": {
        "species": "mouse",
        "strain_type": "T2DM_obese",
        "fasted_bg": (180, 280),
        "fed_bg": (350, 550),
        "random_bg": (300, 500),
        "tir_target": (80, 250),
        "hypo_threshold": 70,
        "severe_hypo": 50,
        "hyper_threshold": 400,
        "severe_hyper": 500,
        "notes": "Leptin receptor null. 6-8주령에 명확한 hyperglycemia. polyuria/polydipsia.",
        "expected_cv_pct": (15, 30),
    },
    "ob/ob (B6.Cg-Lepob)": {
        "species": "mouse",
        "strain_type": "obese_modest_hyper",
        "fasted_bg": (120, 180),
        "fed_bg": (200, 320),
        "random_bg": (180, 280),
        "tir_target": (80, 250),
        "hypo_threshold": 70,
        "severe_hypo": 50,
        "hyper_threshold": 350,
        "severe_hyper": 450,
        "notes": "Leptin null. 비만은 심하나 hyperglycemia는 db/db보다 약함. age-dependent.",
        "expected_cv_pct": (15, 25),
    },
    "STZ T1DM mouse": {
        "species": "mouse",
        "strain_type": "T1DM_chemical",
        "fasted_bg": (250, 400),
        "fed_bg": (400, 600),
        "random_bg": (350, 550),
        "tir_target": (80, 250),
        "hypo_threshold": 70,
        "severe_hypo": 50,
        "hyper_threshold": 400,
        "severe_hyper": 500,
        "notes": "Streptozotocin multi-low-dose 또는 single-high-dose. β-cell ablation. insulin 의존.",
        "expected_cv_pct": (20, 40),
    },
    "NZO": {
        "species": "mouse",
        "strain_type": "polygenic_T2DM",
        "fasted_bg": (140, 220),
        "fed_bg": (250, 400),
        "random_bg": (200, 350),
        "tir_target": (80, 250),
        "hypo_threshold": 70,
        "severe_hypo": 50,
        "hyper_threshold": 350,
        "severe_hyper": 450,
        "notes": "New Zealand Obese. polygenic obesity + IGT, sex-dependent T2DM 발현.",
        "expected_cv_pct": (15, 25),
    },
    "KK-Ay": {
        "species": "mouse",
        "strain_type": "T2DM_obese",
        "fasted_bg": (150, 240),
        "fed_bg": (300, 500),
        "random_bg": (250, 400),
        "tir_target": (80, 250),
        "hypo_threshold": 70,
        "severe_hypo": 50,
        "hyper_threshold": 400,
        "severe_hyper": 500,
        "notes": "Yellow agouti(Ay) allele on KK. 12-16주령 hyperglycemia. obesity + IR.",
        "expected_cv_pct": (15, 30),
    },
    "Sprague-Dawley (SD)": {
        "species": "rat",
        "strain_type": "control_lean",
        "fasted_bg": (70, 110),
        "fed_bg": (110, 160),
        "random_bg": (90, 150),
        "tir_target": (60, 160),
        "hypo_threshold": 60,
        "severe_hypo": 45,
        "hyper_threshold": 200,
        "severe_hyper": 250,
        "notes": "표준 outbred rat 대조. metabolic study baseline.",
        "expected_cv_pct": (8, 18),
    },
    "Wistar": {
        "species": "rat",
        "strain_type": "control_lean",
        "fasted_bg": (70, 105),
        "fed_bg": (105, 155),
        "random_bg": (85, 145),
        "tir_target": (60, 160),
        "hypo_threshold": 60,
        "severe_hypo": 45,
        "hyper_threshold": 200,
        "severe_hyper": 250,
        "notes": "Wistar outbred rat. SD와 유사한 metabolic profile.",
        "expected_cv_pct": (8, 18),
    },
    "ZDF (Zucker Diabetic Fatty)": {
        "species": "rat",
        "strain_type": "T2DM_obese",
        "fasted_bg": (150, 280),
        "fed_bg": (300, 500),
        "random_bg": (250, 450),
        "tir_target": (60, 250),
        "hypo_threshold": 60,
        "severe_hypo": 45,
        "hyper_threshold": 400,
        "severe_hyper": 500,
        "notes": "Leptin receptor mutation rat. males 발현 강함. 8-10주령 hyperglycemia.",
        "expected_cv_pct": (15, 30),
    },
    "GK (Goto-Kakizaki)": {
        "species": "rat",
        "strain_type": "non_obese_T2DM",
        "fasted_bg": (110, 170),
        "fed_bg": (170, 280),
        "random_bg": (150, 250),
        "tir_target": (60, 220),
        "hypo_threshold": 60,
        "severe_hypo": 45,
        "hyper_threshold": 300,
        "severe_hyper": 400,
        "notes": "Non-obese T2DM rat. β-cell mass 감소. spontaneous IGT.",
        "expected_cv_pct": (12, 22),
    },
    "DIO HFD (C57BL/6J 60% HFD)": {
        "species": "mouse",
        "strain_type": "diet_induced_obese",
        "fasted_bg": (110, 170),
        "fed_bg": (180, 280),
        "random_bg": (150, 240),
        "tir_target": (80, 220),
        "hypo_threshold": 70,
        "severe_hypo": 50,
        "hyper_threshold": 300,
        "severe_hyper": 400,
        "notes": "60% kcal HFD ≥12주. obesity + IR + mild hyperglycemia. T2DM 전구.",
        "expected_cv_pct": (12, 22),
    },
}


# 측정 단위 변환(필요시)
def mgdl_to_mmoll(mgdl: float) -> float:
    """mg/dL → mmol/L (당뇨: 18.0 환산)."""
    return mgdl / 18.0


def mmoll_to_mgdl(mmoll: float) -> float:
    return mmoll * 18.0


# 라이트/다크 사이클 표준 (12:12, lights on 07:00)
DEFAULT_LIGHT_CYCLE = {
    "lights_on_hr": 7,
    "lights_off_hr": 19,
}


# Challenge 표준 프로토콜 (참고치)
CHALLENGE_PROTOCOLS = {
    "GTT_ip": {
        "name": "Intraperitoneal Glucose Tolerance Test",
        "dose_g_per_kg": 2.0,
        "fasting_hr": 6,
        "sampling_minutes": [0, 15, 30, 60, 90, 120],
        "notes": "Andrikopoulos 2008 권고. 마우스 6h fast.",
    },
    "GTT_oral": {
        "name": "Oral Glucose Tolerance Test",
        "dose_g_per_kg": 2.0,
        "fasting_hr": 6,
        "sampling_minutes": [0, 15, 30, 60, 90, 120],
        "notes": "GLP-1 inkretin 반영. gavage.",
    },
    "ITT": {
        "name": "Insulin Tolerance Test",
        "dose_U_per_kg": 0.75,
        "fasting_hr": 4,
        "sampling_minutes": [0, 15, 30, 45, 60, 90],
        "notes": "insulin sensitivity 추정. severe hypo 모니터.",
    },
    "MTT": {
        "name": "Mixed Meal Tolerance Test",
        "dose_kcal_per_kg": 10.0,
        "fasting_hr": 6,
        "sampling_minutes": [0, 15, 30, 60, 90, 120, 180],
        "notes": "physiological postprandial 평가.",
    },
}


def list_models() -> list:
    """등록된 species/model 키 목록."""
    return list(SPECIES_REFERENCE.keys())


def get_reference(model_key: str) -> dict:
    """모델 키에 해당하는 reference dict 반환. 없으면 KeyError."""
    if model_key not in SPECIES_REFERENCE:
        raise KeyError(f"Unknown model: {model_key}. Available: {list_models()}")
    return SPECIES_REFERENCE[model_key]
