# exams/utils/pdf/pdf_tables.py
from reportlab.platypus import Table, TableStyle, Paragraph, Spacer, PageBreak
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT

from exams.app_utils.pdf.autofit import autofit

from exams.views_helpers import build_best_worst_tables



styles = getSampleStyleSheet()
TITLE_STYLE = ParagraphStyle("title", parent=styles["Title"], alignment=TA_CENTER, fontSize=13, leading=14)
SMALL_CENTER = ParagraphStyle("small_center", parent=styles["Normal"], alignment=TA_CENTER, fontSize=9)
SMALL_LEFT = ParagraphStyle("small_left", parent=styles["Normal"], alignment=TA_LEFT, fontSize=9)
SMALL_BOLD = ParagraphStyle("small_bold", parent=styles["Normal"], alignment=TA_LEFT, fontSize=9)
FOOTER_STYLE = ParagraphStyle("footer", parent=styles["Normal"], alignment=TA_CENTER, fontSize=9)

# Colors chosen to match your sample (approx)
HEADER_BG = colors.HexColor("#cfeefc")
STUDENTS_BG = colors.HexColor("#BEFEF6")
GRADES_BG = colors.HexColor("#FEFB96")
OWNERSHIP_BG = colors.HexColor("#d7f2ff")
TABLE_BORDER = colors.black

def _to_num_safe(v):
    try:
        if v is None:
            return 0
        return float(v)
    except Exception:
        try:
            return int(v)
        except Exception:
            return 0

# ---------- Header Block ----------
# Small style used for the title / region text (adjust as needed)
TITLE_STYLE = ParagraphStyle("title", fontName="Helvetica-Bold", fontSize=12, alignment=TA_CENTER, leading=14)
SMALL_LEFT = ParagraphStyle("small_left", fontName="Helvetica-Bold", fontSize=12, alignment=TA_LEFT, leading=14)

# Simple header function that returns a single Table (autofit row for MKOA)
def pdf_header_block_simple(region, year):
    """
    Simple header table:
     - Two title rows span both columns
     - Third row: label + value (MKOA / REGION) as two columns (autofit)
     - Returns a single Table (safe to story.append(tbl))
    """

    # FIX: If region comes as tuple (id, name)
    if isinstance(region, tuple):
        region = type("RegionTemp", (), {"name": region[1]})()

    region_name = getattr(region, "name", str(region) if region is not None else "")

    # Use Paragraph for nicer text rendering (but could be raw strings)
    title1 = Paragraph("OFISI YA RAIS - TAWALA ZA MIKOA NA SERIKALI ZA MITAA", TITLE_STYLE)
    title2 = Paragraph(f"MATOKEO YA DARASA LA SABA - {year}", TITLE_STYLE)

    label = Paragraph("MKOA / REGION:", SMALL_LEFT)
    value = Paragraph(region_name, SMALL_LEFT)

    # Data: two columns, with first two rows spanning both columns
    data = [
        [title1, ""],   # row 0 -> will span (0,0)-(1,0)
        [title2, ""],   # row 1 -> will span (0,1)-(1,1)
        [label, value], # row 2 -> two separate cells (autofit)
    ]

    # Create table without fixed colWidths so ReportLab will auto-calc widths.
    tbl = Table(data, hAlign="LEFT")  # no colWidths -> auto sizing

    tbl.setStyle(TableStyle([
        # Title rows span both columns and are centered in a bold box
        ("SPAN", (0,0), (1,0)),
        ("SPAN", (0,1), (1,1)),
        ("BACKGROUND", (0,0), (1,1), colors.HexColor("#cfeefc")),
        ("ALIGN", (0,0), (1,1), "CENTER"),
        ("FONTNAME", (0,0), (1,1), "Helvetica-Bold"),
        ("VALIGN", (0,0), (1,1), "MIDDLE"),
        ("BOX", (0,0), (1,1), 1, colors.black),

        # MKOA row: light grid, left aligned label/value, small paddings
        ("GRID", (0,2), (1,2), 0.4, colors.HexColor("#999999")),
        ("ALIGN", (0,2), (0,2), "LEFT"),
        ("ALIGN", (1,2), (1,2), "LEFT"),
        ("BOX", (0,0), (1,1), 1, colors.black),
    ]))

    return tbl






