import pandas as pd
import numpy as np
import streamlit as st
from streamlit_searchbox import st_searchbox

FILE_PATH = r"C:\Users\julio\OneDrive\Documentos\Trabajo\Ideas Frescas\Proyectos\REM\BD\BD_Mazatlan.xlsm"


# -------------------------------------------------------------------------
# Helpers
# -------------------------------------------------------------------------
def calc_delta_pct(current, previous):
    """Regresa el cambio % entre dos valores, o None si no se puede calcular."""
    if previous is None or previous == 0 or pd.isna(previous):
        return None
    try:
        return (current - previous) / previous * 100
    except ZeroDivisionError:
        return None


@st.cache_data(show_spinner=False)
def load_data(path):
    xls = pd.ExcelFile(path)

    ventas = pd.read_excel(xls, "Ventas")
    precios = pd.read_excel(xls, "Precios")
    vertical = pd.read_excel(xls, "Vertical")
    horizontal = pd.read_excel(xls, "Horizontal")
    lote = pd.read_excel(xls, "Lote")

    # ---- Fechas a datetime ----
    ventas["Fecha"] = pd.to_datetime(ventas["Fecha"], errors="coerce")
    precios["Fecha"] = pd.to_datetime(precios["Fecha"], errors="coerce")

    # ---- Limpiar / forzar numéricos en VENTAS ----
    # Ventas_periodo
    if "Ventas_periodo" in ventas.columns:
        ventas["Ventas_periodo"] = (
            ventas["Ventas_periodo"]
            .astype(str)
            .str.replace(",", "", regex=False)
            .str.replace("$", "", regex=False)
            .str.strip()
        )
        ventas["Ventas_periodo"] = pd.to_numeric(
            ventas["Ventas_periodo"], errors="coerce"
        ).fillna(0)
    else:
        ventas["Ventas_periodo"] = 0.0

    # Inventario_disponible (por si también viene como texto)
    if "Inventario_disponible" in ventas.columns:
        ventas["Inventario_disponible"] = (
            ventas["Inventario_disponible"]
            .astype(str)
            .str.replace(",", "", regex=False)
            .str.replace("$", "", regex=False)
            .str.strip()
        )
        ventas["Inventario_disponible"] = pd.to_numeric(
            ventas["Inventario_disponible"], errors="coerce"
        )

    # ---- Limpiar / forzar numéricos en PRECIOS ----
    for col in ["Precio", "M2"]:
        if col in precios.columns:
            precios[col] = (
                precios[col]
                .astype(str)
                .str.replace(",", "", regex=False)
                .str.replace("$", "", regex=False)
                .str.replace("m2", "", regex=False)
                .str.replace("m²", "", regex=False)
                .str.strip()
            )
            precios[col] = pd.to_numeric(precios[col], errors="coerce")

    # ---- Calcular Precio_m2 ya con columnas numéricas ----
    precios["Precio_m2"] = np.where(
        precios["M2"].notna() & (precios["M2"] != 0),
        precios["Precio"] / precios["M2"],
        np.nan,
    )

    # ---- Mapear Zonas por proyecto/tipo ----
    vertical_map = vertical[["Nombre_desarrollo", "Zona"]].copy()
    vertical_map["Tipo_proyecto"] = "Vertical"

    horizontal_map = horizontal[["Nombre_desarrollo", "Zona"]].copy()
    horizontal_map["Tipo_proyecto"] = "Horizontal"

    lote_map = lote[["Nombre_desarrollo", "Zona"]].copy()
    lote_map["Tipo_proyecto"] = "Lote"

    zona_map = pd.concat([vertical_map, horizontal_map, lote_map], ignore_index=True)

    # ---- Unir zona a Ventas y Precios ----
    ventas = ventas.merge(
        zona_map,
        on=["Nombre_desarrollo", "Tipo_proyecto"],
        how="left",
    )

    precios = precios.merge(
        zona_map,
        on=["Nombre_desarrollo", "Tipo_proyecto"],
        how="left",
    )

    return ventas, precios


