#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pandas as pd
import dash
from dash import Dash, dcc, html
from dash.dependencies import Input, Output
import plotly.express as px
import plotly.graph_objects as go

# ============================
# 1) Leer base y normalizar
# ============================
df = pd.read_csv("data/PESCADORESINSCRITOS_2003-2024.csv", low_memory=False)

df.columns = df.columns.str.strip()

# ---- Normalizar Región (viene como 10.0, etc.) ----
df["Region"] = df["Region"].astype(str).str.strip()
df["Region"] = df["Region"].str.replace(".0", "", regex=False)

# Diccionario oficial con número romano + nombre, en orden geográfico
dicc_regiones = {
    "15": "XV Arica y Parinacota",
    "1":  "I Tarapacá",
    "2":  "II Antofagasta",
    "3":  "III Atacama",
    "4":  "IV Coquimbo",
    "5":  "V Valparaíso",
    "6":  "VI Libertador General Bernardo O'Higgins",
    "7":  "VII Maule",
    "16": "XVI Ñuble",
    "8":  "VIII Biobío",
    "9":  "IX de Araucanía",
    "14": "XIV Los Ríos",
    "10": "X Los Lagos",
    "11": "XI Aysén del General Carlos Ibáñez del Campo",
    "12": "XII Magallanes y Antártica Chilena",
}

# Columna con nombre elegante de región
df["Region_Nombre"] = df["Region"].map(dicc_regiones).fillna(df["Region"])

# Años y totales numéricos
numeric_cols = [
    "Año", "Pescador_Mujer", "Pescador_Hombre", "Total_Pescador",
    "Buzo_Mariscador_Mujer", "Buzo_Mariscador_Hombre", "Total_Buzo_Mariscador",
    "Recolector_Orilla_Mujer", "Recolector_Orilla_Hombre", "Total_Recolector_Orilla",
    "Armador_Mujer", "Armador_Hombre", "Total_Armador",
    "Total_Mujer", "Total_Hombre", "Total_General",
]
for col in numeric_cols:
    df[col] = pd.to_numeric(df[col], errors="coerce")

df_base = df.dropna(subset=["Año", "Region", "Total_General"])

min_year = int(df_base["Año"].min())
max_year = int(df_base["Año"].max())

# Orden geográfico deseado de códigos de región
region_order_geo = [
    "15",  # XV Arica y Parinacota
    "1",   # I Tarapacá
    "2",   # II Antofagasta
    "3",   # III Atacama
    "4",   # IV Coquimbo
    "5",   # V Valparaíso
    "13",  # RM (puede que no esté en df, lo dejamos por si acaso)
    "6",   # VI O'Higgins
    "7",   # VII Maule
    "16",  # XVI Ñuble
    "8",   # VIII Biobío
    "9",   # IX Araucanía
    "14",  # XIV Los Ríos
    "10",  # X Los Lagos
    "11",  # XI Aysén
    "12",  # XII Magallanes
]

# Códigos de región presentes en los datos, respetando orden geográfico
regiones_presentes = sorted(df_base["Region"].dropna().unique().tolist())
regiones_unicas = [r for r in region_order_geo if r in regiones_presentes]

# Mapa código -> nombre
map_region_nombre = {code: dicc_regiones.get(code, code) for code in regiones_unicas}

# ============================
# 2) Estilos
# ============================
COLORS = {
    "bg": "#f5f7fa",
    "card": "white",
    "accent": "#005f73",
    "muted": "#555555",
    "hombre": "#3d4f6c",
    "mujer": "#4b9a6c",
}

CARD_STYLE = {
    "backgroundColor": COLORS["card"],
    "borderRadius": "8px",
    "padding": "15px",
    "boxShadow": "0 2px 5px rgba(0,0,0,0.08)",
    "marginBottom": "15px",
}

# ============================
# 3) App
# ============================
app = Dash(
    __name__,
    requests_pathname_prefix="/apps/pescadores/",
)

