# app.py
import streamlit as st
import pandas as pd
from pathlib import Path

# ---------------------------
# Configuración general
# ---------------------------
st.set_page_config(page_title="Dashboard Mazatlán", layout="wide")
st.title("Dashboard Mazatlán")
st.caption("REM - Julio 2025")

# ---------------------------
# Utilidades
# ---------------------------
@st.cache_data
def list_sheets(xls_path: Path):
    import openpyxl
    wb = openpyxl.load_workbook(xls_path, read_only=True, keep_vba=True, data_only=True)
    return [ws.title for ws in wb.worksheets]

@st.cache_data
def read_sheet(xls_path: Path, sheet_name: str) -> pd.DataFrame:
    return pd.read_excel(xls_path, sheet_name=sheet_name, engine="openpyxl")


def kpi_grid(values: dict):
    if not values:
        st.info("KPIs pendientes de conectar.")
        return
    cols = st.columns(min(4, len(values)))
    for i, (label, val) in enumerate(values.items()):
        with cols[i % len(cols)]:
            st.metric(label=label, value=f"{val:,.2f}")

data_path = Path(r"C:\Users\julio\OneDrive\Desktop\BD_Mazatlan.xlsm")

# Validación de archivo
if not data_path.exists():
    st.error(f"No se encontró el archivo en: {data_path.resolve()}")
    st.stop()

# Carga de hojas (para selecciones rápidas en cada tab)
sheets = list_sheets(data_path)


tab_oferta, tab_demanada = st.tabs(["Oferta"," Demanda"])

