"""Streamlit UI for CVOT-MACEAdjudicate-Kor.

참고용 · 연구용 도구입니다. 임상 의사결정용이 아닙니다 (Not for clinical decision).

Run:
    streamlit run app.py
"""

from __future__ import annotations

import io
import os
from collections import Counter
from typing import Any, Dict, List

try:
    import streamlit as st
    import pandas as pd
    import matplotlib.pyplot as plt
except ImportError as e:
    print(
        f"[CVOT-MACEAdjudicate-Kor] Streamlit/pandas/matplotlib not installed: {e}\n"
        "Install dependencies first:\n"
        "    pip install -r requirements.txt\n"
        "Then run: streamlit run app.py"
    )
    raise SystemExit(0)

from modules import ingest, classify, adjudicate, sensitivity


DISCLAIMER = (
    "참고용 · 연구용 도구입니다. 임상 의사결정용이 아닙니다 "
    "(Not for clinical decision)."
)


@st.cache_data(show_spinner=False)
def _load_packets(packets_path: str, troponin_path: str):
    return ingest.load_packets_csv(packets_path, troponin_path)


@st.cache_data(show_spinner=False)
def _load_charter(path: str):
    return ingest.load_charter(path)


@st.cache_data(show_spinner=False)
def _load_judgements(path: str):
    return adjudicate.load_judgements_csv(path)


def main() -> None:
    st.set_page_config(page_title="CVOT-MACEAdjudicate-Kor", layout="wide")
    st.title("CVOT-MACEAdjudicate-Kor")
    st.warning(DISCLAIMER)
    st.caption(
        "T2DM CVOT MACE 의심 사건의 charter-driven 자동 보조 분류 · CEC 2-reader "
        "blinded 워크플로우 · sensitivity analysis · DSMB/CSR 리포트 생성."
    )

    here = os.path.dirname(os.path.abspath(__file__))

    with st.sidebar:
        st.header("입력")
        packets_csv = st.text_input("Event packets CSV", value=os.path.join(here, "data/synthetic_packets.csv"))
        troponin_csv = st.text_input("Troponin time-series CSV", value=os.path.join(here, "data/synthetic_troponin.csv"))
        adj_csv = st.text_input("Adjudications CSV", value=os.path.join(here, "data/synthetic_adjudications.csv"))
        charter_yaml = st.text_input("Charter YAML", value=os.path.join(here, "data/charter_example.yaml"))
        st.divider()
        include_type2 = st.checkbox("Type 2 MI 포함 (charter override)", value=False)

    try:
        raw_packets = _load_packets(packets_csv, troponin_csv)
    except FileNotFoundError:
        st.error(f"Packets CSV not found: {packets_csv}")
        return

    charter = _load_charter(charter_yaml)
    effective_include_type2 = include_type2 or bool(charter.get("include_type2_mi", False))
    packets = ingest.deidentify_all(raw_packets)

    tab1, tab2, tab3, tab4 = st.tabs([
        "1. Ingest / De-ID",
        "2. 자동 분류 보조",
        "3. CEC 2-reader 워크플로우 / Drift",
        "4. Sensitivity + 리포트",
    ])

    with tab1:
        st.subheader(f"Packets: {len(packets)}")
        rows = []
        for p in packets:
            rows.append({
                "event_id": p.event_id,
                "patient_id (hashed)": p.patient_id,
                "site (masked)": p.site_id,
                "event_date (shifted)": p.event_date,
                "age": p.age, "sex": p.sex, "arm": p.treatment_arm,
                "suspected": p.suspected_category,
                "n_troponin_points": len(p.troponin_series),
            })
        st.dataframe(pd.DataFrame(rows), use_container_width=True)
        st.json(charter, expanded=False)

    with tab2:
        st.subheader("자동 보조 분류 (UDM 2018 / AHA / ESC / CV death)")
        results = classify.classify_all(packets, include_type2_mi=effective_include_type2)
        rows = [r.to_dict() for r in results]
        df = pd.DataFrame(rows)
        st.dataframe(df, use_container_width=True)

        # Distribution
        col1, col2 = st.columns(2)
        with col1:
            st.markdown("**Domain 분포**")
            st.bar_chart(df["domain"].value_counts())
        with col2:
            st.markdown("**Label 분포**")
            st.bar_chart(df["label"].value_counts())

        st.session_state["classifications"] = rows

    with tab3:
        st.subheader("2-reader paired blinded adjudication")
        if not os.path.exists(adj_csv):
            st.warning(f"Adjudications CSV not found: {adj_csv}")
            return
        jdgs = _load_judgements(adj_csv)
        adj_summary = adjudicate.summarize(jdgs)
        c1, c2, c3, c4 = st.columns(4)
        c1.metric("Paired events", adj_summary["n_events_paired"])
        c2.metric("Discordance rate", adj_summary["discordance_rate"])
        c3.metric("Overall kappa", adj_summary["overall_kappa"])
        c4.metric("Discordant", adj_summary["n_discordant"])

        st.markdown("**Routing on discordance**")
        st.json(adj_summary.get("routing", {}))

        st.markdown("**Kappa by quarter (drift)**")
        kq = adj_summary.get("kappa_by_quarter", {})
        if kq:
            kq_df = pd.DataFrame({"quarter": list(kq.keys()), "kappa": list(kq.values())})
            st.line_chart(kq_df.set_index("quarter"))

        st.markdown("**Label distribution by quarter**")
        ldist = adj_summary.get("label_distribution_by_quarter", {})
        if ldist:
            labels = sorted({lab for c in ldist.values() for lab in c})
            df_ld = pd.DataFrame(
                [[ldist[q].get(lab, 0) for lab in labels] for q in sorted(ldist)],
                index=sorted(ldist), columns=labels,
            )
            st.bar_chart(df_ld)

        st.markdown("**Workload / turnaround**")
        st.json({
            "workload": adj_summary.get("workload_by_adjudicator", {}),
            "turnaround_h": adj_summary.get("turnaround_h_by_adjudicator", {}),
        })

        st.session_state["adjudication_summary"] = adj_summary

    with tab4:
        st.subheader("Sensitivity analysis")
        cls_dicts = st.session_state.get("classifications")
        if cls_dicts is None:
            results = classify.classify_all(packets, include_type2_mi=effective_include_type2)
            cls_dicts = [r.to_dict() for r in results]
        packet_arms = {p.event_id: p.treatment_arm for p in raw_packets}
        grid = sensitivity.run_sensitivity_grid(cls_dicts, packet_arms)

        rows = []
        for s in grid:
            rows.append({
                "endpoint": s.name,
                "n_total": s.n_total,
                "components": ", ".join(f"{k}={v}" for k, v in s.by_component.items()),
                "by_arm": ", ".join(f"{k}={v}" for k, v in s.by_arm.items()),
            })
        st.dataframe(pd.DataFrame(rows), use_container_width=True)

        st.markdown("**DSMB-ready interim summary**")
        adj_summary = st.session_state.get("adjudication_summary", {})
        dsmb = sensitivity.dsmb_interim_summary(grid, adj_summary)
        st.json(dsmb, expanded=False)

        st.markdown("**CSR/manuscript supplementary report**")
        out_path = st.text_input("Report output path",
                                 value=os.path.join(here, "reports/run.docx"))
        if st.button("Export report"):
            path = sensitivity.export_csr_docx(out_path, grid, adj_summary, charter)
            st.success(f"Saved: {path}")


if __name__ == "__main__":
    main()
