import streamlit as st
import pandas as pd

st.set_page_config(
    page_title="Observatoire Sportif 2023 - Par Commune",
    page_icon="🏅",
    layout="wide",
)

DATA_DIR = "/Users/patrickbayeux/Documents/2 - Observatoire/DATA/2026/claude/"


def norm_code(val):
    s = str(val).strip().split(".")[0]
    if s.isdigit():
        return s.zfill(5)
    return s


@st.cache_data(show_spinner="Chargement des données…")
def load_data():
    # Synthèse agrégée par commune (générée par analyse_sports.py)
    comm = pd.read_excel(DATA_DIR + "synthese_sports.xlsx", sheet_name="Communes")
    comm["code_commune"] = comm["code_commune"].apply(norm_code)
    comm["dep"] = comm["dep"].astype(str).str.strip()
    comm["epci_nom"] = comm["epci_nom"].fillna("").astype(str).str.strip()
    comm["population"] = pd.to_numeric(comm["population"], errors="coerce").fillna(0).astype(int)

    # EPCI agrégé
    epci = pd.read_excel(DATA_DIR + "synthese_sports.xlsx", sheet_name="EPCI")
    epci["epci_nom"] = epci["epci_nom"].fillna("").astype(str).str.strip()
    epci["population"] = pd.to_numeric(epci["population"], errors="coerce").fillna(0).astype(int)

    # Équipements par famille
    equip_fam = pd.read_excel(DATA_DIR + "synthese_sports.xlsx", sheet_name="Equip_par_famille")
    equip_fam["code_commune"] = equip_fam["code_commune"].apply(norm_code)

    # Clubs par fédération (détail)
    clubs = pd.read_excel(DATA_DIR + "clubs-data-2023.xlsx")
    clubs["code"] = clubs["Code Commune"].apply(norm_code)
    clubs["total"] = pd.to_numeric(clubs["Total_actifs"], errors="coerce").fillna(0).astype(int)
    clubs = clubs[["code", "Fédération", "total"]].rename(columns={"Fédération": "federation"})

    # Licenciés par fédération (détail)
    lic = pd.read_excel(DATA_DIR + "lic-data-2023.xlsx")
    lic["code"] = lic["Code Commune"].apply(norm_code)
    lic["total"] = pd.to_numeric(lic["Total"], errors="coerce").fillna(0).astype(int)
    lic = lic[["code", "Fédération", "total"]].rename(columns={"Fédération": "federation"})

    return comm, epci, equip_fam, clubs, lic


@st.cache_data(show_spinner=False)
def build_commune_list(_comm):
    df = _comm[_comm["commune"].notna() & (_comm["commune"] != "")].copy()
    pop_str = df["population"].apply(
        lambda p: f"  {int(p):,} hab.".replace(",", "\u202f") if p > 0 else ""
    )
    df["label"] = df["commune"].str.title() + "  (" + df["dep"] + ")" + pop_str
    return df.sort_values("label").reset_index(drop=True)


comm_df, epci_df, equip_fam_df, clubs_df, lic_df = load_data()
communes_list = build_commune_list(comm_df)
epci_list = epci_df[epci_df["epci_nom"] != ""].sort_values("epci_nom").reset_index(drop=True)

# Colonnes familles d'équipements
FAM_COLS = [c for c in equip_fam_df.columns if c.startswith("equip_")]

# ── Interface ─────────────────────────────────────────────────────────────────

st.title("🏅 Observatoire Sportif 2023 — par commune ou intercommunalité")
st.caption("Source : Ministère des Sports · Données 2023")

mode = st.radio(
    "Rechercher par :",
    ["🏘️ Commune", "🏛️ Intercommunalité (EPCI)"],
    horizontal=True,
)

commune_slug = "zone"
codes = set()
pop_affichee = 0
nb_clubs = nb_lic = nb_equip = 0
lic_pour_1000 = clubs_pour_1000 = equip_pour_1000 = None