# ---------- Students block ----------
def pdf_students_block(t):
    def pct(x, total):
        try:
            return f"{(x / total) * 100:.1f}%"
        except:
            return "0%"

    def label(text):
        return Paragraph(f"<b>{text}</b>", SMALL_LEFT)

    # Build the table data
    data = [
        [Paragraph("WANAFUNZI", TITLE_STYLE)],
        [
            Paragraph("", SMALL_LEFT),
            Paragraph("WAS F", SMALL_CENTER),
            Paragraph("%", SMALL_CENTER),
            Paragraph("WAV M", SMALL_CENTER),
            Paragraph("%", SMALL_CENTER),
            Paragraph("JUMLA", SMALL_CENTER),
            Paragraph("%", SMALL_CENTER),
        ],

        # Row that must NOT wrap column 0
        [
            label("WALIOSAJILIWA"),
            t.get("reg_f", 0), pct(t.get("reg_f", 0), t.get("reg", 0)),
            t.get("reg_m", 0), pct(t.get("reg_m", 0), t.get("reg", 0)),
            t.get("reg", 0), "100%" if t.get("reg", 0) else "0%",
        ],

        # Row that must NOT wrap column 0
        [
            label("WENYE MATOKEO"),
            t.get("sat_f", 0), pct(t.get("sat_f", 0), t.get("reg", 0)),
            t.get("sat_m", 0), pct(t.get("sat_m", 0), t.get("reg", 0)),
            t.get("sat", 0), pct(t.get("sat", 0), t.get("reg", 0)),
        ],

        [
            label("WASIOFANYA"),
            t.get("abs_f", 0), pct(t.get("abs_f", 0), t.get("reg", 0)),
            t.get("abs_m", 0), pct(t.get("abs_m", 0), t.get("reg", 0)),
            t.get("abs", 0), pct(t.get("abs", 0), t.get("reg", 0)),
        ],

        [
            label("WASTANI WA JML"),
            t.get("avg", ""),
            t.get("grade", ""),
            t.get("status", ""), "", "",
        ],

        [
            label("JUMLA YA SHULE"),
            t.get("school_count", 0), "", "", "", "",
        ],
    ]

    # ---------------------------------------------
    # MANUAL COLUMN ADJUSTMENT:
    # Column 0 gets fixed width, others auto-fit
    # ---------------------------------------------
    col_widths = [120] + [None] * (len(data[1]) - 1)

    tbl = Table(data, colWidths=col_widths, hAlign="LEFT")

    tbl.setStyle(TableStyle([
        ("SPAN", (0,0), (-1,0)),
        ("BACKGROUND", (0,0), (-1,0), STUDENTS_BG),
        ("GRID", (0,0), (-1,-1), 0.5, TABLE_BORDER),
        ("ALIGN", (1,1), (-1,-1), "CENTER"),
        ("ALIGN", (0,0), (-1,0), "CENTER"),
        ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
        ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
        ("LEFTPADDING", (0,2), (0,-1), 4),
    ]))

    return tbl



