import streamlit as st
import pandas as pd
import plotly.express as px
import numpy as np
from functions import get_settings, fetch_itaee_mock, last_common_quarter, compute_qoq, fetch_pib_const_nacional, get_inflacion_anual, get_prev_value,get_prev_value,fmt_pp,inflacion_acumulada,get_yoy_value
from functions import load_gdp_by_sector_csv



st.set_page_config(page_title="Crecimiento económico por estado", page_icon="📈", layout="wide")
with open("design.css", "r", encoding="utf-8") as f:
    st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)

cfg = get_settings()
df_raw, meta = fetch_itaee_mock()
last_q = last_common_quarter(df_raw)
df_qoq = compute_qoq(df_raw)
df_last = df_qoq[df_qoq["periodo"] == last_q].dropna(subset=["qoq_pct"])
view = df_last.copy()

with st.sidebar:
    st.header("Filtros")

    st.divider()
    origen = meta.get("source", "api")
    badge = f'<span class="badge api">Origen: API</span>' if origen=="api" else f'<span class="badge db">Origen: BD</span>'
    st.markdown(badge, unsafe_allow_html=True)
    st.markdown(f"**Último trimestre:** {last_q}")
    st.markdown(f"**Consultado:** {meta.get('fetched_at','')}")


st.title("Datos economicos")

tab1, tab2 = st.tabs(["Datos Macroeconomicos", "Datos Microeconomicos"])