if mode == "🏘️ Commune":
    labels = ["— Sélectionner une commune —"] + communes_list["label"].tolist()
    selected_label = st.selectbox(
        "Rechercher une commune",
        options=labels,
        help="Tapez les premières lettres pour filtrer la liste",
    )
    if selected_label == "— Sélectionner une commune —":
        st.info("Sélectionnez une commune dans la liste pour afficher ses données sportives 2023.", icon="👆")
        st.stop()

    row = communes_list[communes_list["label"] == selected_label].iloc[0]
    codes = {row["code_commune"]}
    pop_affichee = int(row["population"])
    commune_slug = row["commune"].replace(" ", "_").replace("/", "-")

    nb_clubs = int(row.get("nb_clubs", 0) or 0)
    nb_lic   = int(row.get("nb_licencies", 0) or 0)
    nb_equip = int(row.get("nb_equipements", 0) or 0)
    lic_pour_1000   = row.get("licencies_pour_1000_hab")
    clubs_pour_1000 = row.get("clubs_pour_1000_hab")
    equip_pour_1000 = row.get("equip_pour_1000_hab")

else:  # EPCI
    epci_options = ["— Sélectionner une intercommunalité —"] + epci_list["epci_nom"].tolist()
    selected_epci = st.selectbox(
        "Rechercher une intercommunalité (EPCI)",
        options=epci_options,
        help="Tapez les premières lettres pour filtrer la liste",
    )
    if selected_epci == "— Sélectionner une intercommunalité —":
        st.info("Sélectionnez une intercommunalité dans la liste pour afficher ses données sportives 2023.", icon="👆")
        st.stop()

    epci_row = epci_list[epci_list["epci_nom"] == selected_epci].iloc[0]
    commune_slug = selected_epci.replace(" ", "_").replace("/", "-")

    # Codes communes de cet EPCI (depuis la synthèse communes)
    codes = set(comm_df[comm_df["epci_nom"] == selected_epci]["code_commune"].tolist())

    pop_affichee = int(epci_row.get("population", 0) or 0)
    nb_clubs = int(epci_row.get("nb_clubs", 0) or 0)
    nb_lic   = int(epci_row.get("nb_licencies", 0) or 0)
    nb_equip = int(epci_row.get("nb_equipements", 0) or 0)
    lic_pour_1000   = epci_row.get("licencies_pour_1000_hab")
    clubs_pour_1000 = epci_row.get("clubs_pour_1000_hab")
    equip_pour_1000 = epci_row.get("equip_pour_1000_hab")

st.divider()

# ── Métriques ─────────────────────────────────────────────────────────────────

if pop_affichee > 0:
    label_pop = "Population commune" if mode == "🏘️ Commune" else "Population intercommunalité"
    st.metric(label_pop, f"{pop_affichee:,}".replace(",", "\u202f") + " habitants")

c1, c2, c3 = st.columns(3)

with c1:
    st.metric("🏟️ Clubs sportifs", f"{nb_clubs:,}".replace(",", "\u202f"))
    if clubs_pour_1000 is not None and str(clubs_pour_1000) not in ("", "None"):
        st.caption(f"soit **{clubs_pour_1000}** clubs pour 1 000 hab.")

with c2:
    st.metric("🎽 Licenciés", f"{nb_lic:,}".replace(",", "\u202f"))
    if lic_pour_1000 is not None and str(lic_pour_1000) not in ("", "None"):
        st.caption(f"soit **{lic_pour_1000}** licenciés pour 1 000 hab.")

with c3:
    st.metric("⚽ Équipements sportifs", f"{nb_equip:,}".replace(",", "\u202f"))
    if equip_pour_1000 is not None and str(equip_pour_1000) not in ("", "None"):
        st.caption(f"soit **{equip_pour_1000}** équipements pour 1 000 hab.")

st.divider()

# ── Filtres détail ────────────────────────────────────────────────────────────

clubs_zone = clubs_df[clubs_df["code"].isin(codes)]
lic_zone   = lic_df[lic_df["code"].isin(codes)]
equip_zone = equip_fam_df[equip_fam_df["code_commune"].isin(codes)]

# ── Tabs détail ───────────────────────────────────────────────────────────────