# ---------- Grades summary block ----------
def pdf_grades_block(grades, totals):
    """
    grades: dict keys af, bf, cf, df, ef, am, bm, cm, dm, em, a,b,c,d,e
    """
    # header + structure (7 columns)
    header_text = "UFAULU WA MADARAJA – JUMLA"
    data = [
        [header_text, "", "", "", "", "", ""],
        ["DARAJA-JINSI", "A", "%", "B", "%", "C", "%"],  # second row as labels, we'll show NO and % in next rows
    ]

    # We'll create WAS, WAV, JUMLA rows with NO and % columns condensed:
    sat_f = totals.get("sat_f", 0)
    sat_m = totals.get("sat_m", 0)
    sat = totals.get("sat", 0)

    def pct_no(val, denom):
        try:
            return round((float(val) / float(denom)) * 100, 1) if denom else 0.0
        except Exception:
            return 0.0

    # WAS row: for each grade show NO and we will show % in separate column (this sample assumes merging layout)
    # For consistent columns, we'll use simplified layout: grade NO as single column, percent shown adjacent in next % column
    # But to match your visual, we'll place NO in the grade columns and % is shown in adjacent column slots.
    # To fit our 7-column scheme, we'll use: [label, A_NO, B_NO, C_NO, D_NO, E_NO, PASS_A_C]
    was_row = [
        "WAS",
        int(grades.get("af", 0)),
        int(grades.get("bf", 0)),
        int(grades.get("cf", 0)),
        int(grades.get("df", 0)),
        int(grades.get("ef", 0)),
        int(grades.get("af", 0) + grades.get("bf", 0) + grades.get("cf", 0))
    ]
    wav_row = [
        "WAV",
        int(grades.get("am", 0)),
        int(grades.get("bm", 0)),
        int(grades.get("cm", 0)),
        int(grades.get("dm", 0)),
        int(grades.get("em", 0)),
        int(grades.get("am", 0) + grades.get("bm", 0) + grades.get("cm", 0))
    ]
    jumla_row = [
        "JUMLA",
        int(grades.get("a", 0)),
        int(grades.get("b", 0)),
        int(grades.get("c", 0)),
        int(grades.get("d", 0)),
        int(grades.get("e", 0)),
        int(grades.get("a", 0) + grades.get("b", 0) + grades.get("c", 0))
    ]

    data.append(was_row)
    data.append(wav_row)
    data.append(jumla_row)

    tbl = autofit(data)
    tbl.setStyle(TableStyle([
        ("SPAN", (0,0), (6,0)),
        ("BACKGROUND", (0,0), (6,0), GRADES_BG),
        ("GRID", (0,0), (-1,-1), 0.5, TABLE_BORDER),
        ("ALIGN", (0,0), (-1,-1), "CENTER"),
        ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
        ("FONTNAME", (0,1), (-1,1), "Helvetica-Bold"),
    ]))

    return tbl

# ---------- Ownership tables block ----------
def pdf_ownership_block(ownership_list):
    """
    Returns a list of Tables for government and non-government blocks, auto-fit.
    Each ownership dict expected keys:
      owner, total_school, sat, af,bf,cf,df,ef,am,bm,cm,dm,em,a,b,c,d,e,pass_f,pass_m,pass_total
    """
    if not ownership_list:
        return []

    result_tables = []

    for o in ownership_list:
        owner = o.get("owner", "GOVERNMENT")
        total_school = o.get("total_school", "")
        sat = o.get("sat", 0)

        header_text = f"UFAULU WA MADARAJA – {owner} – SHULE {total_school} – WALIOFANYA {sat}"
        data = [
            [header_text, "", "", "", "", "", ""],
            ["", "A", "B", "C", "D", "E", "PASS A–C"],
            ["WAS",
             int(o.get("af", 0)), int(o.get("bf", 0)), int(o.get("cf", 0)),
             int(o.get("df", 0)), int(o.get("ef", 0)), int(o.get("pass_f", 0))],
            ["WAV",
             int(o.get("am", 0)), int(o.get("bm", 0)), int(o.get("cm", 0)),
             int(o.get("dm", 0)), int(o.get("em", 0)), int(o.get("pass_m", 0))],
            ["JUMLA",
             int(o.get("a", 0)), int(o.get("b", 0)), int(o.get("c", 0)),
             int(o.get("d", 0)), int(o.get("e", 0)), int(o.get("pass_total", 0))],
            # optional WASTANI WA JML row may be appended by the caller as separate small table
        ]

        tbl = autofit(data)
        tbl.setStyle(TableStyle([
            ("SPAN", (0,0), (6,0)),
            ("BACKGROUND", (0,0), (6,0), OWNERSHIP_BG),
            ("GRID", (0,0), (-1,-1), 0.5, TABLE_BORDER),
            ("ALIGN", (0,0), (-1,-1), "CENTER"),
            ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
            ("FONTNAME", (0,1), (-1,1), "Helvetica-Bold"),
        ]))

        result_tables.append(tbl)

    return result_tables