def get_periods(ventas: pd.DataFrame):
    periods = sorted(ventas["Fecha"].dropna().unique())
    if len(periods) == 0:
        return None, None, []
    last_period = periods[-1]
    prev_period = periods[-2] if len(periods) > 1 else None
    return last_period, prev_period, periods


def aggregate_proyecto_metrics(ventas, precios, period):
    """
    KPIs por proyecto para un periodo:
    - Unidades vendidas (Ventas_periodo)
    - Precio promedio
    - M2 promedio
    - Precio_m2 promedio
    """
    ventas_p = ventas[ventas["Fecha"] == period].copy()
    precios_p = precios[precios["Fecha"] == period].copy()

    # Ventas por proyecto
    ventas_proj = (
        ventas_p
        .groupby(["Tipo_proyecto", "Nombre_desarrollo", "Zona"], as_index=False)[
            "Ventas_periodo"
        ]
        .sum()
    )

    # Precios promedio por proyecto
    precios_proj = (
        precios_p
        .groupby(["Tipo_proyecto", "Nombre_desarrollo", "Zona"], as_index=False)
        .agg(
            Precio_prom=("Precio", "mean"),
            M2_prom=("M2", "mean"),
            Precio_m2_prom=("Precio_m2", "mean"),
        )
    )

    proj = ventas_proj.merge(
        precios_proj,
        on=["Tipo_proyecto", "Nombre_desarrollo", "Zona"],
        how="left",
    )

    return proj

# -------------------------------------------------------------
# Helper interno: clasificar proyectos (disp / vendidos / detenidos)
# -------------------------------------------------------------
def clasificar_proyectos(df_periodo: pd.DataFrame, tipo: str):
    df_t = df_periodo[df_periodo["Tipo_proyecto"] == tipo].copy()

    if df_t.empty:
        return 0, 0, 0, 0  # disp, vend, det, activos

    if "Ventas_detenidas" not in df_t.columns:
        df_t["Ventas_detenidas"] = False

    agg = df_t.groupby("Nombre_desarrollo").agg(
        inventario_total=("Inventario_disponible", "sum"),
        ventas_total=("Ventas_periodo", "sum"),
        detenidas_flag=("Ventas_detenidas", lambda s: any(
            str(x).strip().lower() in ["1", "true", "sí", "si", "x"] for x in s
        )),
    )

    cond_vendido = (agg["inventario_total"] == 0) & (agg["ventas_total"] > 0)
    cond_detenido = (agg["inventario_total"] > 0) & (agg["detenidas_flag"])
    cond_disponible = (agg["inventario_total"] > 0) & (~agg["detenidas_flag"])

    n_disp = int(cond_disponible.sum())
    n_vend = int(cond_vendido.sum())
    n_det = int(cond_detenido.sum())
    n_act = n_disp + n_vend  # activos = disponibles + vendidos

    return n_disp, n_vend, n_det, n_act



# -------------------------------------------------------
# Helper: KPI en formato vertical con números pequeños
# -------------------------------------------------------
def kpi_vertical(titulo: str, valor, delta):
    delta_txt = "N/A"
    delta_color = "#999999"

    if delta is not None:
        if delta >= 0:
            delta_color = "#00c853"  # verde
            delta_txt = f"↑ {delta:,.1f}%"
        else:
            delta_color = "#d50000"  # rojo
            delta_txt = f"↓ {abs(delta):,.1f}%"

    html = f"""
    <div style="text-align:center; padding:8px 0;">
        <div style="font-size:13px; font-weight:600; color:#dddddd;">
            {titulo}
        </div>
        <div style="font-size:20px; font-weight:700; margin-top:2px;">
            {valor}
        </div>
        <div style="font-size:12px; color:{delta_color}; margin-top:0px;">
            {delta_txt}
        </div>
    </div>
    """
    st.markdown(html, unsafe_allow_html=True)



