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

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

TODAS_ESPECIES_VALUE = "__TODAS__"

# ============================
# 1) Leer base y normalizar
# ============================
df = pd.read_csv("data/DESEMBARQUE_ARTESANAL_CALETA_2000_2024.csv", low_memory=False)
df.columns = df.columns.str.strip()

# Normalizar columnas clave
df["ESPECIE"] = df["ESPECIE"].astype(str).str.upper().str.strip()

# --- REGIÓN: puede venir como 10.0, etc. ---
df["REGION"] = df["REGION"].astype(str).str.strip()
df["REGION"] = df["REGION"].str.replace(".0", "", regex=False)

# --- Cd_Caleta: forzar a string limpio (por si viene como 123.0) ---
df["Cd_Caleta"] = df["Cd_Caleta"].astype(str).str.strip()
df["Cd_Caleta"] = df["Cd_Caleta"].str.replace(".0", "", regex=False)

df["Nm_Caleta"] = df["Nm_Caleta"].astype(str).str.strip()

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

df["REGION_NOMBRE"] = df["REGION"].map(dicc_regiones).fillna(df["REGION"])

# Numéricos
df["AÑO"] = pd.to_numeric(df["AÑO"], errors="coerce").round().astype("Int64")
df["TOTAL"] = pd.to_numeric(df["TOTAL"], errors="coerce")

# ============================
# 2) Base reducida
# ============================
df_base = df[["ESPECIE", "AÑO", "TOTAL", "REGION", "REGION_NOMBRE", "Cd_Caleta", "Nm_Caleta"]].dropna(subset=["AÑO", "TOTAL"]).copy()
df_base["AÑO"] = df_base["AÑO"].astype(int)

min_year = int(df_base["AÑO"].min())
max_year = int(df_base["AÑO"].max())

# Especies ordenadas por tonelaje total
especies_ordenadas = (
    df_base.groupby("ESPECIE")["TOTAL"]
    .sum()
    .sort_values(ascending=False)
    .index.tolist()
)

# Especies por defecto
especies_default_deseadas = ["ANCHOVETA", "SARDINA COMUN"]
default_especies = [e for e in especies_default_deseadas if e in especies_ordenadas] or especies_ordenadas[:2]

# ----- Regiones únicas en orden geográfico -----
region_order_geo = ["15", "1", "2", "3", "4", "5", "13", "6", "7", "16", "8", "9", "14", "10", "11", "12"]
regiones_presentes = sorted(df_base["REGION"].dropna().unique().tolist())
regiones_unicas = [r for r in region_order_geo if r in regiones_presentes]

map_region_nombre = {code: dicc_regiones.get(code, code) for code in regiones_unicas}

def build_caleta_options(dff):
    caletas_unique = (
        dff[["Cd_Caleta", "Nm_Caleta"]]
        .drop_duplicates()
        .sort_values("Nm_Caleta")
    )
    return [
        {"label": f"{row['Nm_Caleta']} ({row['Cd_Caleta']})", "value": row["Cd_Caleta"]}
        for _, row in caletas_unique.iterrows()
    ]

def format_tons(x):
    return f"{x:,.1f} t".replace(",", "X").replace(".", ",").replace("X", ".")

def build_species_options(species_list):
    return [{"label": "TODAS LAS ESPECIES", "value": TODAS_ESPECIES_VALUE}] + [
        {"label": e, "value": e} for e in species_list
    ]

caleta_options_all = build_caleta_options(df_base)

# ============================
# 3) Estilos
# ============================
COLORS = {
    "bg": "#f5f7fa",
    "card": "white",
    "accent": "#005f73",
    "muted": "#666666",
    "info_bg": "#eef6f8",
    "info_border": "#005f73",
    "soft_box": "#f9fbfc",
    "soft_border": "#dde7ea",
}

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

TOP5_BOX_STYLE = {
    "marginTop": "16px",
    "padding": "12px 14px",
    "backgroundColor": COLORS["soft_box"],
    "border": f"1px solid {COLORS['soft_border']}",
    "borderRadius": "8px",
}