# ---------- District summary block ----------
def pdf_district_summary_block(districts_rows, districts_totals):
    """
    districts_rows: list of dicts with keys: district_name, total, pass, fail, pass_pct, male, female
    districts_totals: same keys with totals
    """
    header = ["District", "Total", "Pass", "Fail", "% Pass", "Male", "Female"]
    data = [header]
    for r in districts_rows:
        data.append([
            r.get("district_name", ""),
            r.get("total", 0),
            r.get("pass", 0),
            r.get("fail", 0),
            r.get("pass_pct", 0.0),
            r.get("male", 0),
            r.get("female", 0),
        ])
    # totals row
    data.append([
        "TOTAL",
        districts_totals.get("total", 0),
        districts_totals.get("pass", 0),
        districts_totals.get("fail", 0),
        districts_totals.get("pass_pct", 0.0),
        districts_totals.get("male", 0),
        districts_totals.get("female", 0),
    ])

    tbl = autofit(data)
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,0), colors.HexColor("#e6f7ff")),
        ("GRID", (0,0), (-1,-1), 0.5, TABLE_BORDER),
        ("ALIGN", (1,1), (-1,-1), "CENTER"),
    ]))
    return tbl

# ---------- Footer paragraph ----------
def pdf_footer_block(footer_text):
    return Paragraph(footer_text, FOOTER_STYLE)










def pdf_school_ranking_block(rows, totals=None):
    """
    Convert school_rank_block.html into a ReportLab table.

    rows: list of dicts:
        {
            "school_name": "",
            "district": "",
            "total": 0,
            "pass": 0,
            "fail": 0,
            "pass_pct": 0,
            "male": 0,
            "female": 0
        }

    totals: optional dict for total row.
    """

    header = [
        "SHULE / SCHOOL",
        "WILAYA / DISTRICT",
        "TOTAL",
        "PASS",
        "FAIL",
        "%PASS",
        "MALE",
        "FEMALE"
    ]

    data = [header]

    # Add row entries
    for s in rows:
        data.append([
            Paragraph(s["school_name"], SMALL_LEFT),
            Paragraph(s["district"], SMALL_LEFT),
            s["total"],
            s["pass"],
            s["fail"],
            f"{s['pass_pct']}%",
            s["male"],
            s["female"]
        ])

    # Totals row (optional)
    if totals:
        data.append([
            Paragraph("<b>TOTAL</b>", SMALL_LEFT),
            "",
            totals.get("total", 0),
            totals.get("pass", 0),
            totals.get("fail", 0),
            f"{totals.get('pass_pct', 0)}%",
            totals.get("male", 0),
            totals.get("female", 0)
        ])

    # Table uses autofit for all columns
    tbl = Table(data, hAlign="LEFT")

    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,0), colors.HexColor("#cfeefc")),
        ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
        ("ALIGN", (2,1), (-1,-1), "CENTER"),
        ("VALIGN", (0,0), (-1,-1), "MIDDLE"),

        ("GRID", (0,0), (-1,-1), 0.5, TABLE_BORDER),

        # Slight left padding for text columns
        ("LEFTPADDING", (0,1), (1,-1), 4),
        ("RIGHTPADDING", (0,1), (1,-1), 4),
    ]))

    return tbl







# Small centered and small-left styles
BEST10_HEADER_STYLE = ParagraphStyle(
    name="best10hdr",
    alignment=TA_CENTER,
    fontSize=10,
    leading=12,
    fontName="Helvetica-Bold"
)

