#!/usr/bin/env python3
"""CLI entry point for InHospGlyWard-Kor (인합글라이워드코어).

종합병원 입원 환자 glycemic management cohort dashboard.

Usage:
    python3 main.py --help
    python3 main.py --gen-data --n 320
    python3 main.py --analyze
    python3 main.py --analyze --top 8
    python3 main.py --report --lang ko
    python3 main.py --all                # gen -> analyze -> report

For research / synthetic data only. NOT for clinical decision making.
"""
from __future__ import annotations

# argparse only at top so --help works without heavy deps.
import argparse
import os
import sys
import textwrap

DISCLAIMER = (
    "[InHospGlyWard-Kor] 본 도구는 참고용·연구용입니다 — "
    "임상 의사결정용 아님 (Not for clinical decision)."
)


def _build_parser() -> argparse.ArgumentParser:
    p = argparse.ArgumentParser(
        prog="in-hosp-gly-ward-kor",
        description=(
            "종합병원 입원 환자(MICU/SICU/CCU/NICU/응급실/일반병동) glycemic management "
            "cohort dashboard. ward별 ADA/KDA inpatient TIR · basal-bolus 부합률 · "
            "in-hospital hypoglycemia · DKA/HHS resolution trajectory · 30-day readmission KPI."
        ),
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=textwrap.dedent("""
            Examples:
              python3 main.py --gen-data --n 320 --seed 42
              python3 main.py --analyze --top 8
              python3 main.py --report --lang ko --out reports/inhospglyward_ko.docx
              python3 main.py --all

            For research / synthetic data only. NOT for clinical decision making.
        """).strip(),
    )
    p.add_argument("--gen-data", action="store_true",
                   help="data/ 에 synthetic CSV (patients / poct_bg / insulin_orders / episodes) 생성")
    p.add_argument("--analyze", action="store_true",
                   help="ward별 TIR · regimen mix · episode trajectory · subgroup · readmission 계산")
    p.add_argument("--report", action="store_true",
                   help="SHM GCMIP-analog 한국어/영문 KPI 리포트 생성 (md + docx)")
    p.add_argument("--all", action="store_true",
                   help="gen-data → analyze → report 일괄 실행")
    p.add_argument("--n", type=int, default=320,
                   help="합성 데이터 환자 수 (default: 320)")
    p.add_argument("--seed", type=int, default=42, help="합성 데이터 seed")
    p.add_argument("--data-dir", default="data", help="CSV 입출력 디렉토리")
    p.add_argument("--top", type=int, default=8,
                   help="ward 랭킹 출력 행 수")
    p.add_argument("--lang", choices=["ko", "en"], default="ko",
                   help="리포트 언어")
    p.add_argument("--out", default="reports/inhospglyward_report.docx",
                   help="리포트 출력 경로 (.docx; python-docx 없으면 .md 로 폴백)")
    return p


def _missing_deps_message(err: Exception) -> str:
    return textwrap.dedent(f"""
        [InHospGlyWard-Kor] 의존성 누락: {err}

        가상환경에서 설치 후 다시 시도하세요:
            python3 -m venv .venv
            source .venv/bin/activate
            pip install -r requirements.txt
            python3 main.py --all

        (argparse 만으로 --help 출력은 가능합니다.)
    """).strip()


def _resolve(here: str, p: str) -> str:
    return p if os.path.isabs(p) else os.path.join(here, p)


def cmd_gen_data(args, here: str) -> int:
    from modules.ingest import generate_synthetic
    out_dir = _resolve(here, args.data_dir)
    rep = generate_synthetic(n_patients=args.n, out_dir=out_dir, seed=args.seed)
    print(f"[gen-data] N환자={rep.n_patients}  POCT={rep.n_poct}  orders={rep.n_orders}  episodes={rep.n_episodes}")
    print(f"[gen-data] dir={out_dir}")
    for note in rep.notes:
        print(f"  - {note}")
    return 0


