"""Interactive nomogram - tkinter (no extra dependencies required).

Run:
    python nomogram_interactive.py

The window shows controls for each predictor and updates the predicted
probability of ypN0 in real time. If streamlit is available, the script
falls back to a streamlit interface; otherwise it uses Tk.
"""

from __future__ import annotations

import math
from pathlib import Path

import pandas as pd

HERE = Path(__file__).resolve().parent
COEF_FILE = HERE.parent / "data" / "nomogram_coefficients.csv"


def load_coef() -> dict:
    df = pd.read_csv(COEF_FILE)
    return dict(zip(df["term"], df["beta"]))


def predict(features: dict, coef: dict) -> float:
    z = coef["intercept"]
    st = features["subtype"]
    if st == "HR-/HER2+":
        z += coef.get("subtype_HR-/HER2+", 0)
    elif st == "HR+/HER2+":
        z += coef.get("subtype_HR+/HER2+", 0)
    elif st == "TNBC":
        z += coef.get("subtype_TNBC", 0)
    if st == "HR+/HER2-":
        ki = features["ki67_cat"]
        if ki == "20_30":
            z += coef.get("ki67_20_30", 0)
        elif ki == "gt30":
            z += coef.get("ki67_gt30", 0)
        if features.get("genomic_high"):
            z += coef.get("genomic_high", 0)
    z += coef.get("age_per_decade", 0) * (features["age"] - 50) / 10
    if features.get("cN23"):
        z += coef.get("cN_stage_cN23", 0)
    if features.get("pembro") and st == "TNBC":
        z += coef.get("regimen_pembro", 0)
    if features.get("pertuzumab") and "HER2+" in st:
        z += coef.get("regimen_pertuzumab", 0)
    if features.get("carbo") and st == "TNBC":
        z += coef.get("regimen_carbo", 0)
    return 1.0 / (1.0 + math.exp(-z))


def run_tk():
    import tkinter as tk
    from tkinter import ttk

    coef = load_coef()
    root = tk.Tk()
    root.title("Nomograma Nivel-2 - ypN0 tras NAST")
    root.geometry("520x540")

    state = dict(subtype=tk.StringVar(value="HR+/HER2-"),
                 ki67_cat=tk.StringVar(value="lt20"),
                 age=tk.IntVar(value=50),
                 cN23=tk.BooleanVar(value=False),
                 pembro=tk.BooleanVar(value=False),
                 pertuzumab=tk.BooleanVar(value=False),
                 carbo=tk.BooleanVar(value=False),
                 genomic_high=tk.BooleanVar(value=False))

    out_lbl = tk.Label(root, text="", font=("Helvetica", 22, "bold"),
                       fg="#c53030")
    detail_lbl = tk.Label(root, text="", font=("Helvetica", 11))

    def refresh(*args):
        feats = dict(subtype=state["subtype"].get(),
                     ki67_cat=state["ki67_cat"].get(),
                     age=int(state["age"].get()),
                     cN23=bool(state["cN23"].get()),
                     pembro=bool(state["pembro"].get()),
                     pertuzumab=bool(state["pertuzumab"].get()),
                     carbo=bool(state["carbo"].get()),
                     genomic_high=bool(state["genomic_high"].get()))
        p = predict(feats, coef)
        out_lbl.config(text=f"P(ypN0) = {p*100:0.1f}%")
        # Risk band
        if p < 0.15:
            band = "Muy bajo"; color = "#9b2c2c"
        elif p < 0.35:
            band = "Bajo"; color = "#c05621"
        elif p < 0.60:
            band = "Intermedio"; color = "#b7791f"
        elif p < 0.80:
            band = "Alto"; color = "#2f855a"
        else:
            band = "Muy alto"; color = "#22543d"
        detail_lbl.config(text=f"Categoria: {band}", fg=color)

    # Layout
    pad = dict(padx=10, pady=4)
    tk.Label(root, text="Subtipo molecular:", anchor="w",
             font=("Helvetica", 10, "bold")).pack(fill="x", **pad)
    for s in ("HR+/HER2-", "TNBC", "HR-/HER2+", "HR+/HER2+"):
        tk.Radiobutton(root, text=s, value=s, variable=state["subtype"],
                       command=refresh).pack(anchor="w", padx=30)

    tk.Label(root, text="Ki67 (solo HR+/HER2-):", anchor="w",
             font=("Helvetica", 10, "bold")).pack(fill="x", **pad)
    for txt, val in (("< 20%", "lt20"), ("20-30%", "20_30"), (">= 30%", "gt30")):
        tk.Radiobutton(root, text=txt, value=val, variable=state["ki67_cat"],
                       command=refresh).pack(anchor="w", padx=30)

    tk.Label(root, text="Edad (anos):", anchor="w",
             font=("Helvetica", 10, "bold")).pack(fill="x", **pad)
    age_sc = tk.Scale(root, from_=25, to=85, orient="horizontal",
                      variable=state["age"], command=refresh)
    age_sc.pack(fill="x", padx=30)

    flag_frame = tk.Frame(root)
    flag_frame.pack(fill="x", **pad)
    tk.Checkbutton(flag_frame, text="cN2-3", variable=state["cN23"],
                   command=refresh).grid(row=0, column=0, sticky="w", padx=8)
    tk.Checkbutton(flag_frame, text="Pembro (TNBC)", variable=state["pembro"],
                   command=refresh).grid(row=0, column=1, sticky="w", padx=8)
    tk.Checkbutton(flag_frame, text="Pertuzumab (HER2+)",
                   variable=state["pertuzumab"],
                   command=refresh).grid(row=1, column=0, sticky="w", padx=8)
    tk.Checkbutton(flag_frame, text="Carboplatino (TNBC)",
                   variable=state["carbo"],
                   command=refresh).grid(row=1, column=1, sticky="w", padx=8)
    tk.Checkbutton(flag_frame, text="Riesgo genomico alto (HR+/HER2-)",
                   variable=state["genomic_high"],
                   command=refresh).grid(row=2, column=0, columnspan=2,
                                         sticky="w", padx=8)

    out_lbl.pack(pady=14)
    detail_lbl.pack()

    tk.Label(root, text=("Fuente: meta-regresion DL random-effects.\n"
                         "van Amstel BJS 2024 (10.1093/bjs/znae203);\n"
                         "Samiei JAMA Surg 2021 (10.1001/jamasurg.2021.0891)."),
             font=("Helvetica", 8), fg="#555").pack(side="bottom", pady=6)

    refresh()
    root.mainloop()


if __name__ == "__main__":
    try:
        run_tk()
    except Exception as e:
        print("Tk failed (no display?):", e)
        # CLI fallback for headless environments
        coef = load_coef()
        feats = dict(subtype="HR-/HER2+", ki67_cat="lt20", age=50,
                     cN23=False, pembro=False, pertuzumab=True,
                     carbo=False, genomic_high=False)
        print("Demo: ", feats, "->", predict(feats, coef))