BEST10_CELL_STYLE = ParagraphStyle(
    name="best10cell",
    alignment=TA_LEFT,
    fontSize=9,
    leading=11,
    fontName="Helvetica"
)



























# --------------------------------------------------------
# BEST/WORST SCHOOL RANK PDF BLOCKS
# --------------------------------------------------------

def pdf_best_table_block(title, rows):
    """Builds a ReportLab block for Top/Bottom 10 table."""
    header = [title]

    tbl_header = [
        ["Rank", "School", "Total", "A", "B", "C", "D", "E", "PASS A–C", "AVG"]
    ]

    data = []

    for i, r in enumerate(rows, start=1):

        # FIX: Ensure we retrieve the school name using any available key
        school_name = (
            r.get("school_name")
            or r.get("school")
            or r.get("name")
            or r.get("school_code")
            or "N/A"
        )

        data.append([
            i,
            school_name,
            r.get("total", 0),
            r.get("a", 0),
            r.get("b", 0),
            r.get("c", 0),
            r.get("d", 0),
            r.get("e", 0),
            r.get("pass_ac", 0),
            r.get("avg", 0),
        ])

    tbl = Table([header] + tbl_header + data, repeatRows=1)

    tbl.setStyle(TableStyle([
        ("SPAN", (0,0), (-1,0)),
        ("BACKGROUND", (0,0), (-1,0), colors.HexColor("#d7f2ff")),
        ("BACKGROUND", (0,1), (-1,1), colors.lightgrey),
        ("GRID", (0,0), (-1,-1), 0.5, colors.black),
        ("ALIGN", (0,0), (-1,-1), "CENTER"),
        ("FONTNAME", (0,0), (-1,1), "Helvetica-Bold"),
    ]))

    return tbl



def pdf_best_worst_group(region_id, year):
    """
    Builds all BEST/WORST tables as ReportLab blocks from best10 logic.
    """

    result = build_best_worst_tables(region_id, year)

    blocks = []

    # Top 10
    blocks.append(pdf_best_table_block("TOP 10 SCHOOLS", result["top10"]))
    blocks.append(Spacer(1, 14))

    # Bottom 10
    blocks.append(pdf_best_table_block("BOTTOM 10 SCHOOLS", result["bottom10"]))
    blocks.append(Spacer(1, 14))

    # Top 10 Big Schools (>=30)
    blocks.append(pdf_best_table_block("TOP 10 SCHOOLS (≥30 CANDIDATES)", result["top10_big"]))
    blocks.append(Spacer(1, 14))

    # Bottom 10 Big Schools (≥30)
    blocks.append(pdf_best_table_block("BOTTOM 10 SCHOOLS (≥30 CANDIDATES)", result["bottom10_big"]))
    blocks.append(Spacer(1, 14))

    # Top 10 GOV
    blocks.append(pdf_best_table_block("TOP 10 GOVERNMENT SCHOOLS", result["top10_gov"]))
    blocks.append(Spacer(1, 14))

    return blocks






SMALL = ParagraphStyle(
    name="small",
    fontSize=7,
    leading=9
)

HEADER = ParagraphStyle(
    name="header",
    fontSize=13,
    leading=15,
    alignment=1,
    fontName="Helvetica-Bold"
)

def pct(val, total):
    return round((val / total * 100), 2) if total else 0