tab1, tab2, tab3, tab4 = st.tabs(["🎽 Licenciés par fédération", "🏟️ Clubs par fédération", "⚽ Équipements par famille", "📐 Besoins théoriques"])

with tab1:
    if lic_zone.empty or lic_zone["total"].sum() == 0:
        st.info("Aucun licencié enregistré dans cette zone.")
    else:
        agg = (
            lic_zone.groupby("federation")["total"]
            .sum()
            .reset_index()
            .rename(columns={"federation": "Fédération", "total": "Licenciés"})
            .sort_values("Licenciés", ascending=False)
            .reset_index(drop=True)
        )
        total = agg["Licenciés"].sum()
        agg["% du total"] = (agg["Licenciés"] / total * 100).round(1).astype(str) + " %"
        st.dataframe(agg, use_container_width=True, hide_index=True)

with tab2:
    if clubs_zone.empty or clubs_zone["total"].sum() == 0:
        st.info("Aucun club enregistré dans cette zone.")
    else:
        agg = (
            clubs_zone.groupby("federation")["total"]
            .sum()
            .reset_index()
            .rename(columns={"federation": "Fédération", "total": "Clubs"})
            .sort_values("Clubs", ascending=False)
            .reset_index(drop=True)
        )
        total = agg["Clubs"].sum()
        agg["% du total"] = (agg["Clubs"] / total * 100).round(1).astype(str) + " %"
        st.dataframe(agg, use_container_width=True, hide_index=True)

with tab3:
    if equip_zone.empty or nb_equip == 0:
        st.info("Aucun équipement enregistré dans cette zone.")
    else:
        fam_sums = equip_zone[FAM_COLS].sum()
        fam_df = (
            fam_sums[fam_sums > 0]
            .reset_index()
            .rename(columns={"index": "Famille", 0: "Équipements"})
            .sort_values("Équipements", ascending=False)
            .reset_index(drop=True)
        )
        fam_df["Famille"] = fam_df["Famille"].str.replace("equip_", "", regex=False)
        total = fam_df["Équipements"].sum()
        fam_df["% du total"] = (fam_df["Équipements"] / total * 100).round(1).astype(str) + " %"
        st.dataframe(fam_df, use_container_width=True, hide_index=True)

# ── Besoins théoriques ────────────────────────────────────────────────────────

# Modèle issu du tableau de bord (paramètres G, H, I, J, coefficient L)
MODELE_EQUIP = [
    {
        "equipement": "Court de tennis",
        "equip_col": "equip_Court de tennis",
        "coefficient": 1.15,
        "disciplines": [
            {"federation": "FF de Tennis", "effectif": 4, "entrainements": 3, "duree": 1.5, "dispo": 35},
        ],
    },
    {
        "equipement": "Salle multisports",
        "equip_col": "equip_Salle multisports",
        "coefficient": 1.15,
        "disciplines": [
            {"federation": "FF de Basketball", "effectif": 10, "entrainements": 3, "duree": 1.5, "dispo": 35},
            {"federation": "FF de Handball",   "effectif": 14, "entrainements": 3, "duree": 1.5, "dispo": 35},
            {"federation": "FF de Volley",      "effectif": 12, "entrainements": 3, "duree": 1.5, "dispo": 35},
            {"federation": "FF de Badminton",   "effectif": 15, "entrainements": 3, "duree": 1.5, "dispo": 35},
        ],
    },
    {
        "equipement": "Terrain de grands jeux",
        "equip_col": "equip_Terrain de grands jeux",
        "coefficient": 1.2,
        "disciplines": [
            {"federation": "FF de Football", "effectif": 30, "entrainements": 3, "duree": 1.5, "dispo": 15},
            {"federation": "FF de Rugby",    "effectif": 40, "entrainements": 3, "duree": 1.5, "dispo": 15},
        ],
    },
    {
        "equipement": "Salle ou terrain spécialisé",
        "equip_col": "equip_Salle ou terrain spécialisé",
        "coefficient": 1.2,
        "disciplines": [
            {"federation": "FF de Gymnastique",     "effectif": 40, "entrainements": 3, "duree": 1.5, "dispo": 35},
            {"federation": "FF d'Escrime",           "effectif": 20, "entrainements": 3, "duree": 1.5, "dispo": 35},
            {"federation": "FF de Tennis de Table",  "effectif": 12, "entrainements": 3, "duree": 1.5, "dispo": 35},
        ],
    },
    {
        "equipement": "Salle de combat",
        "equip_col": "equip_Salle de combat",
        "coefficient": 1.2,
        "disciplines": [
            {"federation": "FF de Judo, Jujitsu, Kendo et DA",      "effectif": 20, "entrainements": 3, "duree": 1.5, "dispo": 35},
            {"federation": "FF de Taekwondo et DA",                  "effectif": 20, "entrainements": 3, "duree": 1.5, "dispo": 35},
            {"federation": "FF d'Aïkido, d'Aïkibudo et Affinitaires","effectif": 20, "entrainements": 3, "duree": 1.5, "dispo": 35},
            {"federation": "FF d'Aïkido et de Budo",                 "effectif": 20, "entrainements": 3, "duree": 1.5, "dispo": 35},
            {"federation": "FF de Karaté et DA",                     "effectif": 20, "entrainements": 3, "duree": 1.5, "dispo": 35},
            {"federation": "FF de Boxe",                             "effectif": 12, "entrainements": 3, "duree": 1.5, "dispo": 35},
        ],
    },
    {
        "equipement": "Équipement d'athlétisme",
        "equip_col": "equip_Equipement d'athlétisme",
        "coefficient": 1.2,
        "disciplines": [
            {"federation": "FF d'Athlétisme", "effectif": 30, "entrainements": 3, "duree": 1.5, "dispo": 35},
        ],
    },
]