app.layout = html.Div(
    style={"fontFamily": "Arial, sans-serif", "backgroundColor": COLORS["bg"], "minHeight": "100vh"},
    children=[
        # Barra superior
        html.Div(
            style={"backgroundColor": COLORS["accent"], "color": "white", "padding": "12px 25px"},
            children=[
                html.H1("Pescadores inscritos por región y género", style={"margin": 0, "fontSize": "22px"}),
                html.Div("Chile, 2003–2024", style={"fontSize": "13px"}),
            ],
        ),

        html.Div(
            style={"padding": "20px 25px"},
            children=[
                html.Div(
                    style={"display": "flex", "gap": "20px", "flexWrap": "wrap"},
                    children=[
                        # ----- FILTROS -----
                        html.Div(
                            style={"flex": "1 1 260px", "maxWidth": "360px"},
                            children=[
                                html.Div(
                                    style=CARD_STYLE,
                                    children=[
                                        html.H3("Filtros", style={"marginTop": 0}),
                                        html.Label("Regiones"),
                                        dcc.Dropdown(
                                            id="region-dropdown",
                                            options=(
                                                [{"label": "Nacional (todas)", "value": "NACIONAL"}] +
                                                [{"label": map_region_nombre.get(r, r), "value": r} for r in regiones_unicas]
                                            ),
                                            value=["NACIONAL"],
                                            multi=True,
                                            style={"marginBottom": "15px"},
                                        ),
                                    ],
                                ),
                                html.Div(
                                    id="resumen-texto",
                                    style=CARD_STYLE | {"fontSize": "13px"},
                                ),
                            ],
                        ),

                        # ----- GRÁFICOS -----
                        html.Div(
                            style={"flex": "3 1 500px"},
                            children=[
                                html.Div(
                                    style=CARD_STYLE,
                                    children=[
                                        html.H4("Distribución por región (año seleccionado)", style={"marginTop": 0}),
                                        dcc.Graph(id="bar-regiones"),

                                        # Slider de año BAJO el primer gráfico
                                        html.Div(
                                            [
                                                html.Label(
                                                    "Año (seleccionar años a visualizar. El resumen muestra el último año de la serie de tiempo)",
                                                    style={
                                                        "fontWeight": "bold",
                                                        "fontSize": "13px",
                                                        "display": "block",
                                                        "marginBottom": "4px",
                                                        "lineHeight": "1.3",
                                                    },
                                                ),
                                                dcc.Slider(
                                                    id="year-slider",
                                                    min=min_year,
                                                    max=max_year,
                                                    value=max_year,
                                                    step=1,
                                                    marks={y: str(y) for y in range(min_year, max_year + 1, 2)},
                                                ),
                                            ],
                                            style={"marginTop": "20px"},
                                        ),
                                    ],
                                ),

                                html.Div(
                                    style=CARD_STYLE,
                                    children=[
                                        html.H4("Serie de tiempo nacional por género", style={"marginTop": 0}),
                                        dcc.Graph(id="bar-tiempo"),
                                        html.Div(
                                            [
                                                "Elaboración: Instituto en Socio-Ecología Costera (SECOS) – Datacenter",
                                                html.Br(),
                                                "Fuente: Registro de pescadores inscritos (Sernapesca / Subpesca, según corresponda).",
                                            ],
                                            style={"fontSize": "11px", "color": COLORS["muted"], "marginTop": "8px"},
                                        ),
                                    ],
                                ),

                                # 👇 NUEVO: Dumbbell por categoría
                                html.Div(
                                    style=CARD_STYLE,
                                    children=[
                                        html.H4("Pescadores inscritos por categoría y género (dumbbell)", style={"marginTop": 0}),
                                        dcc.Graph(id="dot-categorias"),
                                    ],
                                ),
                            ],
                        ),
                    ],
                ),
            ],
        ),
    ],
)

