"""Complex-script text for PyMuPDF HTML boxes. MuPDF does not fall back per glyph across fonts,
so each run of Bengali / Arabic / other text is wrapped in a span with the font that has its glyphs."""
from __future__ import annotations
import html
import re

BN = r"\u0980-\u09FF\u200c\u200d"
AR = r"\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF"
_RUN = re.compile(rf"([{BN}]+)|([{AR}][{AR}\s]*)|([^{BN}{AR}]+)")

FONT_DIR = "/usr/share/fonts/truetype/noto"
CSS = f"""
@font-face {{font-family: bn; src: url(NotoSansBengali-Regular.ttf);}}
@font-face {{font-family: bnb; src: url(NotoSansBengali-Bold.ttf);}}
@font-face {{font-family: ns; src: url(NotoSans-Regular.ttf);}}
@font-face {{font-family: nsb; src: url(NotoSans-Bold.ttf);}}
@font-face {{font-family: ar; src: url(NotoNaskhArabic-Regular.ttf);}}
.bn {{font-family: bn;}} .ns {{font-family: ns;}} .ar {{font-family: ar;}}
b .bn, .bold .bn {{font-family: bnb;}} b .ns, .bold .ns {{font-family: nsb;}}
"""


def spans(text: str) -> str:
    """Escape and wrap text in per-script spans. Newlines become <br>."""
    out = []
    for m in _RUN.finditer(text or ""):
        cls = "bn" if m.group(1) else "ar" if m.group(2) else "ns"
        out.append(f'<span class="{cls}">{html.escape(m.group(0))}</span>')
    return "".join(out).replace("\n", "<br>")


BN_DIGITS = str.maketrans("0123456789", "০১২৩৪৫৬৭৮৯")


def fmt_mark(value: float, lang: str) -> str:
    """2.5 -> '2½' ; 0.25 -> '¼' ; 3 -> '3' ; Bengali digits when lang == 'bn'."""
    whole = int(value)
    frac = round(value - whole, 2)
    sym = {0.25: "¼", 0.5: "½", 0.75: "¾"}.get(frac, "")
    if frac and not sym:
        s = f"{value:g}"
    else:
        s = (str(whole) if whole or not sym else "") + sym
    return s.translate(BN_DIGITS) if lang == "bn" else s


T = {
    "bn": {"provisional": "অস্থায়ী — চূড়ান্ত নয়", "final": "চূড়ান্ত", "school": "প্রতিষ্ঠান", "exam": "পরীক্ষা",
           "class": "শ্রেণি", "section": "শাখা", "subject": "বিষয়", "name": "নাম", "roll": "রোল",
           "question": "প্রশ্ন", "part": "অংশ", "max": "পূর্ণমান", "obtained": "প্রাপ্ত", "total": "মোট",
           "strengths": "শক্তির দিক", "weaknesses": "দুর্বলতা", "suggestions": "উন্নতির পরামর্শ", "summary": "সারসংক্ষেপ",
           "not_attempted": "উত্তর দেয়নি", "not_counted": "গণ্য নয়", "missing": "অনুপস্থিত", "more_errors": "আরও {n}টি ভুল",
           "rough": "খসড়া", "date": "তারিখ", "page": "পৃষ্ঠা"},
    "en": {"provisional": "PROVISIONAL — not final", "final": "Final", "school": "School", "exam": "Exam",
           "class": "Class", "section": "Section", "subject": "Subject", "name": "Name", "roll": "Roll",
           "question": "Question", "part": "Part", "max": "Max", "obtained": "Marks", "total": "Total",
           "strengths": "Strengths", "weaknesses": "Weaknesses", "suggestions": "Suggestions", "summary": "Summary",
           "not_attempted": "Not attempted", "not_counted": "Not counted", "missing": "Missing",
           "more_errors": "{n} more errors", "rough": "Rough work", "date": "Date", "page": "Page"},
}