def calcul_besoins(modele, lic_zone, clubs_zone, equip_zone, pop, fam_cols):
    rows_synthese = []
    rows_detail   = []

    for cat in modele:
        eq_col   = cat["equip_col"]
        coeff    = cat["coefficient"]
        equip_col_label = cat["equipement"]

        # Équipements actuels
        if eq_col in fam_cols:
            actuel = int(equip_zone[eq_col].sum())
        else:
            actuel = 0

        besoin_consolide = 0.0
        lic_total_cat    = 0
        clubs_total_cat  = 0

        for d in cat["disciplines"]:
            fed   = d["federation"]
            G, H, I, J = d["effectif"], d["entrainements"], d["duree"], d["dispo"]

            lic_fed   = int(lic_zone[lic_zone["federation"] == fed]["total"].sum())
            clubs_fed = int(clubs_zone[clubs_zone["federation"] == fed]["total"].sum())

            lic_total_cat   += lic_fed
            clubs_total_cat += clubs_fed

            if lic_fed > 0 and G > 0 and J > 0:
                besoin_k = lic_fed / G * H * I / J
            else:
                besoin_k = 0.0

            besoin_l = besoin_k * coeff
            besoin_consolide += besoin_l

            taux_lic   = round(lic_fed   / pop * 1000, 3) if pop > 0 else 0
            taux_clubs = round(clubs_fed / pop * 1000, 3) if pop > 0 else 0

            rows_detail.append({
                "Catégorie":               equip_col_label,
                "Fédération":              fed,
                "Licenciés":               lic_fed,
                "Taux lic./1 000 hab":     taux_lic,
                "Clubs":                   clubs_fed,
                "Taux clubs/1 000 hab":    taux_clubs,
                "Besoin théorique":        round(besoin_k, 2),
                "Besoin majoré":           round(besoin_l, 2),
            })

        ecart = round(besoin_consolide - actuel, 2)
        rows_synthese.append({
            "Catégorie d'équipements":   equip_col_label,
            "Licenciés (total)":         lic_total_cat,
            "Clubs (total)":             clubs_total_cat,
            "Besoins consolidés":        round(besoin_consolide, 2),
            "Équipements actuels":       actuel,
            "Écart":                     ecart,
        })

    return pd.DataFrame(rows_synthese), pd.DataFrame(rows_detail)


