"""Streamlit dashboard for InHospGlyWard-Kor (인합글라이워드코어).

Run:
    streamlit run app.py

  - Ward별 ADA/KDA inpatient TIR radar / bar
  - basal-bolus vs sliding-scale 비율
  - DKA / HHS / Hypo episode trajectory
  - perioperative / steroid / TPN-PN / ER subgroup KPI
  - discharge transition + 30-day readmission KM

본 도구는 참고용·연구용입니다 — 임상 의사결정용 아님.
"""
from __future__ import annotations

import os
import sys

# Lazy import streamlit so this file can still be syntax-checked w/o streamlit.
try:
    import streamlit as st
    import pandas as pd
    import plotly.express as px
    import plotly.graph_objects as go
except Exception as _err:  # pragma: no cover
    print("[InHospGlyWard-Kor] streamlit/plotly/pandas 미설치:", _err)
    print("pip install -r requirements.txt 후 다시 시도하세요.")
    sys.exit(0)

HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)

from modules import ingest, tir, regimen, episode, subgroup, transition, report  # noqa: E402

DATA_DIR = os.path.join(HERE, "data")
DISCLAIMER = ("본 대시보드는 **참고용·연구용**입니다. 임상 의사결정 도구가 아닙니다. "
              "표시된 데이터는 모두 de-identified surrogate (synthetic).")


def ensure_data():
    if not os.path.exists(os.path.join(DATA_DIR, "patients.csv")):
        st.warning("data/ 디렉토리에 CSV가 없습니다 — synthetic data 를 생성합니다.")
        ingest.generate_synthetic(out_dir=DATA_DIR, n_patients=320, seed=42)


@st.cache_data(show_spinner=False)
def load_bundle():
    patients, poct, orders, episodes, irep = ingest.load_all(DATA_DIR)
    return {
        "patients": patients, "poct": poct, "orders": orders,
        "episodes": episodes, "irep": irep,
    }


def page_overview(bundle):
    st.subheader("1. Ward별 ADA/KDA inpatient TIR")
    ward_rows = tir.compute_ward_tir(bundle["patients"], bundle["poct"])
    df = pd.DataFrame([w.__dict__ for w in ward_rows])
    st.dataframe(df, use_container_width=True, hide_index=True)

    fig = px.bar(df, x="ward", y="pct_in_range",
                 color="kda_compliance_score",
                 color_continuous_scale="Viridis",
                 hover_data=["mean_bg", "pct_hypo_l1", "pct_hyper_180"],
                 title="Ward TIR (% in target band)")
    st.plotly_chart(fig, use_container_width=True)

    # radar of TIR / hypo / hyper / persistent
    radar = go.Figure()
    metrics = ["pct_in_range", "pct_hyper_180", "pct_hypo_l1", "kda_compliance_score"]
    for _, row in df.iterrows():
        radar.add_trace(go.Scatterpolar(
            r=[row[m] for m in metrics],
            theta=metrics, fill="toself", name=row["ward"],
        ))
    radar.update_layout(title="Ward KPI radar", polar=dict(radialaxis=dict(visible=True)))
    st.plotly_chart(radar, use_container_width=True)


def page_regimen(bundle):
    st.subheader("2. Ward별 insulin regimen mix")
    rows = regimen.compute_regimen_mix(bundle["patients"], bundle["orders"])
    df = pd.DataFrame([r.__dict__ for r in rows])
    st.dataframe(df, use_container_width=True, hide_index=True)
    stack_cols = ["pct_basal_bolus", "pct_sliding_scale_only",
                  "pct_iv_infusion", "pct_basal_only", "pct_no_insulin"]
    long = df.melt(id_vars=["ward"], value_vars=stack_cols,
                   var_name="regimen", value_name="pct")
    fig = px.bar(long, x="ward", y="pct", color="regimen", barmode="stack",
                 title="Insulin regimen mix per ward (%)")
    st.plotly_chart(fig, use_container_width=True)


def page_episodes(bundle):
    st.subheader("3. DKA / HHS / Hypo / Hyper episode trajectory")
    rows = episode.summarize_episodes(bundle["episodes"])
    df = pd.DataFrame([r.__dict__ for r in rows])
    st.dataframe(df, use_container_width=True, hide_index=True)
    if not df.empty:
        fig = px.bar(df, x="episode_type", y="protocol_compliance_pct",
                     hover_data=["n_total", "resolution_rate", "median_resolution_h"],
                     title="ADA DKA/HHS protocol compliance (%)")
        st.plotly_chart(fig, use_container_width=True)
        fig2 = px.scatter(df, x="median_resolution_h", y="resolution_rate",
                          size="n_total", color="episode_type",
                          title="Resolution rate vs median resolution time")
        st.plotly_chart(fig2, use_container_width=True)