INFO_BOX_STYLE = {
    "marginBottom": "10px",
    "padding": "10px 12px",
    "backgroundColor": COLORS["info_bg"],
    "borderLeft": f"4px solid {COLORS['info_border']}",
    "fontSize": "13px",
    "borderRadius": "4px",
    "lineHeight": "1.5",
}

# ============================
# 4) App Layout
# ============================
app = Dash(__name__, requests_pathname_prefix="/apps/caletas/")

app.layout = html.Div(
    style={"fontFamily": "Arial", "backgroundColor": COLORS["bg"], "minHeight": "100vh"},
    children=[
        html.Div(
            style={"backgroundColor": COLORS["accent"], "color": "white", "padding": "12px 25px"},
            children=[
                html.H1("Desembarques por caleta (Artesanal)", style={"margin": 0, "fontSize": "22px"}),
                html.Div("Serie de tiempo 2000–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": "380px"},
                            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,
                                            placeholder="Selecciona una o más regiones",
                                            style={"marginBottom": "12px"},
                                        ),

                                        html.Label("Caleta"),
                                        dcc.Dropdown(
                                            id="caleta-dropdown",
                                            options=caleta_options_all,
                                            value=[],
                                            multi=True,
                                            placeholder="Selecciona una o más caletas",
                                            style={"marginBottom": "12px"},
                                        ),

                                        html.Label("Especies"),
                                        dcc.Dropdown(
                                            id="especie-dropdown",
                                            options=build_species_options(especies_ordenadas),
                                            value=default_especies,
                                            multi=True,
                                            style={"marginBottom": "12px"},
                                        ),
                                    ],
                                )
                            ],
                        ),

                        # ----- GRÁFICO -----
                        html.Div(
                            style={"flex": "3 1 500px"},
                            children=[
                                html.Div(
                                    style=CARD_STYLE,
                                    children=[
                                        html.Div(id="mensaje-contexto", style=INFO_BOX_STYLE),

                                        dcc.Graph(id="grafico-caletas"),

                                        html.Div(id="top5-especies", style=TOP5_BOX_STYLE),

                                        html.Div(
                                            [
                                                html.Label(
                                                    "Rango de años",
                                                    style={"fontWeight": "bold", "fontSize": "13px", "marginBottom": "4px"},
                                                ),
                                                dcc.RangeSlider(
                                                    id="year-range",
                                                    min=min_year,
                                                    max=max_year,
                                                    value=[min_year, max_year],
                                                    step=1,
                                                    marks={y: str(y) for y in range(min_year, max_year + 1, 5)},
                                                ),
                                            ],
                                            style={"marginTop": "20px"},
                                        ),

                                        html.Div(
                                            ["Valores: Toneladas anuales desembarcadas por especie a nivel de caletas."],
                                            style={"fontSize": "12px", "color": COLORS["muted"], "marginTop": "10px"},
                                        ),
                                        html.Div(
                                            [
                                                "Elaboración: Instituto en Socio-Ecología Costera (SECOS) – Datacenter",
                                                html.Br(),
                                                "Fuente: Sernapesca",
                                            ],
                                            style={"fontSize": "11px", "color": COLORS["muted"], "marginTop": "4px"},
                                        ),
                                    ],
                                )
                            ],
                        ),
                    ],
                )
            ],
        ),
    ],
)

# ============================
# 5A) CALLBACK: Si el usuario elige una región, sacar "NACIONAL"
# ============================
@app.callback(
    Output("region-dropdown", "value"),
    Input("region-dropdown", "value"),
)
def auto_quitar_nacional(regiones_sel):
    regiones_sel = regiones_sel or []

    if "NACIONAL" in regiones_sel:
        reales = [r for r in regiones_sel if r != "NACIONAL"]
        if len(reales) > 0:
            return reales

    return regiones_sel