# -------------------------------------------------------------------------
# PÁGINA RESUMEN
# -------------------------------------------------------------------------
def render_resumen(
    ventas,
    precios,
    periodo_sel,
    periodo_prev,
    tipo_filter,
    proyectos_seleccionados,
):
    st.title("REM- Mazatlán")
    st.caption(
        "Ideas Frescas - Dashboard de análisis de ventas y precios de proyectos inmobiliarios en Mazatlán"
    )

    # Filtrado base
    ventas_sel = ventas.copy()
    precios_sel = precios.copy()

    # Filtro por proyectos seleccionados (desde sidebar)
    if proyectos_seleccionados:
        ventas_sel = ventas_sel[ventas_sel["Nombre_desarrollo"].isin(proyectos_seleccionados)]
        precios_sel = precios_sel[precios_sel["Nombre_desarrollo"].isin(proyectos_seleccionados)]

    # Filtro por tipo (desde sidebar)
    if tipo_filter:
        ventas_sel = ventas_sel[ventas_sel["Tipo_proyecto"].isin(tipo_filter)]
        precios_sel = precios_sel[precios_sel["Tipo_proyecto"].isin(tipo_filter)]



    # Ventas actual y anterior
    ventas_actual = ventas_sel[ventas_sel["Fecha"] == periodo_sel].copy()
    ventas_prev = (
        ventas_sel[ventas_sel["Fecha"] == periodo_prev].copy()
        if periodo_prev is not None
        else ventas_sel[ventas_sel["Fecha"] == periodo_sel].copy() * 0
    )
    
    # Meses transcurridos entre periodo actual y periodo anterior
    if periodo_prev is not None:
        meses_diff = (periodo_sel.year - periodo_prev.year) * 12 + (periodo_sel.month - periodo_prev.month)
        if meses_diff < 1:
            meses_diff = 1
    else:
        meses_diff = 1  # fallback para evitar división entre 0


    # ---------------------------------------------------------------------
    # KPI PRINCIPALES
    # ---------------------------------------------------------------------
    st.subheader("KPIs generales del periodo")

    # Proyectos activos por tipo (inventario_disponible > 0)
    if "Inventario_disponible" in ventas_actual.columns:
        activos_actual = (
            ventas_actual[ventas_actual["Inventario_disponible"] > 0]
            .groupby("Tipo_proyecto")["Nombre_desarrollo"]
            .nunique()
        )
    else:
        activos_actual = ventas_actual.groupby("Tipo_proyecto")["Nombre_desarrollo"].nunique()

    if periodo_prev is not None:
        if "Inventario_disponible" in ventas_prev.columns:
            activos_prev = (
                ventas_prev[ventas_prev["Inventario_disponible"] > 0]
                .groupby("Tipo_proyecto")["Nombre_desarrollo"]
                .nunique()
            )
        else:
            activos_prev = ventas_prev.groupby("Tipo_proyecto")["Nombre_desarrollo"].nunique()
    else:
        activos_prev = activos_actual * 0

    # --- Promedio unidades por desarrollo por tipo (se mantiene como antes) ---
    prom_tipo_actual = (
        ventas_actual.groupby(["Tipo_proyecto", "Nombre_desarrollo"])["Ventas_periodo"]
        .sum()
        .groupby("Tipo_proyecto")
        .mean()
    )
    prom_tipo_prev = (
        ventas_prev.groupby(["Tipo_proyecto", "Nombre_desarrollo"])["Ventas_periodo"]
        .sum()
        .groupby("Tipo_proyecto")
        .mean()
    )

    # ============================================================
    # ABSORCIÓN ÚLTIMO MES (TOTAL Y POR TIPO)
    # ============================================================

    # 1) Total del periodo: sumar por proyecto para evitar doble conteo
    unidades_total_actual = (
        ventas_actual.groupby("Nombre_desarrollo")["Ventas_periodo"].sum().sum()
    )
    unidades_total_prev = (
        ventas_prev.groupby("Nombre_desarrollo")["Ventas_periodo"].sum().sum()
        if periodo_prev is not None
        else 0
    )

    absor_total_actual = unidades_total_actual / meses_diff
    absor_total_prev = (
        unidades_total_prev / meses_diff if periodo_prev is not None else None
    )

    # 2) Por tipo (Vertical / Horizontal / Lote), también sumando por proyecto
    def calc_absorcion_por_tipo(tipo: str):
        df_act = ventas_actual[ventas_actual["Tipo_proyecto"] == tipo]
        df_prev = ventas_prev[ventas_prev["Tipo_proyecto"] == tipo]

        unidades_act = (
            df_act.groupby("Nombre_desarrollo")["Ventas_periodo"].sum().sum()
            if not df_act.empty
            else 0
        )
        unidades_prev = (
            df_prev.groupby("Nombre_desarrollo")["Ventas_periodo"].sum().sum()
            if periodo_prev is not None and not df_prev.empty
            else 0
        )

        absor_act = unidades_act / meses_diff
        absor_prev = (
            unidades_prev / meses_diff if periodo_prev is not None else None
        )

        return absor_act, absor_prev

    abs_vert_actual, abs_vert_prev = calc_absorcion_por_tipo("Vertical")
    abs_horiz_actual, abs_horiz_prev = calc_absorcion_por_tipo("Horizontal")
    abs_lote_actual, abs_lote_prev = calc_absorcion_por_tipo("Lote")

    
    col_total, col_v, col_h, col_l = st.columns(4)

    # Total general - Absorción último mes
    with col_total:
        delta_tot = calc_delta_pct(absor_total_actual, absor_total_prev)
        st.metric(
            "Absorción último mes (Total)",
            f"{absor_total_actual:,.1f}",
            f"{delta_tot:,.1f} %" if delta_tot is not None else "N/A",
        )

    def show_absorcion_tipo(col, abs_act, abs_prev, label):
        with col:
            delta = calc_delta_pct(abs_act, abs_prev)
            st.metric(
                f"Absorción último mes ({label})",
                f"{abs_act:,.1f}",
                f"{delta:,.1f} %" if delta is not None else "N/A",
            )

    show_absorcion_tipo(col_v, abs_vert_actual, abs_vert_prev, "Vertical")
    show_absorcion_tipo(col_h, abs_horiz_actual, abs_horiz_prev, "Horizontal")
    show_absorcion_tipo(col_l, abs_lote_actual, abs_lote_prev, "Lotes")

    # -------------------------------------------------------------
    # Resumen por tipo: proyectos y absorción prom x proyecto
    # -------------------------------------------------------------
    st.subheader("Resumen de proyectos por tipo")

    # Métricas por tipo: periodo actual y anterior
    tipos = ["Vertical", "Horizontal", "Lote"]
    metrics = {}

    for tipo in tipos:
        disp_act, vend_act, det_act, act_act = clasificar_proyectos(ventas_actual, tipo)

        if periodo_prev is not None and not ventas_prev.empty:
            disp_prev, vend_prev, det_prev, act_prev = clasificar_proyectos(ventas_prev, tipo)
        else:
            disp_prev = vend_prev = det_prev = act_prev = 0

        metrics[tipo] = {
            "disp_act": disp_act,
            "vend_act": vend_act,
            "det_act": det_act,
            "act_act": act_act,
            "disp_prev": disp_prev,
            "vend_prev": vend_prev,
            "det_prev": det_prev,
            "act_prev": act_prev,
        }

    # Absorciones por tipo ya calculadas arriba:
    absorciones_actual = {
        "Vertical": abs_vert_actual,
        "Horizontal": abs_horiz_actual,
        "Lote": abs_lote_actual,
    }
    absorciones_prev = {
        "Vertical": abs_vert_prev,
        "Horizontal": abs_horiz_prev,
        "Lote": abs_lote_prev,
    }

    col1, col2, col3 = st.columns(3)

    def render_columna_tipo(col, tipo_label: str):
        data = metrics[tipo_label]
        abs_act = absorciones_actual.get(tipo_label, 0.0)
        abs_prev = absorciones_prev.get(tipo_label, None)

        disp_act = data["disp_act"]
        vend_act = data["vend_act"]
        det_act = data["det_act"]
        act_act = data["act_act"]

        disp_prev = data["disp_prev"]
        vend_prev = data["vend_prev"]
        det_prev = data["det_prev"]
        act_prev = data["act_prev"]

        # Absorción promedio por proyecto activo (solo para el periodo actual)
        if act_act > 0 and abs_act is not None:
            absor_prom_act = abs_act / act_act
        else:
            absor_prom_act = 0.0

        if act_prev > 0 and abs_prev is not None:
            absor_prom_prev = abs_prev / act_prev
        else:
            absor_prom_prev = None

        with col:
            st.markdown(f"#### {tipo_label}")

            # Proyectos disponibles
            delta_disp = calc_delta_pct(disp_act, disp_prev)
            st.metric(
                "Proyectos disponibles",
                f"{disp_act}",
                f"{delta_disp:,.1f} %" if delta_disp is not None else "N/A",
            )

            # Proyectos vendidos
            delta_vend = calc_delta_pct(vend_act, vend_prev)
            st.metric(
                "Proyectos vendidos",
                f"{vend_act}",
                f"{delta_vend:,.1f} %" if delta_vend is not None else "N/A",
            )

            # Proyectos detenidos
            delta_det = calc_delta_pct(det_act, det_prev)
            st.metric(
                "Proyectos detenidos",
                f"{det_act}",
                f"{delta_det:,.1f} %" if delta_det is not None else "N/A",
            )

            # Absorción promedio por proyecto activo
            delta_abs_prom = calc_delta_pct(absor_prom_act, absor_prom_prev)
            st.metric(
                "Absorción prom x proyecto",
                f"{absor_prom_act:,.1f}",
                f"{delta_abs_prom:,.1f} %" if delta_abs_prom is not None else "N/A",
            )

        

    render_columna_tipo(col1, "Vertical")
    render_columna_tipo(col2, "Horizontal")
    render_columna_tipo(col3, "Lote")


    st.markdown("---")

    # Métricas de proyectos activos y promedio por desarrollo
    st.subheader("Proyectos activos y promedio de unidades por desarrollo")

    col1, col2, col3 = st.columns(3)

    with col1:
        st.markdown("**Proyectos activos por tipo**")
        rows = []
        for tipo in ["Vertical", "Horizontal", "Lote"]:
            act_a = activos_actual.get(tipo, 0)
            act_p = activos_prev.get(tipo, 0)
            delta = calc_delta_pct(act_a, act_p)
            rows.append({
                "Tipo": tipo,
                "Proyectos activos": act_a,
                "Δ% vs periodo anterior": f"{delta:,.1f} %" if delta is not None else "N/A",
            })
        st.dataframe(pd.DataFrame(rows), use_container_width=True)

    with col2:
        st.markdown("**Promedio de unidades vendidas por desarrollo**")
        rows2 = []
        for tipo in ["Vertical", "Horizontal", "Lote"]:
            a = prom_tipo_actual.get(tipo, 0)
            p = prom_tipo_prev.get(tipo, 0)
            delta = calc_delta_pct(a, p)
            rows2.append({
                "Tipo": tipo,
                "Unidades prom. por desarrollo": round(a, 2),
                "Δ% vs periodo anterior": f"{delta:,.1f} %" if delta is not None else "N/A",
            })
        st.dataframe(pd.DataFrame(rows2), use_container_width=True)

    with col3:
        st.markdown("**Resumen rápido**")
        st.write(
            f"- Periodo actual: **{periodo_sel.strftime('%Y-%m-%d')}**"
        )
        if periodo_prev is not None:
            st.write(
                f"- Periodo anterior comparado: **{periodo_prev.strftime('%Y-%m-%d')}**"
            )
        else:
            st.write("- No hay periodo anterior para comparar.")
        st.write(
            "- Estos indicadores te dicen si el mercado está **acelerando** o **frenando** "
            "en unidades y en número de proyectos activos."
        )

    st.markdown("---")

    # ---------------------------------------------------------------------
    # TOP 3 ZONAS (VENTAS + PRECIOS + M2 + PRECIO/M2)
    # ---------------------------------------------------------------------
    st.subheader("Top 3 Zonas con más ventas (periodo actual)")

    # Ventas por zona
    ventas_zona_actual = (
        ventas_actual.groupby("Zona")["Ventas_periodo"].sum().reset_index()
    )
    ventas_zona_actual = ventas_zona_actual.sort_values(
        "Ventas_periodo", ascending=False
    )

    if periodo_prev is not None:
        ventas_zona_prev = (
            ventas_prev.groupby("Zona")["Ventas_periodo"].sum().reset_index()
        )
    else:
        ventas_zona_prev = ventas_zona_actual.copy()
        ventas_zona_prev["Ventas_periodo"] = 0

    # KPIs de precios por zona (usamos la hoja de Precios)
    precios_actual = precios_sel[precios_sel["Fecha"] == periodo_sel].copy()

    precios_zona = (
        precios_actual
        .groupby("Zona", as_index=False)
        .agg(
            Precio_prom=("Precio", "mean"),
            M2_prom=("M2", "mean"),
            Precio_m2_prom=("Precio_m2", "mean"),
        )
    )

    # Merge ventas + precios + delta
    top_zonas = ventas_zona_actual.merge(
        ventas_zona_prev, on="Zona", how="left", suffixes=("_act", "_prev")
    ).merge(
        precios_zona, on="Zona", how="left"
    )

    top_zonas["Delta_ventas_pct"] = top_zonas.apply(
        lambda row: calc_delta_pct(row["Ventas_periodo_act"], row["Ventas_periodo_prev"]),
        axis=1,
    )

    # Ordenamos por ventas actuales
    top_zonas = top_zonas.sort_values("Ventas_periodo_act", ascending=False)

    # Sólo Top 3
    top3 = top_zonas.head(3).copy()

    # Formato amigable
    top3_display = top3[[
        "Zona",
        "Ventas_periodo_act",
        "Delta_ventas_pct",
        "Precio_prom",
        "M2_prom",
        "Precio_m2_prom",
    ]].rename(
        columns={
            "Ventas_periodo_act": "Unidades vendidas",
            "Delta_ventas_pct": "Δ% unidades vs periodo anterior",
            "Precio_prom": "Precio promedio",
            "M2_prom": "M2 promedio",
            "Precio_m2_prom": "Precio promedio m²",
        }
    )

    # Redondear columnas numéricas
    for col in ["Precio promedio", "M2 promedio", "Precio promedio m²"]:
        if col in top3_display.columns:
            top3_display[col] = top3_display[col].round(2)

    if not top3_display.empty:
        def fmt_delta(x):
            return f"{x:,.1f} %" if pd.notna(x) else "N/A"

        top3_display["Δ% unidades vs periodo anterior"] = top3_display[
            "Δ% unidades vs periodo anterior"
        ].apply(fmt_delta)

        st.dataframe(top3_display, use_container_width=True)
    else:
        st.info("No hay información suficiente para mostrar el Top 3 de zonas.")

    st.markdown("---")

    # ---------------------------------------------------------------------
    # TOP 10 PROYECTOS POR VENTAS (POR TIPO / SEGMENTO)
    # ---------------------------------------------------------------------
    st.subheader("Top 10 proyectos que más vendieron")

    # Métricas por proyecto para periodo actual y anterior
    proj_actual = aggregate_proyecto_metrics(ventas_sel, precios_sel, periodo_sel)
    if periodo_prev is not None:
        proj_prev = aggregate_proyecto_metrics(ventas_sel, precios_sel, periodo_prev)
    else:
        proj_prev = proj_actual.copy()
        proj_prev["Ventas_periodo"] = 0
        proj_prev["Precio_prom"] = np.nan
        proj_prev["M2_prom"] = np.nan
        proj_prev["Precio_m2_prom"] = np.nan

    proj_merged = proj_actual.merge(
        proj_prev[
            ["Tipo_proyecto", "Nombre_desarrollo", "Zona", "Ventas_periodo"]
        ],
        on=["Tipo_proyecto", "Nombre_desarrollo", "Zona"],
        how="left",
        suffixes=("_act", "_prev"),
    )

    proj_merged["Delta_ventas_pct"] = proj_merged.apply(
        lambda row: calc_delta_pct(row["Ventas_periodo_act"], row["Ventas_periodo_prev"]),
        axis=1,
    )

    # Selector de segmento
    segmento_sel = st.radio(
        "Segmento",
        options=["Todos", "Vertical", "Horizontal", "Lote"],
        horizontal=True,
    )

    df_top = proj_merged.copy()
    if segmento_sel != "Todos":
        df_top = df_top[df_top["Tipo_proyecto"] == segmento_sel]

    df_top = df_top.sort_values("Ventas_periodo_act", ascending=False).head(10)

    if not df_top.empty:
        top_display = df_top[[
            "Tipo_proyecto",
            "Nombre_desarrollo",
            "Zona",
            "Ventas_periodo_act",
            "Ventas_periodo_prev",
            "Delta_ventas_pct",
            "Precio_prom",
            "M2_prom",
            "Precio_m2_prom",
        ]].rename(
            columns={
                "Tipo_proyecto": "Tipo",
                "Nombre_desarrollo": "Proyecto",
                "Zona": "Zona",
                "Ventas_periodo_act": "Unidades periodo actual",
                "Ventas_periodo_prev": "Unidades periodo anterior",
                "Delta_ventas_pct": "Δ% unidades",
                "Precio_prom": "Precio prom.",
                "M2_prom": "M2 prom.",
                "Precio_m2_prom": "Precio m² prom.",
            }
        )

        for col in ["Precio prom.", "M2 prom.", "Precio m² prom."]:
            if col in top_display.columns:
                top_display[col] = top_display[col].round(2)

        top_display["Δ% unidades"] = top_display["Δ% unidades"].apply(
            lambda x: f"{x:,.1f} %" if pd.notna(x) else "N/A"
        )

        st.dataframe(top_display, use_container_width=True)
    else:
        st.info("No hay información suficiente para mostrar el Top 10 de proyectos.")

    st.markdown("---")

    # ---------------------------------------------------------------------
    # VISTA POR ZONA Y TIPO PARA DESARROLLADOR
    # ---------------------------------------------------------------------
    st.subheader("Vista por zona y tipo de proyecto (desarrollador)")

    resumen_zona_tipo = (
        ventas_actual
        .groupby(["Zona", "Tipo_proyecto"], as_index=False)["Ventas_periodo"]
        .sum()
        .rename(columns={"Ventas_periodo": "Unidades periodo actual"})
    )

    if periodo_prev is not None:
        resumen_prev = (
            ventas_prev
            .groupby(["Zona", "Tipo_proyecto"], as_index=False)["Ventas_periodo"]
            .sum()
            .rename(columns={"Ventas_periodo": "Unidades periodo anterior"})
        )
    else:
        resumen_prev = resumen_zona_tipo.copy()
        resumen_prev["Unidades periodo anterior"] = 0

    resumen_zona_tipo = resumen_zona_tipo.merge(
        resumen_prev,
        on=["Zona", "Tipo_proyecto"],
        how="left",
    )

    resumen_zona_tipo["Δ% unidades"] = resumen_zona_tipo.apply(
        lambda row: calc_delta_pct(
            row["Unidades periodo actual"], row["Unidades periodo anterior"]
        ),
        axis=1,
    )

    resumen_zona_tipo["Δ% unidades"] = resumen_zona_tipo["Δ% unidades"].apply(
        lambda x: f"{x:,.1f} %" if pd.notna(x) else "N/A"
    )

    st.write(
        "Esta tabla te permite ver **qué zonas** son más fuertes para cada tipo "
        "de proyecto (vertical, horizontal, lote) y cómo se comportan vs el periodo anterior."
    )

    st.dataframe(resumen_zona_tipo.sort_values(
        ["Zona", "Tipo_proyecto", "Unidades periodo actual"],
        ascending=[True, True, False]
    ), use_container_width=True)