with tab4:
    st.subheader("📐 Modélisation des besoins théoriques en équipements sportifs")
    st.caption(
        "Méthodologie : Besoin théorique = Nb licenciés ÷ Effectif × Séances/sem. × Durée (h) ÷ Disponibilité (h/sem.) "
        "— consolidé par catégorie avec majoration +15 % (salles) ou +20 % (autres). "
        "Source : Tableau de bord Observatoire."
    )

    if pop_affichee == 0:
        st.info("Aucune population renseignée — impossible de calculer les taux.", icon="ℹ️")
    else:
        df_synth, df_detail = calcul_besoins(
            MODELE_EQUIP, lic_zone, clubs_zone, equip_zone, pop_affichee, FAM_COLS
        )

        st.markdown("### Synthèse par catégorie d'équipements")

        def color_ecart(val):
            if isinstance(val, (int, float)):
                if val > 0:
                    return "color: #d9534f; font-weight:bold"   # rouge = déficit
                elif val < 0:
                    return "color: #5cb85c; font-weight:bold"   # vert  = excédent
            return ""

        styled = df_synth.style.map(color_ecart, subset=["Écart"])
        st.dataframe(styled, use_container_width=True, hide_index=True)

        st.markdown(
            "> 🔴 Écart positif = déficit d'équipements &nbsp;·&nbsp; "
            "🟢 Écart négatif = offre excédentaire"
        )

        with st.expander("🔍 Détail par fédération"):
            st.dataframe(df_detail, use_container_width=True, hide_index=True)

        st.divider()
        st.markdown("#### 📥 Exporter la modélisation")
        exp_a, exp_b = st.columns(2)
        with exp_a:
            st.download_button(
                "⬇️ Synthèse besoins (CSV)",
                data=df_synth.to_csv(index=False, sep=";", encoding="utf-8-sig").encode("utf-8-sig"),
                file_name=f"besoins_theoriques_{commune_slug}.csv",
                mime="text/csv",
            )
        with exp_b:
            st.download_button(
                "⬇️ Détail fédérations (CSV)",
                data=df_detail.to_csv(index=False, sep=";", encoding="utf-8-sig").encode("utf-8-sig"),
                file_name=f"besoins_detail_{commune_slug}.csv",
                mime="text/csv",
            )


# ── Export ────────────────────────────────────────────────────────────────────

st.divider()
st.subheader("📥 Exporter les données")


def to_csv(df):
    return df.to_csv(index=False, sep=";", encoding="utf-8-sig").encode("utf-8-sig")


exp1, exp2, exp3 = st.columns(3)

with exp1:
    if not lic_zone.empty and lic_zone["total"].sum() > 0:
        agg = (
            lic_zone.groupby("federation")["total"]
            .sum()
            .reset_index()
            .rename(columns={"federation": "Fédération", "total": "Licenciés"})
            .sort_values("Licenciés", ascending=False)
        )
        st.download_button(
            "⬇️ Licenciés (CSV)",
            data=to_csv(agg),
            file_name=f"licencies_2023_{commune_slug}.csv",
            mime="text/csv",
        )

with exp2:
    if not clubs_zone.empty and clubs_zone["total"].sum() > 0:
        agg = (
            clubs_zone.groupby("federation")["total"]
            .sum()
            .reset_index()
            .rename(columns={"federation": "Fédération", "total": "Clubs"})
            .sort_values("Clubs", ascending=False)
        )
        st.download_button(
            "⬇️ Clubs (CSV)",
            data=to_csv(agg),
            file_name=f"clubs_2023_{commune_slug}.csv",
            mime="text/csv",
        )

with exp3:
    if not equip_zone.empty and nb_equip > 0:
        fam_sums = equip_zone[FAM_COLS].sum()
        fam_df = (
            fam_sums[fam_sums > 0]
            .reset_index()
            .rename(columns={"index": "Famille", 0: "Équipements"})
            .sort_values("Équipements", ascending=False)
        )
        fam_df["Famille"] = fam_df["Famille"].str.replace("equip_", "", regex=False)
        st.download_button(
            "⬇️ Équipements (CSV)",
            data=to_csv(fam_df),
            file_name=f"equipements_2023_{commune_slug}.csv",
            mime="text/csv",
        )