with tab_oferta:
    # ---------------------------
    # Tabs principales
    # ---------------------------
    tab_vertical, tab_horizontal, tab_lote, tab_zonas = st.tabs(["Vertical", "Horizontal", "Lote", "Zonas"])

    # ---------------------------
    # TAB: Vertical
    # ---------------------------
    with tab_vertical:
        df_v = read_sheet(data_path, "Vertical")

        # ---------------------------
        # Desarrollos que "entran" (mes actual y los 2 anteriores)
        # ---------------------------
        

        col_fecha = "Fecha_inicio_venta"
        if col_fecha not in df_v.columns:
            st.warning(f"No se encontró la columna **{col_fecha}** en la hoja seleccionada.")
        else:
            dft = df_v.copy()
            dft[col_fecha] = pd.to_datetime(dft[col_fecha], errors="coerce")

            hoy = pd.Timestamp.today().normalize()
            mes_actual = hoy.to_period("M")
            inicio_ventana = (mes_actual - 3).to_timestamp(how="start")   # primer día de hace 2 meses
            fin_ventana    = mes_actual.to_timestamp(how="end")           # último día del mes actual

            mask = (dft[col_fecha] >= inicio_ventana) & (dft[col_fecha] <= fin_ventana)
            df_entran = dft.loc[mask].sort_values(col_fecha)

            # Columnas de nombre posibles (ajusta si tu Excel tiene otro encabezado)
            posibles_nombre = [c for c in ["Desarrollo", "Proyecto", "Nombre", "Nombre_desarrollo"] if c in df_entran.columns]
            mostrar_cols = [col_fecha] + posibles_nombre
            mostrar_cols = list(dict.fromkeys(mostrar_cols))  # dedupe

            # Detecta columna de nombre una vez
            col_nombre = None
            for c in ["Desarrollo", "Proyecto", "Nombre", "Nombre_desarrollo"]:
                if c in df_v.columns:
                    col_nombre = c
                    break

            c1, c2 = st.columns(2)
 

            # -------------------------
            # Columna izquierda: ENTRAN
            # -------------------------
            with c1:
                st.markdown(f"### Desarrollos que **entraron** ({inicio_ventana.date()} → {fin_ventana.date()})")

                if col_nombre is None:
                    st.warning("No se encontró ninguna columna de nombre de desarrollo.")
                else:
                    st.metric("Desarrollos que entran", len(df_entran))

                    if len(df_entran) == 0:
                        st.write("No hay desarrollos nuevos")
                    else:
                        # Lista formateada: nombre — fecha — zona
                        for _, fila in df_entran.sort_values(col_fecha).iterrows():
                            nombre = str(fila[col_nombre])
                            fecha = fila[col_fecha]
                            zona = fila["Zona"] if "Zona" in df_entran.columns else "—"
                            fecha_str = fecha.strftime("%b-%Y") if pd.notna(fecha) else "—"
                            st.write(f"• {nombre} — *{fecha_str}* — **{zona}**")

            # -------------------------
            # Columna derecha: VENDIDOS
            # -------------------------
            with c2:
                st.markdown(f"### Desarrollos **vendidos** ({inicio_ventana.date()} → {fin_ventana.date()})")

                col_fin = "Fecha_fin_ventas"
                if col_fin not in df_v.columns:
                    st.warning(f"No se encontró la columna **{col_fin}** en la hoja seleccionada.")
                else:
                    df_fin = df_v.copy()
                    df_fin[col_fin] = pd.to_datetime(df_fin[col_fin], errors="coerce")

                    mask_fin = (df_fin[col_fin] >= inicio_ventana) & (df_fin[col_fin] <= fin_ventana)
                    df_vendidos = df_fin.loc[mask_fin]

                    st.metric("Desarrollos vendidos", len(df_vendidos))

                    if len(df_vendidos) == 0:
                        st.write("No hay desarrollos vendidos")
                    else:
                        for _, fila in df_vendidos.sort_values(col_fin).iterrows():
                            nombre = str(fila[col_nombre]) if col_nombre else "—"
                            fecha = fila[col_fin]
                            zona = fila["Zona"] if "Zona" in df_vendidos.columns else "—"
                            fecha_str = fecha.strftime("%b-%Y") if pd.notna(fecha) else "—"
                            st.write(f"• {nombre} — *{fecha_str}* — **{zona}**")

            # --- Configuración columnas ---
            import plotly.graph_objects as go

            # ---- Config columnas ----
            COL_INICIO = "Fecha_inicio_venta"
            COL_FIN    = "Fecha_fin_ventas"

            # ---- Limpieza y coerción de fechas ----
            dft = df_v.copy()
            for c in [COL_INICIO, COL_FIN]:
                if c in dft.columns:
                    dft[c] = pd.to_datetime(dft[c], errors="coerce", dayfirst=True)

            # ---- Rango temporal: desde la 1ª fecha de inicio hasta (max(fecha_fin, hoy)) ----
            hoy = pd.Timestamp.today().normalize()
            min_inicio = dft[COL_INICIO].dropna().min()
            max_techo  = pd.Series([
                dft[COL_FIN].dropna().max() if COL_FIN in dft.columns else hoy,
                hoy
            ]).max()

            if pd.isna(min_inicio):
                st.warning("No hay fechas válidas en 'Fecha_inicio_venta'.")
            else:
                idx_m = pd.period_range(min_inicio.to_period("M"), max_techo.to_period("M"), freq="M").to_timestamp()

                # ---- Activos por mes (intervalo vs mes) ----
                activos_rows = []
                for mes_ini in idx_m:
                    mes_fin = mes_ini.to_period("M").to_timestamp(how="end")
                    mask_activo = (
                        (dft[COL_INICIO] <= mes_fin) &
                        (dft[COL_FIN].isna() | (dft[COL_FIN] >= mes_ini))
                    )
                    activos_rows.append({"mes": mes_ini, "activos": int(mask_activo.sum())})

                df_activos = pd.DataFrame(activos_rows).sort_values("mes")

                # ---- % crecimiento mes a mes ----
                df_activos["crec_mom_pct"] = df_activos["activos"].pct_change() * 100
                # Opcional: mostrar 0% en el primer mes en lugar de NaN
                # df_activos["crec_mom_pct"].fillna(0, inplace=True)

            # --- Layout 2×2 ---
            c1, c2 = st.columns(2)
            c3, c4 = st.columns(2)

            # Q1: Histórico de proyectos activos
            with c1:
                st.markdown("#### Proyectos **activos** y **% crecimiento**")

                fig = go.Figure()

                # Activos (eje izquierdo)
                fig.add_trace(go.Scatter(
                    x=df_activos["mes"],
                    y=df_activos["activos"],
                    name="Activos",
                    mode="lines+markers",
                    yaxis="y1"
                ))

                # % Crecimiento (eje derecho)
                fig.add_trace(go.Scatter(
                    x=df_activos["mes"],
                    y=df_activos["crec_mom_pct"],
                    name="% Crecimiento MoM",
                    mode="lines+markers",
                    yaxis="y2"
                ))

                fig.update_layout(
                    margin=dict(l=10, r=10, t=10, b=10),
                    legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
                    xaxis=dict(title="Mes"),
                    yaxis=dict(title="Proyectos activos"),
                    yaxis2=dict(title="% crecimiento MoM", overlaying="y", side="right", tickformat=".1f"),
            hovermode="x unified"
                )

                st.plotly_chart(fig, use_container_width=True)

                # (Opcional) tabla resumen debajo
                #st.dataframe(df_activos, use_container_width=True)
            
            # Q2–Q4: Placeholders (los llenamos cuando definas métricas/columnas)
            with c2:
                st.markdown("#### Entraron vs Vendidos (mensual)")
                st.info("Pendiente: definimos columnas para conteo mensual y renderizamos barras apiladas.")

            with c3:
                st.markdown("#### Inventario activo (mensual)")
                st.info("Pendiente: define columna de inventario (unidades/m²) y agregación mensual.")

            with c4:
                st.markdown("#### Precio / ticket promedio (mensual)")
                st.info("Pendiente: define columna de precio y agregación mensual (mean).")




    # ---------------------------
    # TAB: Horizontal
    # ---------------------------
    with tab_horizontal:
        

        df_h = read_sheet(data_path, "Horizontal")

        # ---------------------------
        # Desarrollos que "entran" (mes actual y los 2 anteriores)
        # ---------------------------
        

        col_fecha = "Fecha_inicio_venta"
        if col_fecha not in df_h.columns:
            st.warning(f"No se encontró la columna **{col_fecha}** en la hoja seleccionada.")
        else:
            dft = df_h.copy()
            dft[col_fecha] = pd.to_datetime(dft[col_fecha], errors="coerce")

            hoy = pd.Timestamp.today().normalize()
            mes_actual = hoy.to_period("M")
            inicio_ventana = (mes_actual - 3).to_timestamp(how="start")   # primer día de hace 2 meses
            fin_ventana    = mes_actual.to_timestamp(how="end")           # último día del mes actual

            mask = (dft[col_fecha] >= inicio_ventana) & (dft[col_fecha] <= fin_ventana)
            df_entran = dft.loc[mask].sort_values(col_fecha)

            # Columnas de nombre posibles (ajusta si tu Excel tiene otro encabezado)
            posibles_nombre = [c for c in ["Desarrollo", "Proyecto", "Nombre", "Nombre_desarrollo"] if c in df_entran.columns]
            mostrar_cols = [col_fecha] + posibles_nombre
            mostrar_cols = list(dict.fromkeys(mostrar_cols))  # dedupe

            # Detecta columna de nombre una vez
            col_nombre = None
            for c in ["Desarrollo", "Proyecto", "Nombre", "Nombre_desarrollo"]:
                if c in df_h.columns:
                    col_nombre = c
                    break

            c1, c2 = st.columns(2)
 

            # -------------------------
            # Columna izquierda: ENTRAN
            # -------------------------
            with c1:
                st.markdown(f"### Desarrollos que **entraron** ({inicio_ventana.date()} → {fin_ventana.date()})")

                if col_nombre is None:
                    st.warning("No se encontró ninguna columna de nombre de desarrollo.")
                else:
                    st.metric("Desarrollos que entran", len(df_entran))

                    if len(df_entran) == 0:
                        st.write("No hay desarrollos nuevos.")
                    else:
                        # Lista formateada: nombre — fecha — zona
                        for _, fila in df_entran.sort_values(col_fecha).iterrows():
                            nombre = str(fila[col_nombre])
                            fecha = fila[col_fecha]
                            zona = fila["Zona"] if "Zona" in df_entran.columns else "—"
                            fecha_str = fecha.strftime("%b-%Y") if pd.notna(fecha) else "—"
                            st.write(f"• {nombre} — *{fecha_str}* — **{zona}**")

            # -------------------------
            # Columna derecha: VENDIDOS
            # -------------------------
            with c2:
                st.markdown(f"### Desarrollos **vendidos** ({inicio_ventana.date()} → {fin_ventana.date()})")

                col_fin = "Fecha_fin_ventas"
                if col_fin not in df_h.columns:
                    st.warning(f"No se encontró la columna **{col_fin}** en la hoja seleccionada.")
                else:
                    df_fin = df_h.copy()
                    df_fin[col_fin] = pd.to_datetime(df_fin[col_fin], errors="coerce")

                    mask_fin = (df_fin[col_fin] >= inicio_ventana) & (df_fin[col_fin] <= fin_ventana)
                    df_vendidos = df_fin.loc[mask_fin]

                    st.metric("Desarrollos vendidos", len(df_vendidos))

                    if len(df_vendidos) == 0:
                        st.write("No hay desarrollos vendidos.")
                    else:
                        for _, fila in df_vendidos.sort_values(col_fin).iterrows():
                            nombre = str(fila[col_nombre]) if col_nombre else "—"
                            fecha = fila[col_fin]
                            zona = fila["Zona"] if "Zona" in df_vendidos.columns else "—"
                            fecha_str = fecha.strftime("%b-%Y") if pd.notna(fecha) else "—"
                            st.write(f"• {nombre} — *{fecha_str}* — **{zona}**")
        
    

    # ---------------------------
    # TAB: Lote
    # ---------------------------
    with tab_lote:
        st.subheader("Vista — Lote")
        
        

    # ---------------------------
    # TAB: Zonas
    # ---------------------------
    with tab_zonas:
        st.subheader("Vista — Zonas")
       

    