# ============================
# 4) Callbacks
# ============================
@app.callback(
    Output("resumen-texto", "children"),
    Output("bar-regiones", "figure"),
    Output("bar-tiempo", "figure"),
    Output("dot-categorias", "figure"),
    Input("region-dropdown", "value"),
    Input("year-slider", "value"),
)
def actualizar_vistas(regiones_sel, year_sel):
    dff = df_base.copy()

    # Filtrar regiones (si solo está "NACIONAL", usamos todas)
    regiones_limpias = [r for r in regiones_sel if r != "NACIONAL"] if regiones_sel else []
    if regiones_limpias:
        dff_year = dff[(dff["Region"].isin(regiones_limpias)) & (dff["Año"] == year_sel)]
        dff_nacional_tiempo = dff[dff["Region"].isin(regiones_limpias)]
        nombres_regiones = [map_region_nombre.get(r, r) for r in regiones_limpias]
        regiones_texto = ", ".join(nombres_regiones)
    else:
        dff_year = dff[dff["Año"] == year_sel]
        dff_nacional_tiempo = dff
        regiones_texto = "todas las regiones"

    # -------- Resumen texto --------
    total_mujer = dff_year["Total_Mujer"].sum()
    total_hombre = dff_year["Total_Hombre"].sum()
    total_general = dff_year["Total_General"].sum()

    if total_general > 0:
        pct_m = 100 * total_mujer / total_general
        pct_h = 100 * total_hombre / total_general
    else:
        pct_m = pct_h = 0.0

    resumen = [
        html.Strong(f"Año {year_sel} · {regiones_texto}"),
        html.Br(),
        f"Total de pescadores inscritos: {int(total_general):,}".replace(",", "."),
        html.Br(),
        f"Mujeres: {int(total_mujer):,} ({pct_m:.1f} %)".replace(",", "."),
        html.Br(),
        f"Hombres: {int(total_hombre):,} ({pct_h:.1f} %)".replace(",", "."),
    ]

    # -------- Gráfico 1: barras por región (año) --------
    if dff_year.empty:
        fig_reg = px.bar()
        fig_reg.update_layout(
            title="Sin datos para el año / región seleccionados",
            template="simple_white",
        )
    else:
        agg_reg = (
            dff_year.groupby("Region", as_index=False)[["Total_Mujer", "Total_Hombre", "Total_General"]]
            .sum()
        )
        agg_reg["Region_Nombre"] = agg_reg["Region"].map(map_region_nombre).fillna(agg_reg["Region"])

        reg_long = agg_reg.melt(
            id_vars=["Region", "Region_Nombre", "Total_General"],
            value_vars=["Total_Mujer", "Total_Hombre"],
            var_name="Genero",
            value_name="N_personas",
        )
        reg_long["Genero"] = reg_long["Genero"].replace({"Total_Mujer": "Mujer", "Total_Hombre": "Hombre"})

        fig_reg = px.bar(
            reg_long,
            x="Region_Nombre",
            y="N_personas",
            color="Genero",
            barmode="group",
        )
        fig_reg.for_each_trace(
            lambda t: t.update(marker_color=COLORS["hombre"]) if t.name == "Hombre" else
                      t.update(marker_color=COLORS["mujer"])
        )

        # Ordenar eje X según orden geográfico
        category_array = [map_region_nombre[r] for r in regiones_unicas if r in agg_reg["Region"].unique()]
        fig_reg.update_layout(
            title=f"Pescadores inscritos por región y género (año {year_sel})",
            xaxis_title="Región",
            yaxis_title="Número de personas",
            template="simple_white",
        )
        fig_reg.update_xaxes(categoryorder="array", categoryarray=category_array)

    # -------- Gráfico 2: serie de tiempo nacional por género --------
    agg_time = (
        dff_nacional_tiempo.groupby("Año", as_index=False)[["Total_Mujer", "Total_Hombre", "Total_General"]]
        .sum()
    )
    time_long = agg_time.melt(
        id_vars=["Año", "Total_General"],
        value_vars=["Total_Mujer", "Total_Hombre"],
        var_name="Genero",
        value_name="N_personas",
    )
    time_long["Genero"] = time_long["Genero"].replace({"Total_Mujer": "Mujer", "Total_Hombre": "Hombre"})

    fig_time = px.bar(
        time_long,
        x="Año",
        y="N_personas",
        color="Genero",
        barmode="group",
    )
    fig_time.for_each_trace(
        lambda t: t.update(marker_color=COLORS["hombre"]) if t.name == "Hombre" else
                  t.update(marker_color=COLORS["mujer"])
    )
    fig_time.update_layout(
        title="Evolución anual de pescadores inscritos por género",
        xaxis_title="Año",
        yaxis_title="Número de personas",
        template="simple_white",
    )

    # -------- Gráfico 3: dumbbell por categoría (año + regiones seleccionadas) --------
    cat_map = [
        ("Pescador artesanal", "Pescador_Mujer", "Pescador_Hombre"),
        ("Buzo Mariscador", "Buzo_Mariscador_Mujer", "Buzo_Mariscador_Hombre"),
        ("Recolector de Orilla", "Recolector_Orilla_Mujer", "Recolector_Orilla_Hombre"),
        ("Armador Artesanal", "Armador_Mujer", "Armador_Hombre"),
    ]

    rows = []
    for cat_name, col_m, col_h in cat_map:
        rows.append({"Categoria": cat_name, "Genero": "Mujer", "N_personas": float(dff_year[col_m].sum() or 0)})
        rows.append({"Categoria": cat_name, "Genero": "Hombre", "N_personas": float(dff_year[col_h].sum() or 0)})

    cat_long = pd.DataFrame(rows)

    if cat_long["N_personas"].sum() == 0:
        fig_cat = px.scatter()
        fig_cat.update_layout(
            title="Sin datos para categoría / año / región seleccionados",
            template="simple_white",
        )
    else:
        # Pivot para tener columnas Mujer/Hombre por categoría
        pivot = (
            cat_long.pivot_table(index="Categoria", columns="Genero", values="N_personas", aggfunc="sum")
            .fillna(0.0)
            .reset_index()
        )

        # Orden: por total (H+M) desc
        pivot["Total"] = pivot.get("Hombre", 0) + pivot.get("Mujer", 0)
        pivot = pivot.sort_values("Total", ascending=False)

        categorias = pivot["Categoria"].tolist()

        fig_cat = go.Figure()

        # 1) Líneas (dumbbell)
        for _, r in pivot.iterrows():
            fig_cat.add_trace(
                go.Scatter(
                    x=[r.get("Mujer", 0), r.get("Hombre", 0)],
                    y=[r["Categoria"], r["Categoria"]],
                    mode="lines",
                    line=dict(width=3, color="rgba(0,0,0,0.25)"),
                    hoverinfo="skip",
                    showlegend=False,
                )
            )

        # 2) Puntos Mujer
        fig_cat.add_trace(
            go.Scatter(
                x=pivot.get("Mujer", pd.Series([0]*len(pivot))).tolist(),
                y=categorias,
                mode="markers",
                name="Mujer",
                marker=dict(size=12, color=COLORS["mujer"]),
                customdata=pivot["Total"].tolist(),
                hovertemplate="<b>%{y}</b><br>Mujer: %{x:,.0f}<extra></extra>",
            )
        )

        # 3) Puntos Hombre
        fig_cat.add_trace(
            go.Scatter(
                x=pivot.get("Hombre", pd.Series([0]*len(pivot))).tolist(),
                y=categorias,
                mode="markers",
                name="Hombre",
                marker=dict(size=12, color=COLORS["hombre"]),
                hovertemplate="<b>%{y}</b><br>Hombre: %{x:,.0f}<extra></extra>",
            )
        )

        fig_cat.update_layout(
            title=f"Distribución por categoría y género (año {year_sel})",
            xaxis_title="Número de personas",
            yaxis_title="Categoría",
            template="simple_white",
            legend_title_text="Género",
            margin=dict(l=10, r=10, t=50, b=10),
        )

        # Para que quede en el mismo orden visual que pivot (desc)
        fig_cat.update_yaxes(categoryorder="array", categoryarray=categorias)

        # Un poquito de aire a la izquierda (si los nombres son largos)
        fig_cat.update_layout(yaxis=dict(automargin=True))

    return resumen, fig_reg, fig_time, fig_cat


# ============================
# 5) Run
# ============================
if __name__ == "__main__":
    app.run(
        host="127.0.0.1",   # 👈 sólo interno
        port=8055,
        debug=False
    )