import os
import sys
import gc
import time
import streamlit as st



def _bytes_fmt(n: float) -> str:
    for unit in ["B", "KB", "MB", "GB", "TB"]:
        if n < 1024:
            return f"{n:.1f} {unit}"
        n /= 1024
    return f"{n:.1f} PB"

def _get_rss_bytes() -> int:
    # Linux (Streamlit Cloud) sin dependencias extra
    try:
        import resource
        r = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
        # En Linux ru_maxrss está en KB
        if sys.platform.startswith("linux"):
            return int(r * 1024)
        # En macOS suele venir en bytes
        return int(r)
    except Exception:
        pass

    # Fallback: psutil si lo tienes instalado
    try:
        import psutil
        return int(psutil.Process(os.getpid()).memory_info().rss)
    except Exception:
        return -1

def _session_state_size_bytes(limit_items: int = 50) -> tuple[int, list[tuple[str, int]]]:
    """
    Estima tamaño de objetos en session_state (no perfecto, pero muy útil).
    """
    try:
        from sys import getsizeof
        total = 0
        items = []
        for k in list(st.session_state.keys()):
            v = st.session_state.get(k)
            try:
                sz = getsizeof(v)
            except Exception:
                sz = 0
            items.append((str(k), int(sz)))
            total += int(sz)
        items.sort(key=lambda x: x[1], reverse=True)
        return total, items[:limit_items]
    except Exception:
        return 0, []



def show_health_panel(scope: str = "global", compact: bool = True, position: str = "top") -> None:
    """
    Llamar al INICIO de cada sección.
    Muestra RAM, tamaño session_state y un botón de limpieza.
    """
    key_base = f"health|{scope}|{position}"
    rss = _get_rss_bytes()
    ss_total, ss_top = _session_state_size_bytes()

    with st.expander(f"🩺 Health Monitor {('— ' + scope) if scope else ''}", expanded=not compact):
        co1, co2, co3 = st.columns(3)
        with co1:
            st.metric("RAM proceso (RSS)", _bytes_fmt(rss) if rss > 0 else "NA")
        with co2:
            st.metric("Session state aprox", _bytes_fmt(ss_total))
        with co3:
            st.metric("GC counts", str(gc.get_count()))

        st.caption("Esto es diagnóstico. RSS es la RAM real del proceso. Session state es aproximado pero útil para detectar acumulación.")

        if ss_top:
            st.markdown("**Top objetos en session_state (aprox):**")
            st.dataframe(
                [{"key": k, "size": _bytes_fmt(sz)} for k, sz in ss_top],
                hide_index=True,
                use_container_width=True
            )

        colA, colB = st.columns([1, 2])
        with colA:
            if st.button("🧹 Limpiar caches", key=f"{key_base}|btn_clear", width="stretch"):
                # Limpia cache_data (no borra cache_resource)
                try:
                    st.cache_data.clear()
                except Exception:
                    pass
                # Limpia resultados “pesados” típicos (ajusta a tus keys)
                for k in list(st.session_state.keys()):
                    if k.startswith("rec_") or k.endswith("_df") or "df_" in k:
                        st.session_state.pop(k, None)
                gc.collect()
                st.success("Caches limpiados. Re-run…")
                st.rerun()

        with colB:
            st.write("Tip: si RSS sube con cada navegación/filtro, estás acumulando objetos (caches o figuras).")