def pdf_ward_ranking_table(region, year, wards):
    """
    Builds Ward Ranking table (ReportLab)
    """
    data = []

    # ====== TITLE ======
    data.append([
        Paragraph(f"WARD RANKING – {region.name} – {year}", HEADER)
    ] + [""] * 29)

    # ====== HEADER ROW 1 ======
    data.append([
        "NO", "WARD NAME", "DISTRICT",
        "A", "", "",
        "B", "", "",
        "C", "", "",
        "D", "", "",
        "E", "", "",
        "TOTAL", "SCH",
        "PASS A–C", "", "",
        "% PASS", "", "",
        "AVG"
    ])

    # ====== HEADER ROW 2 ======
    data.append([
        "", "", "",
        "F", "M", "T",
        "F", "M", "T",
        "F", "M", "T",
        "F", "M", "T",
        "F", "M", "T",
        "", "",
        "F", "M", "T",
        "F%", "M%", "T%",
        ""
    ])

    # ====== DATA ROWS ======
    for w in wards:
        data.append([
            w["rank"],
            w["name"],
            w["district"],

            w["af"], w["am"], w["a"],
            w["bf"], w["bm"], w["b"],
            w["cf"], w["cm"], w["c"],
            w["df"], w["dm"], w["d"],
            w["ef"], w["em"], w["e"],

            w["total_std"],
            w["total_schools"],

            w["pass_f"], w["pass_m"], w["pass_t"],
            pct(w["pass_f"], w["total_std"]),
            pct(w["pass_m"], w["total_std"]),
            pct(w["pass_t"], w["total_std"]),

            w["avg_score"],
        ])

    col_widths = [20, 90, 70] + [24]*15 + [40, 30] + [28]*3 + [32]*3 + [36]

    tbl = Table(data, colWidths=col_widths, repeatRows=3)

    tbl.setStyle(TableStyle([
        ("SPAN", (0,0), (-1,0)),
        ("BACKGROUND", (0,0), (-1,0), colors.HexColor("#CFEAFB")),
        ("ALIGN", (0,0), (-1,0), "CENTER"),
        ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),

        ("GRID", (0,1), (-1,-1), 0.5, colors.black),

        ("BACKGROUND", (0,1), (-1,2), colors.HexColor("#E2F7FD")),
        ("FONTNAME", (0,1), (-1,2), "Helvetica-Bold"),
        ("ALIGN", (0,1), (-1,-1), "CENTER"),

        ("ALIGN", (1,3), (2,-1), "LEFT"),
        ("FONTSIZE", (0,1), (-1,-1), 7),
    ]))

    return tbl


# pdf_tables.py
from reportlab.platypus import Table, TableStyle, Paragraph
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet

styles = getSampleStyleSheet()

def pdf_district_summary_block(ctx):
    t = ctx["totals"]

    data = [
        ["DISTRICT SUMMARY"],
        ["WALIOSAJILIWA",
         t["af"], t["am"], t["a"],
         t["bf"], t["bm"], t["b"],
         t["cf"], t["cm"], t["c"],
         t["df"], t["dm"], t["d"],
         t["ef"], t["em"], t["e"],
         t["total_std"]
        ],
        ["PASS (A–C)",
         t["pass_f"], t["pass_m"], t["pass_t"],
         "", "", "", "", "", "", "", "", "", "", "", "", ""
        ],
        ["AVERAGE SCORE", "", "", "", "", "", "", "", "", "", "", "", "", "", "", t["avg_score"]],
        ["TOTAL SCHOOLS", "", "", "", "", "", "", "", "", "", "", "", "", "", "", t["total_schools"]],
    ]

    table = Table(data, colWidths=[70] + [25]*15)

    table.setStyle(TableStyle([
        ("SPAN", (0,0), (-1,0)),
        ("BACKGROUND", (0,0), (-1,0), colors.HexColor("#CFEAFB")),
        ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
        ("ALIGN", (1,1), (-1,-1), "CENTER"),
        ("GRID", (0,0), (-1,-1), 0.5, colors.black),
    ]))

    return table


from reportlab.platypus import Table, TableStyle
from reportlab.lib import colors

def simple_rank_table(headers, rows):
    data = [headers]
    for r in rows:
        data.append(r)

    t = Table(data, repeatRows=1)
    t.setStyle(TableStyle([
        ("GRID", (0,0), (-1,-1), 0.5, colors.black),
        ("BACKGROUND", (0,0), (-1,0), colors.lightgrey),
        ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
        ("ALIGN", (2,1), (-1,-1), "CENTER"),
    ]))
    return t