def page_subgroups(bundle):
    st.subheader("4. Subgroup: perioperative / steroid / TPN-PN / ER")
    rows = subgroup.compute_subgroups(bundle["patients"], bundle["poct"])
    df = pd.DataFrame([r.__dict__ for r in rows])
    st.dataframe(df, use_container_width=True, hide_index=True)
    if not df.empty:
        fig = px.bar(df, x="subgroup", y="pct_in_140_180",
                     hover_data=["mean_bg", "pct_hypo_l1", "pct_hyper_250",
                                 "protocol_label", "protocol_compliance_pct"],
                     title="Subgroup 140-180 band coverage (%)")
        st.plotly_chart(fig, use_container_width=True)


def page_transition(bundle):
    st.subheader("5. Discharge transition + 30-day readmission")
    trans = transition.summarize_transition(bundle["patients"])
    cols = st.columns(3)
    cols[0].metric("Total patients", trans.n_total)
    cols[1].metric("30-day readmits", f"{trans.n_readmit_30d} ({trans.readmit_rate_pct}%)")
    cols[2].metric("Median time to readmit (d)", trans.median_time_to_readmit_d)

    st.write("**Discharge regimen mix**", trans.discharge_regimen_mix)
    st.write("**Readmit reason mix**", trans.readmit_reason_mix)

    by_reg = pd.DataFrame(transition.regimen_vs_readmit(bundle["patients"]))
    st.dataframe(by_reg, use_container_width=True, hide_index=True)
    if not by_reg.empty:
        fig = px.bar(by_reg, x="regimen", y="readmit_rate_pct",
                     hover_data=["n", "n_readmit"],
                     title="30-day readmission % by discharge regimen")
        st.plotly_chart(fig, use_container_width=True)

    km = transition.kaplan_meier_30d(bundle["patients"])
    if km:
        km_df = pd.DataFrame(km, columns=["day", "S(t)", "n_at_risk"])
        fig = px.line(km_df, x="day", y="S(t)", markers=True,
                      title="Kaplan-Meier — 30일 내 무재입원 생존")
        st.plotly_chart(fig, use_container_width=True)
        st.dataframe(km_df, use_container_width=True, hide_index=True)


def page_report(bundle):
    st.subheader("6. SHM GCMIP-analog KPI 리포트 (md/docx)")
    lang = st.radio("언어", ["ko", "en"], horizontal=True)
    if st.button("리포트 생성"):
        ward_rows = tir.compute_ward_tir(bundle["patients"], bundle["poct"])
        reg_rows = regimen.compute_regimen_mix(bundle["patients"], bundle["orders"])
        ep_rows = episode.summarize_episodes(bundle["episodes"])
        sub_rows = subgroup.compute_subgroups(bundle["patients"], bundle["poct"])
        trans = transition.summarize_transition(bundle["patients"])
        km = transition.kaplan_meier_30d(bundle["patients"])
        md = report.build_markdown(ward_rows, reg_rows, ep_rows, sub_rows, trans, km, language=lang)
        out_md = os.path.join(HERE, "reports", f"inhospglyward_{lang}.md")
        out_docx = os.path.join(HERE, "reports", f"inhospglyward_{lang}.docx")
        report.write_markdown(out_md, md)
        written = report.write_docx(out_docx, md, title="InHospGlyWard-Kor KPI 리포트")
        st.success(f"생성 완료: md={out_md} / docx={written}")
        st.download_button("MD 다운로드", md, file_name=os.path.basename(out_md))


def main():
    st.set_page_config(page_title="InHospGlyWard-Kor", layout="wide")
    st.title("인합글라이워드코어 (InHospGlyWard-Kor)")
    st.caption("종합병원 입원 환자 glycemic management cohort dashboard")
    st.warning(DISCLAIMER)
    ensure_data()
    bundle = load_bundle()

    tabs = st.tabs([
        "Ward TIR", "Regimen mix", "Episodes",
        "Subgroups", "Discharge & readmit", "Report",
    ])
    with tabs[0]:
        page_overview(bundle)
    with tabs[1]:
        page_regimen(bundle)
    with tabs[2]:
        page_episodes(bundle)
    with tabs[3]:
        page_subgroups(bundle)
    with tabs[4]:
        page_transition(bundle)
    with tabs[5]:
        page_report(bundle)


if __name__ == "__main__":
    main()