# ============================
# 5B) CALLBACK: Filtrar caletas por región
# ============================
@app.callback(
    Output("caleta-dropdown", "options"),
    Output("caleta-dropdown", "value"),
    Input("region-dropdown", "value"),
    Input("caleta-dropdown", "value"),
)
def actualizar_caletas_por_region(regiones_sel, caletas_sel):
    regiones_sel = regiones_sel or []
    caletas_sel = caletas_sel or []

    if (not regiones_sel) or ("NACIONAL" in regiones_sel):
        return caleta_options_all, caletas_sel

    dff = df_base[df_base["REGION"].isin(regiones_sel)]
    opts = build_caleta_options(dff)

    valid_values = {o["value"] for o in opts}
    caletas_filtradas = [c for c in caletas_sel if c in valid_values]

    return opts, caletas_filtradas

# ============================
# 5C) CALLBACK: Ajustar especies automáticamente
# - Siempre ofrece "TODAS LAS ESPECIES"
# - Por defecto selecciona las 2 más desembarcadas de la selección actual
# ============================
@app.callback(
    Output("especie-dropdown", "options"),
    Output("especie-dropdown", "value"),
    Input("region-dropdown", "value"),
    Input("caleta-dropdown", "value"),
)
def actualizar_especies_disponibles(regiones_sel, caletas_sel):
    regiones_sel = regiones_sel or []
    caletas_sel = caletas_sel or []

    dff = df_base.copy()

    regiones_limpias = [r for r in regiones_sel if r != "NACIONAL"]
    if regiones_limpias:
        dff = dff[dff["REGION"].isin(regiones_limpias)]

    if caletas_sel:
        if isinstance(caletas_sel, str):
            caletas_sel = [caletas_sel]
        dff = dff[dff["Cd_Caleta"].isin(caletas_sel)]

    especies_locales = (
        dff.groupby("ESPECIE")["TOTAL"]
        .sum()
        .sort_values(ascending=False)
        .index.tolist()
    )

    if not especies_locales:
        return build_species_options([]), []

    opts = build_species_options(especies_locales)

    # Por defecto: las 2 más desembarcadas
    defaults = especies_locales[:2]

    # Si no hay suficientes, usar las disponibles
    if not defaults:
        defaults = especies_locales[:1]

    return opts, defaults