def cmd_analyze(args, here: str):
    from modules import ingest, tir, regimen, episode, subgroup, transition
    data_dir = _resolve(here, args.data_dir)
    if not os.path.exists(os.path.join(data_dir, "patients.csv")):
        print(f"[!] data 없음: {data_dir}/patients.csv — 먼저 --gen-data 실행", file=sys.stderr)
        return None
    patients, poct, orders, episodes, irep = ingest.load_all(data_dir)
    print(f"[ingest] N={irep.n_patients}  POCT={irep.n_poct}  orders={irep.n_orders}  episodes={irep.n_episodes}")
    print(f"[ingest] de-id: {irep.deid_method}")

    ward_tir = tir.compute_ward_tir(patients, poct)
    rank = tir.ward_ranking(ward_tir)
    print(f"\n[ward TIR ranking — top {args.top}] (KDA compliance score)")
    for w, s in rank[: args.top]:
        print(f"  {w:6s}  score={s}")

    reg_mix = regimen.compute_regimen_mix(patients, orders)
    print("\n[ward regimen mix]")
    for r in reg_mix:
        print(f"  {r.ward:6s}  bb={r.pct_basal_bolus}%  ss-only={r.pct_sliding_scale_only}%  "
              f"IV={r.pct_iv_infusion}%  ADA-bb-rate={r.ada_basal_bolus_rate}%")

    ep_summary = episode.summarize_episodes(episodes)
    print("\n[episode trajectory]")
    for e in ep_summary:
        print(f"  {e.episode_type:24s}  N={e.n_total}  resolved={e.resolution_rate}%  "
              f"medRes(h)={e.median_resolution_h}  protoComp={e.protocol_compliance_pct}%")

    sub = subgroup.compute_subgroups(patients, poct)
    print("\n[subgroup KPI]")
    for s in sub:
        print(f"  {s.subgroup:14s}  N={s.n_patients:3d}  mean={s.mean_bg}  "
              f"140-180={s.pct_in_140_180}%  hypo={s.pct_hypo_l1}%  protoComp={s.protocol_compliance_pct}%")

    trans = transition.summarize_transition(patients)
    print("\n[discharge transition]")
    print(f"  total={trans.n_total}  readmit30d={trans.n_readmit_30d} ({trans.readmit_rate_pct}%)  "
          f"medTimeToReadmit={trans.median_time_to_readmit_d}d")
    print(f"  discharge mix={trans.discharge_regimen_mix}")
    print(f"  reasons={trans.readmit_reason_mix}")

    km = transition.kaplan_meier_30d(patients)
    print("\n[Kaplan-Meier (head)]")
    for d, s, n in km[:10]:
        print(f"  day={d:3d}  S(t)={s:.4f}  n_at_risk={n}")

    return {
        "patients": patients,
        "poct": poct,
        "orders": orders,
        "episodes": episodes,
        "ward_tir": ward_tir,
        "regimen_mix": reg_mix,
        "ep_summary": ep_summary,
        "subgroups": sub,
        "transition": trans,
        "km": km,
    }


def cmd_report(args, here: str, pre=None) -> int:
    from modules import report
    bundle = pre or cmd_analyze(args, here)
    if not bundle:
        return 2
    md = report.build_markdown(
        ward_tir=bundle["ward_tir"],
        regimen_mix=bundle["regimen_mix"],
        episodes=bundle["ep_summary"],
        subgroups=bundle["subgroups"],
        transition=bundle["transition"],
        km_rows=bundle["km"],
        language=args.lang,
    )
    out = _resolve(here, args.out)
    md_path = out.rsplit(".", 1)[0] + ".md"
    report.write_markdown(md_path, md)
    written = report.write_docx(out, md, title="InHospGlyWard-Kor KPI 리포트")
    print(f"[report] markdown: {md_path}")
    print(f"[report] docx:     {written}")
    return 0


def main(argv=None) -> int:
    args = _build_parser().parse_args(argv)
    print(DISCLAIMER)
    here = os.path.dirname(os.path.abspath(__file__))

    # If no action chosen → show help-like guidance
    if not any([args.gen_data, args.analyze, args.report, args.all]):
        print("\n사용 예: python3 main.py --all  |  python3 main.py --help")
        return 0

    try:
        if args.all:
            rc = cmd_gen_data(args, here)
            if rc != 0:
                return rc
            bundle = cmd_analyze(args, here)
            if not bundle:
                return 2
            return cmd_report(args, here, pre=bundle)
        if args.gen_data:
            cmd_gen_data(args, here)
        bundle = None
        if args.analyze:
            bundle = cmd_analyze(args, here)
            if not bundle:
                return 2
        if args.report:
            return cmd_report(args, here, pre=bundle)
        return 0
    except ImportError as e:
        print(_missing_deps_message(e))
        return 0
    except FileNotFoundError as e:
        print(f"[!] file missing: {e}", file=sys.stderr)
        return 2


if __name__ == "__main__":
    sys.exit(main())
