import io

import altair as alt
import pandas as pd
import streamlit as st

from utils.db import district_summary, list_communes, list_districts, station_level_results
from utils.ui import stat_card


def render():
    district_id = st.session_state.get("district_id")
    districts = {d["id"]: d["name"] for d in list_districts()}

    if not district_id:
        st.info("أضف دائرة انتخابية أولاً.")
        return

    st.caption(f"الدائرة الحالية: **{districts[district_id]}**")

    communes = list_communes(district_id)
    commune_labels = {"": f"كل الدائرة ({sum(c['station_count'] for c in communes)} مكتب)"}
    commune_labels.update(
        {c["commune"]: f"{c['commune'] or 'بدون جماعة'} ({c['station_count']} مكتب)" for c in communes}
    )
    scope_commune = st.selectbox(
        ":material/location_on: نطاق النتائج",
        options=list(commune_labels.keys()),
        format_func=lambda c: commune_labels[c],
    )

    totals, candidate_rows, reported = district_summary(
        district_id, commune=scope_commune if scope_commune else None
    )

    reported_count_badge = reported["reported_count"] or 0
    total_count_badge = reported["total_count"] or 0
    if total_count_badge and reported_count_badge == total_count_badge:
        st.badge("اكتمل إدخال جميع المكاتب", icon=":material/check_circle:", color="green")
    elif reported_count_badge:
        st.badge("جارٍ إدخال النتائج", icon=":material/pending:", color="orange")
    else:
        st.badge("لم يتم إدخال أي نتائج بعد", icon=":material/schedule:", color="blue")

    registered = totals["registered"] or 0
    voters = totals["voters"] or 0
    blank = totals["blank"] or 0
    null_votes = totals["null_votes"] or 0
    turnout = (voters / registered * 100) if registered else 0

    reported_count = reported["reported_count"] or 0
    total_count = reported["total_count"] or 0

    st.progress(
        (reported_count / total_count) if total_count else 0,
        text=f"مكاتب أُدخلت نتائجها: {reported_count} من {total_count}",
    )

    c1, c2, c3, c4 = st.columns(4)
    with c1:
        stat_card(":material/how_to_reg:", "الناخبون المسجلون", f"{registered:,}", accent="blue")
    with c2:
        stat_card(":material/how_to_vote:", "عدد المصوتين", f"{voters:,}", accent="blue")
    with c3:
        stat_card(":material/percent:", "نسبة المشاركة", f"{turnout:.1f}%", accent="orange")
    with c4:
        stat_card(":material/block:", "الأصوات الملغاة والبيضاء", f"{(blank + null_votes):,}", accent="red")

    st.subheader(":material/how_to_vote: نتائج المترشحين واللوائح")

    display_df = None
    total_candidate_votes = sum(c["total_votes"] for c in candidate_rows) if candidate_rows else 0

    if not candidate_rows:
        st.info("لا يوجد مترشحون مسجلون لهذه الدائرة بعد.")
    elif total_candidate_votes == 0:
        st.info("لم يتم تسجيل أي صوت بعد فهاد النطاق.")
    else:
        df = pd.DataFrame(candidate_rows).sort_values("total_votes", ascending=False).reset_index(drop=True)
        df.insert(0, "الترتيب", df.index + 1)
        df["نسبة الأصوات"] = df["total_votes"] / total_candidate_votes * 100
        df = df.rename(
            columns={"party": "الحزب", "name": "المترشح / اللائحة", "total_votes": "عدد الأصوات"}
        )
        display_df = df[["الترتيب", "الحزب", "المترشح / اللائحة", "عدد الأصوات", "نسبة الأصوات"]]

        leader = display_df.iloc[0]
        st.badge(
            f"المتصدر: {leader['المترشح / اللائحة']} ({leader['الحزب']}) — {leader['عدد الأصوات']:,} صوت",
            icon=":material/military_tech:",
            color="orange",
        )

        st.dataframe(
            display_df,
            hide_index=True,
            width="stretch",
            column_config={
                "الترتيب": st.column_config.NumberColumn("الترتيب", format="%d"),
                "نسبة الأصوات": st.column_config.ProgressColumn(
                    "نسبة الأصوات", format="%.1f%%", min_value=0, max_value=100
                ),
            },
        )

        pie_chart = (
            alt.Chart(df)
            .mark_arc(innerRadius=70, stroke="#ffffff", strokeWidth=2)
            .encode(
                theta=alt.Theta("عدد الأصوات:Q", stack=True),
                color=alt.Color(
                    "المترشح / اللائحة:N",
                    legend=alt.Legend(title="المترشح / اللائحة", orient="bottom", columns=2),
                ),
                order=alt.Order("عدد الأصوات:Q", sort="descending"),
                tooltip=[
                    alt.Tooltip("المترشح / اللائحة:N"),
                    alt.Tooltip("الحزب:N"),
                    alt.Tooltip("عدد الأصوات:Q", format=","),
                    alt.Tooltip("نسبة الأصوات:Q", format=".1f", title="النسبة (%)"),
                ],
            )
        )
        st.altair_chart(pie_chart, width="stretch")

    if total_count:
        scope_label = scope_commune or "كل الدائرة"
        with st.expander(":material/download: تصدير النتائج"):
            summary_df = pd.DataFrame(
                [
                    {"البيان": "الدائرة", "القيمة": districts[district_id]},
                    {"البيان": "النطاق", "القيمة": scope_label},
                    {"البيان": "الناخبون المسجلون", "القيمة": registered},
                    {"البيان": "عدد المصوتين", "القيمة": voters},
                    {"البيان": "نسبة المشاركة (%)", "القيمة": round(turnout, 2)},
                    {"البيان": "الأوراق البيضاء والملغاة", "القيمة": blank + null_votes},
                    {"البيان": "مكاتب أُدخلت نتائجها", "القيمة": f"{reported_count} من {total_count}"},
                ]
            )
            station_rows = station_level_results(district_id)
            if scope_commune:
                station_rows = [r for r in station_rows if r["الجماعة"] == scope_commune]
            station_df = pd.DataFrame(station_rows)

            excel_buffer = io.BytesIO()
            with pd.ExcelWriter(excel_buffer, engine="openpyxl") as writer:
                summary_df.to_excel(writer, sheet_name="ملخص المشاركة", index=False)
                if display_df is not None:
                    display_df.to_excel(writer, sheet_name="نتائج المترشحين", index=False)
                station_df.to_excel(writer, sheet_name="تفصيل حسب المكتب", index=False)

            st.download_button(
                "تحميل النتائج كملف Excel",
                data=excel_buffer.getvalue(),
                file_name=f"{districts[district_id]}_{scope_label}_نتائج.xlsx",
                mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                icon=":material/download:",
            )

            if display_df is not None:
                csv = display_df.to_csv(index=False).encode("utf-8-sig")
                st.download_button(
                    "تحميل نتائج المترشحين كملف CSV",
                    data=csv,
                    file_name=f"{districts[district_id]}_{scope_label}_نتائج.csv",
                    mime="text/csv",
                    icon=":material/download:",
                )


if __name__ == "__main__":
    render()