with tab1:
   

    st.markdown("#### PIB nacional – Serie histórica (precios constantes, base 2018)")

    try:
        df_pib = fetch_pib_const_nacional()  # consulta directa API
        # KPI simple (último dato)
        last_row = df_pib.iloc[-1]
        colA, colB = st.columns([4, 1])

        # --- KPIs del último trimestre (reemplaza tu bloque de tarjeta) ---
        # Asegura orden e índice por periodo
        df_pib2 = df_pib.sort_values("period").set_index("period")

        p_last = df_pib2.index[-1]
        v_last = df_pib2.loc[p_last, "value"]

        # Periodos de referencia
        p_prev = p_last - 1   # trimestre previo
        p_yoy  = p_last - 4   # mismo trimestre del año anterior

        # Valores (con fallback si no existen)
        v_prev = df_pib2.loc[p_prev, "value"] if p_prev in df_pib2.index else np.nan
        v_yoy  = df_pib2.loc[p_yoy,  "value"] if p_yoy  in df_pib2.index  else np.nan

        # Cálculos
        qoq = (v_last - v_prev) / v_prev * 100 if np.isfinite(v_prev) and v_prev != 0 else np.nan
        yoy = (v_last - v_yoy) / v_yoy * 100   if np.isfinite(v_yoy)  and v_yoy  != 0 else np.nan

        # Promedio QoQ últimos 4T
        pchg = df_pib2["value"].pct_change() * 100
        prom_qoq_4t = pchg.tail(4).mean() if pchg.tail(4).notna().sum() >= 1 else np.nan

        # Helpers de formato
        def fmt_pct(x):
            return "—" if not np.isfinite(x) else f"{x:+.2f}%"

        def arrow_span(x):
            if not np.isfinite(x): return ""
            arrow = "▲" if x > 0 else ("▼" if x < 0 else "■")
            color = "#16a34a" if x > 0 else ("#ef4444" if x < 0 else "#9ca3af")
            return f'<span style="color:{color};font-weight:700;margin-left:.5rem">{arrow}</span>'
        
        # Helper para mostrar "YYYYTn"
        def _pstr(p):
            # Si ya tienes period_str en df_pib, úsalo; si no, genera a partir de Period
            try:
                return df_pib2.loc[p, "period_str"]
            except Exception:
                return str(p).replace("Q", "T")

        ultimo_periodo = _pstr(p_last)

        # Etiquetas automáticas tipo "2025T2 vs 2025T1" y "2025T2 vs 2024T2"
        label_qoq = f"{_pstr(p_last)} vs {_pstr(p_prev)}" if p_prev in df_pib2.index else "—"
        label_yoy = f"{_pstr(p_last)} vs {_pstr(p_yoy)}"  if p_yoy  in df_pib2.index else "—"


        with colB:
            st.markdown(
                f'''
                <div class="card">
                <h3>Último trimestre</h3>
                <div class="value">{ultimo_periodo}</div>
                <div class="small">Índice: {v_last:.2f}</div>
                <div class="small">{label_qoq}: {fmt_pct(qoq)} {arrow_span(qoq)}</div>
                <div class="small">{label_yoy}: {fmt_pct(yoy)} {arrow_span(yoy)}</div>
                <div class="small">Prom. trimestral (últ. 4T): {fmt_pct(prom_qoq_4t)} {arrow_span(prom_qoq_4t)}</div>
                </div>
                ''',
                unsafe_allow_html=True
            )
       
        with colA:
            # Título dinámico para la gráfica
            last_row = df_pib.iloc[-1]
            ultimo_periodo = last_row["period_str"]
            titulo_pib = (
                f"PIB nacional (trimestral, desestacionalizado, base 2018=100) — Último trimestre: {ultimo_periodo}"
            )
             # Gráfica histórica
            fig_pib = px.line(
                df_pib,
                x="date", y="value",
                labels={"date": "Fecha (fin de trimestre)", "value": "Índice (2018=100)"},
                title= titulo_pib
            )
            fig_pib.update_traces(mode="lines+markers")
            fig_pib.update_layout(margin=dict(l=10, r=10, t=40, b=10))
            st.plotly_chart(fig_pib, use_container_width=True)

        st.caption("Fuente: INEGI (BIE). Consulta directa en tiempo real")
    except Exception as e:
        st.warning(f"No se pudo consultar el PIB nacional desde INEGI: {e}")



    st.divider()
    st.markdown("#### PIB por actividad económica (trimestral) — Serie histórica")

    # Ruta a tu CSV (puedes ponerla fija o exponer un input)
    path_csv = r"C:\Users\julio\OneDrive\Documentos\Trabajo\Ideas Frescas\Proyectos\Economics_data\Data\Producto-interno-bruto-trimestral-actividad-economica.csv"

    # # Selector de columna de valor
    # col_val = st.selectbox("Columna de valor a graficar", options=["GDP", "Time"], index=0)

    try:

        f1, f2 = st.columns(2)
        df_sect = load_gdp_by_sector_csv(path_csv, value_col='GDP')

        # Heurística: si los valores son muy grandes (>= 1e12), mostramos en miles de millones
        if df_sect["value"].max() >= 1e12:
            df_sect["value_plot"] = df_sect["value"] / 1e9
            y_col = "value_plot"
            y_lab = "PIB (miles de millones MXN)"
        else:
            y_col = "value"
            y_lab = "PIB (MXN)"

        # Ordenar leyenda por contribución en el último trimestre
        last_q = df_sect["period"].max()
        contrib = (df_sect[df_sect["period"] == last_q]
                .groupby("Sector")[y_col].sum()
                .sort_values(ascending=False))
        order = contrib.index.tolist()

        # Gráfica stacked area
        fig = px.area(
            df_sect,
            x="date", y=y_col, color="Sector",
            category_orders={"Sector": order},
            labels={"date": "Fecha (fin de trimestre)", y_col: y_lab, "Sector": "Sector"},
            title=f"PIB trimestral por actividad — último: {str(last_q).replace('Q','T')}",
)

        # --- 1) Leyenda abajo, horizontal ---
        fig.update_layout(
            height=480,
            margin=dict(l=10, r=180, t=60, b=40),
            hovermode="x unified", 
            xaxis=dict(
                tickformat="%Y-%m",
                title=None,
                showspikes=True,
                spikemode="across",
                spikesnap="cursor",
                spikedash="dot",
                spikecolor="rgba(150,150,150,0.5)"
            ),
            yaxis=dict(
                title=y_lab,
                tickprefix="$" if "MXN" in y_lab else "",
                separatethousands=True,
                hoverformat="$.2f",
            ),
            legend=dict(
                title="Sectores",
                orientation="v",        # vertical
                yanchor="middle", y=0.5,
                xanchor="left", x=1.02, # al lado derecho fuera del gráfico
                bgcolor="rgba(0,0,0,0)",
                itemsizing="trace"
            ),
            legend_itemclick="toggle",
            legend_itemdoubleclick="toggleothers"
        )
        # Crea una etiqueta de trimestre tipo 2024-T2 (si ya tienes 'period', úsalo)
        if "period" in df_sect.columns:
            df_sect["quarter_label"] = df_sect["period"].astype(str).str.replace("Q", "T", regex=False)
        else:
            # derivar desde la fecha
            q = pd.PeriodIndex(pd.to_datetime(df_sect["date"], errors="coerce"), freq="Q")
            df_sect["quarter_label"] = q.astype(str).str.replace("Q", "T", regex=False)

        
        # Función para abreviar nombres largos en hover (por ejemplo >25 caracteres)
        def acorta(texto, n=25):
            return texto if len(texto) <= n else texto[:n] + "…"

        for tr in fig.data:
            # Nombre completo del sector
            sector_name = tr.name

            # Serie de ese sector en el mismo orden temporal de la traza
            serie = df_sect[df_sect["Sector"] == sector_name].sort_values("date")

            # Etiqueta de trimestre tipo 2024-T2
            sector_quarters = serie["quarter_label"].values

            # --- Leyenda abreviada ---
            tr.name = acorta(sector_name, n=15)   # <--- aquí se acorta el nombre para la leyenda

            # --- Hover con nombre completo ---
            custom = np.column_stack([
                np.repeat(sector_name, len(serie)),   # completo para hover
                sector_quarters
            ])
            tr.customdata = custom

            tr.hovertemplate = (
                "<b>%{customdata[0]}</b><br>"         # Sector completo
                "Trimestre: %{customdata[1]}<br>"
                f"{y_lab}: $%{{y:,.2f}}"
                "<extra></extra>"
            )
        with f1:
            st.plotly_chart(fig, use_container_width=True)

        # Tabla resumen del último trimestre (top 10 sectores)
    
        top_df = contrib.reset_index().rename(columns={"index": "Sector", y_col: y_lab})
        top_df[y_lab] = top_df[y_lab].map(lambda v: f"{v:,.2f}")

        # ---------------- Top sectores (último trimestre) con Δ comparativas ----------------
        # Periodos de comparación
        p_last = last_q
        p_prev = p_last - 1   # t-1
        p_yoy1 = p_last - 4   # t-4 (año pasado)
        p_yoy2 = p_last - 8   # t-8 (hace dos años)

        # Pivot a matriz sectores x periodos con el valor (suma por si hay duplicados)
        periods_needed = [p_last, p_prev, p_yoy1, p_yoy2]
        mat = (
            df_sect[df_sect["period"].isin(periods_needed)]
            .pivot_table(index="Sector", columns="period", values=y_col, aggfunc="sum")
        )

        # Helper de % variación
        def pct_change(curr, base):
            if pd.isna(curr) or pd.isna(base) or base == 0:
                return np.nan
            return (curr - base) / base * 100.0

        # Construimos tabla final
        col_qoq = f"{str(p_last).replace('Q','T')} vs {str(p_prev).replace('Q','T')}"
        col_yoy = f"{str(p_last).replace('Q','T')} vs {str(p_yoy1).replace('Q','T')}"
        col_y2y = f"{str(p_last).replace('Q','T')} vs {str(p_yoy2).replace('Q','T')}"

        curr_vals = mat.get(p_last)  # Serie por sector con el valor del último trimestre

        top_df = pd.DataFrame({
            "Sector": mat.index,
            y_lab: curr_vals,  # valor del último trimestre
            col_qoq: [
                pct_change(mat.loc[s, p_last], mat.loc[s, p_prev]) if p_prev in mat.columns else np.nan
                for s in mat.index
            ],
            col_yoy: [
                pct_change(mat.loc[s, p_last], mat.loc[s, p_yoy1]) if p_yoy1 in mat.columns else np.nan
                for s in mat.index
            ],
            col_y2y: [
                pct_change(mat.loc[s, p_last], mat.loc[s, p_yoy2]) if p_yoy2 in mat.columns else np.nan
                for s in mat.index
            ]
        })

        # Ordena por tamaño del último trimestre (desc)
        top_df = top_df.sort_values(by=y_lab, ascending=False)

        # Formatos bonitos
        top_df[y_lab] = top_df[y_lab].map(lambda v: f"{v:,.2f}")
        for col in [col_qoq, col_yoy, col_y2y]:
            top_df[col] = top_df[col].map(lambda x: "—" if pd.isna(x) else f"{x:+.2f}%")

        with f2:
            st.markdown("**Top sectores (último trimestre)**")
            st.dataframe(top_df.head(10), use_container_width=True)

    except Exception as e:
        st.warning(f"No se pudo cargar el CSV o limpiar los datos: {e}")
        st.caption("Verifica la ruta del archivo, permisos de lectura y que existan las columnas 'Sector'/'Quarter'/'GDP'/'Time'.")


   
    # ================= INFLACIÓN =================
    st.divider()
    settings = get_settings()
    # st.header("Inflación anual (INPC)")

    try:
        df_inflacion = get_inflacion_anual(settings["BANXICO_TOKEN"])  # consulta directa API
        df_inflacion.rename(columns={"Fecha": "date", "Valor": "Inflacion"}, inplace=True)
        df_inflacion = df_inflacion[df_inflacion["date"]>="2005-01-01"].copy()
        last_row = df_inflacion.iloc[-1]

        c1, c2 = st.columns([4, 1])
        with c2:
            # --- Datos ordenados -----------------------------------------
            df = df_inflacion.copy()
            df = df.dropna(subset=["date", "Inflacion"])
            df["date"] = pd.to_datetime(df["date"])
            df_sorted = df.sort_values("date").reset_index(drop=True)

            # Último registro
            last_row = df_sorted.iloc[-1]
            last_date = last_row["date"]
            last_val = float(last_row["Inflacion"])

            # Variación vs mes anterior y vs mismo mes del año pasado (p.p.)
            prev_val = get_prev_value(df_sorted, last_date)
            yoy_val = get_yoy_value(df_sorted, last_date)

            delta_mom_pp = (last_val - prev_val) if prev_val is not None else None
            delta_yoy_pp = (last_val - yoy_val) if yoy_val is not None else None

            # (Opcional) Promedio del último año calendario móvil
            one_year_ago = last_date - pd.DateOffset(years=1)
            mask_last_year = (df_sorted["date"] > one_year_ago) & (df_sorted["date"] <= last_date)
            infl_prom_ult_anio = df_sorted.loc[mask_last_year, "Inflacion"].mean()

            # --- Tarjeta HTML (estilos mínimos) --------------------------
            st.markdown("""
            <style>
            .card {
            background: #111827; /* gris muy oscuro */
            color: white;
            padding: 16px;
            border-radius: 16px;
            border: 1px solid #1f2937;
            }
            .card h3 { margin: 0 0 8px 0; font-size: 1.1rem; font-weight: 600; color: #93c5fd; }
            .card .value { font-size: 2rem; font-weight: 700; margin-bottom: 2px; }
            .card .small { font-size: 0.95rem; color: #d1d5db; }
            .card .muted { font-size: 0.9rem; color: #9ca3af; margin-top: 6px; }
            .card .row { display: flex; gap: 12px; margin-top: 6px; }
            .badge {
            display: inline-block; padding: 2px 8px; border-radius: 9999px;
            background: #1f2937; border: 1px solid #374151; font-size: 0.85rem;
            }
            .up { color: #34d399; }   /* verde */
            .down { color: #f87171; } /* rojo */
            .na { color: #9ca3af; }
            </style>
            """, unsafe_allow_html=True)

            mom_str = '<span class="na">s/d</span>' if delta_mom_pp is None else \
                    f'<span class="{"up" if delta_mom_pp>=0 else "down"}">{fmt_pp(delta_mom_pp)}</span>'
            yoy_str = '<span class="na">s/d</span>' if delta_yoy_pp is None else \
                    f'<span class="{"up" if delta_yoy_pp>=0 else "down"}">{fmt_pp(delta_yoy_pp)}</span>'

            st.markdown(
                f'''
                <div class="card">
                <h3>Último año</h3>
                <div class="value">{last_date.year}</div>
                <div class="small">Inflación mensual (último dato): <b>{last_val:.2f}%</b></div>
                <div class="row">
                    <div class="badge">Δ vs mes anterior: {mom_str}</div>
                    <div class="badge">Δ vs mismo mes año pasado: {yoy_str}</div>
                </div>
                <div class="muted">Inflación promedio últimos 12 meses: <b>{infl_prom_ult_anio:.2f}%</b></div>
                </div>
                ''',
                unsafe_allow_html=True
            )

                # --- Calculadora de Inflación Acumulada ----------------------
            st.markdown("**Calculadora de inflación acumulada**")
            min_dt = df_sorted["date"].min().date()
            max_dt = df_sorted["date"].max().date()

            a1, a2 = st.columns(2)
           # Construimos lista de meses disponibles (primer día de cada mes)
            min_month = pd.Timestamp(min_dt).replace(day=1)
            max_month = pd.Timestamp(max_dt).replace(day=1)
            meses = pd.date_range(min_month, max_month, freq="MS")

            MESES_ES = [
                "enero","febrero","marzo","abril","mayo","junio",
                "julio","agosto","septiembre","octubre","noviembre","diciembre"
            ]
            labels = [f"{MESES_ES[d.month-1].capitalize()} {d.year}" for d in meses]
            label2date = dict(zip(labels, meses))

            # Selector de rango (mes–año) sin día
            ini_label, fin_label = st.select_slider(
                "Rango (mes–año)",
                options=labels,
                value=(labels[0], labels[-1]),
            )

            # Convertimos a fechas (primer día del mes)
            fecha_ini = label2date[ini_label].date()
            fecha_fin = label2date[fin_label].date()

            # Validación
            if fecha_ini > fecha_fin:
                st.error("La fecha inicial no puede ser mayor a la fecha final.")
            else:
                # Usa fecha_ini y fecha_fin como antes.
                # OJO: si compones inflación mensual, el filtro estándar es:
                # (date > fecha_ini) & (date <= fecha_fin)
                periodo = df_sorted[(df_sorted["date"] > pd.to_datetime(fecha_ini)) &
                                    (df_sorted["date"] <= pd.to_datetime(fecha_fin))]


                acc = inflacion_acumulada(periodo)

                st.markdown(
                    f"""
                    **Rango seleccionado:** {pd.to_datetime(fecha_ini).strftime('%Y-%m')} → {pd.to_datetime(fecha_fin).strftime('%Y-%m')}  
                    **Meses considerados:** {len(periodo)}  
                    **Inflación acumulada:** <span style="font-weight:700">{acc:.2f}%</span>
                    """,
                    unsafe_allow_html=True
                )
        with c1:
            fig_inflacion = px.line(
                df_inflacion,
                x="date", y="Inflacion",
                labels={"date": "Año", "Inflacion": "Inflación anual (%)"},
                title="Inflación anual en México (INPC)"
            )
            fig_inflacion.update_traces(mode="lines+markers")
            fig_inflacion.update_layout(margin=dict(l=10, r=10, t=40, b=10))
            st.plotly_chart(fig_inflacion, use_container_width=True)

        st.caption(
            "**¿Qué es el INPC?:** El Índice Nacional de Precios al Consumidor (INPC) mide la variación de los precios "
            "de una canasta de bienes y servicios representativa del consumo de los hogares mexicanos. "
            "Estos datos permiten analizar la inflación y sus efectos en el poder adquisitivo."
        )

    except Exception as e:
        st.warning(f"No se pudo consultar el INPC desde INEGI: {e}")

    





























    st.caption("ITAEE base 2018 — variación trimestral desestacionalizada")
    col1, col2, col3,= st.columns([1,1,1])
    if not view.empty:
        top_plus = view.sort_values("qoq_pct", ascending=False).iloc[0]
        top_minus = view.sort_values("qoq_pct", ascending=True).iloc[0]
        mediana = view["qoq_pct"].median()
        cobertura = view["estado"].nunique()

        with col1:
            st.markdown('<div class="card"><h3>Top + crecimiento</h3>'
                        f'<div class="value">{top_plus["estado"]}</div>'
                        f'<div class="small">{top_plus["qoq_pct"]:.2f}% </div></div>', unsafe_allow_html=True)
        with col2:
            st.markdown('<div class="card"><h3>Top − crecimiento</h3>'
                        f'<div class="value">{top_minus["estado"]}</div>'
                        f'<div class="small">{top_minus["qoq_pct"]:.2f}% </div></div>', unsafe_allow_html=True)
        with col3:
            st.markdown('<div class="card"><h3>Mediana nacional</h3>'
                        f'<div class="value">{mediana:.2f}%</div>'
                        f'<div class="small">Δ trimestral</div></div>', unsafe_allow_html=True)
    st.subheader("Barras comparadas")
    fig = px.bar(view.sort_values("qoq_pct"), x="estado", y="qoq_pct",
                labels={"estado":"Estado","qoq_pct":"Crecimiento%"},
                text=view.sort_values("qoq_pct")["qoq_pct"].map(lambda v: f"{v:.2f}%"))
    fig.update_traces(textposition="outside")
    fig.update_layout(margin=dict(l=10,r=10,t=30,b=10))
    st.plotly_chart(fig, use_container_width=True)


with tab2:
    st.subheader("Mapa de proyectos")
    st.write("Aquí va tu mapa con folium o plotly…")



st.caption("Nota: datos de ejemplo (mock). Reemplaza fetch_itaee_mock() por consulta real a INEGI o BD.")