# ============================
# 5D) CALLBACK: Gráfico + Top 5 + mensaje contexto
# ============================
@app.callback(
    Output("grafico-caletas", "figure"),
    Output("top5-especies", "children"),
    Output("mensaje-contexto", "children"),
    Input("region-dropdown", "value"),
    Input("caleta-dropdown", "value"),
    Input("especie-dropdown", "value"),
    Input("year-range", "value"),
)
def actualizar_grafico(regiones_sel, caletas_sel, especies_sel, year_range):

    dff = df_base.copy()

    regiones_sel = regiones_sel or []
    caletas_sel = caletas_sel or []

    # Filtrar regiones
    regiones_limpias = [r for r in regiones_sel if r != "NACIONAL"]
    if regiones_limpias:
        dff = dff[dff["REGION"].isin(regiones_limpias)]

    # Filtrar caletas
    if caletas_sel:
        if isinstance(caletas_sel, str):
            caletas_sel = [caletas_sel]
        dff = dff[dff["Cd_Caleta"].isin(caletas_sel)]

    # Filtrar años
    a0, a1 = year_range
    dff = dff[(dff["AÑO"] >= a0) & (dff["AÑO"] <= a1)]

    # ============================
    # Mensaje contextual + Top 5
    # ============================
    if caletas_sel:
        caleta_names = (
            df_base[df_base["Cd_Caleta"].isin(caletas_sel)][["Cd_Caleta", "Nm_Caleta"]]
            .drop_duplicates()
            .sort_values("Nm_Caleta")["Nm_Caleta"]
            .tolist()
        )
        caleta_texto = ", ".join(caleta_names)

        if not dff.empty:
            resumen_especies = (
                dff.groupby("ESPECIE", as_index=False)["TOTAL"]
                .sum()
                .sort_values("TOTAL", ascending=False)
            )

            n_especies = resumen_especies["ESPECIE"].nunique()
            total_periodo = resumen_especies["TOTAL"].sum()
            top5 = resumen_especies.head(5)
            total_top5 = top5["TOTAL"].sum()
            pct_top5 = (total_top5 / total_periodo * 100) if total_periodo > 0 else 0

            mensaje = html.Div([
                html.Div([
                    html.B("Modo caleta: "),
                    f"al seleccionar {caleta_texto}, el selector de especies ofrece la opción ",
                    html.B("TODAS LAS ESPECIES"),
                    " y, por defecto, muestra las 2 especies más desembarcadas de la selección actual."
                ]),
                html.Div(
                    [
                        html.B(f"{n_especies} especies "),
                        "registran desembarque en esta caleta. ",
                        html.B(f"Top 5 representan {pct_top5:.0f}% "),
                        f"del desembarque para el periodo {a0}–{a1}."
                    ],
                    style={"marginTop": "6px"}
                )
            ])

            top5_children = [
                html.Div(
                    f"Top 5 especies con mayor desembarque acumulado ({a0}–{a1})",
                    style={"fontWeight": "bold", "marginBottom": "8px"}
                ),
                html.Ol(
                    [
                        html.Li(f"{row['ESPECIE']}: {format_tons(row['TOTAL'])}")
                        for _, row in top5.iterrows()
                    ],
                    style={"margin": 0, "paddingLeft": "20px"}
                )
            ]
        else:
            mensaje = html.Div([
                html.Div([
                    html.B("Modo caleta: "),
                    f"se seleccionó {caleta_texto}, pero no hay desembarques registrados para el periodo {a0}–{a1}."
                ])
            ])
            top5_children = html.Div("No hay desembarques para esta caleta en el rango de años seleccionado.")
    else:
        mensaje = html.Div([
            html.Div([
                html.B("Modo general: "),
                "el gráfico muestra, por defecto, las 2 especies más desembarcadas de la selección actual."
            ]),
            html.Div(
                [
                    "También puedes elegir ",
                    html.B("TODAS LAS ESPECIES"),
                    " o seleccionar manualmente una o más especies específicas."
                ],
                style={"marginTop": "6px"}
            )
        ])
        top5_children = html.Div(
            "Selecciona una caleta para ver el resumen automático de especies y el Top 5 de desembarques.",
            style={"color": COLORS["muted"]}
        )

    # ============================
    # Filtrar especies para el gráfico
    # ============================
    if isinstance(especies_sel, str):
        especies_sel = [especies_sel]
    especies_sel = especies_sel or []

    if TODAS_ESPECIES_VALUE in especies_sel:
        dff_plot = dff.copy()
    elif especies_sel:
        dff_plot = dff[dff["ESPECIE"].isin(especies_sel)]
    else:
        dff_plot = dff.copy()

    if dff_plot.empty:
        fig = px.line()
        fig.update_layout(
            title="No hay datos disponibles para la selección actual",
            template="simple_white",
            margin={"l": 60, "r": 20, "t": 70, "b": 40},
        )
        fig.update_xaxes(type="linear", dtick=1, tickmode="linear")
        return fig, top5_children, mensaje

    dff_grouped = (
        dff_plot.groupby(["AÑO", "ESPECIE"], as_index=False)["TOTAL"]
        .sum()
        .sort_values(["ESPECIE", "AÑO"])
    )

    fig = px.line(
        dff_grouped,
        x="AÑO",
        y="TOTAL",
        color="ESPECIE",
        markers=True
    )

    # Título dinámico
    if caletas_sel:
        titulo = "Caletas: " + ", ".join(caleta_names)
    else:
        titulo = "Todas las caletas"

    fig.update_layout(
        title=f"Desembarques artesanales por caleta<br><sup>{titulo}</sup>",
        xaxis_title="Año",
        yaxis_title="Toneladas",
        template="simple_white",
        hovermode="x unified",
        margin={"l": 60, "r": 20, "t": 70, "b": 40},
        legend_title_text="Especie",
    )

    fig.update_xaxes(
        type="linear",
        dtick=1,
        tickmode="linear"
    )

    return fig, top5_children, mensaje

# ============================
# 6) RUN
# ============================
if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8050, debug=False)