"""
Report generation: HTML, PDF, DOCX, XLSX — formal legal/IP bulletin styling.

Reports are unbranded and labelled for "Iran" only.
Terminology: Applicant (not Owner), Publication (not Advertisement).
Mark is shown in target-language transliteration + translation.
Goods/services and disclaimer are translated; disclaimer is its own field.
Each entry links to download the source PDF.
"""
import os
import datetime as dt
from jinja2 import Environment, FileSystemLoader, select_autoescape
from ..config import config

TEMPLATE_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "report_templates")
_env = Environment(
    loader=FileSystemLoader(TEMPLATE_DIR),
    autoescape=select_autoescape(["html", "xml"]),
)

DESIGNS = ["bulletin", "minimal", "compact"]
LANGUAGES = {"en": "English", "fa": "Farsi", "zh": "Chinese", "ar": "Arabic"}
RTL_LANGS = {"fa", "ar"}


def _labels(lang):
    en = {
        "title": "Trademark Publications",
        "subtitle": "Notice of Applications Filed for Registration",
        "jurisdiction_label": "Jurisdiction",
        "pub_date": "Publication Date", "opp_deadline": "Opposition Deadline",
        "pub_no": "Publication No.", "app_no": "Application No.",
        "app_date": "Filing Date",
        "mark": "Mark", "translit": "Transliteration", "translation": "Translation",
        "applicant": "Applicant", "rep": "Legal Representative",
        "class": "Class(es)", "goods": "Goods / Services",
        "disclaimer": "Disclaimer", "nationality": "Nationality",
        "source": "Source", "download": "Download source PDF", "no": "No.",
        "entry": "Entry", "applications": "Applications",
        "pending": "[translation pending]",
        "note": "Any interested party may file a notice of opposition within "
                "thirty (30) days of the publication date.",
        "footer": "This bulletin is provided for opposition-watch purposes.",
    }
    fa = {
        "title": "انتشار علائم تجاری",
        "subtitle": "آگهی تقاضای ثبت علامت تجاری",
        "jurisdiction_label": "حوزه",
        "pub_date": "تاریخ انتشار", "opp_deadline": "مهلت اعتراض",
        "pub_no": "شماره آگهی", "app_no": "شماره اظهارنامه", "app_date": "تاریخ اظهارنامه",
        "mark": "علامت", "translit": "آوانگاری", "translation": "ترجمه",
        "applicant": "متقاضی", "rep": "نماینده قانونی",
        "class": "طبقه", "goods": "کالا و خدمات",
        "disclaimer": "اغماض", "nationality": "تابعیت",
        "source": "منبع", "download": "دانلود فایل منبع", "no": "ردیف",
        "entry": "ردیف", "applications": "تعداد",
        "pending": "[در انتظار ترجمه]",
        "note": "هر ذینفع می‌تواند ظرف سی (۳۰) روز از تاریخ انتشار اعتراض خود را تسلیم نماید.",
        "footer": "این نشریه برای پایش اعتراضات تهیه شده است.",
    }
    zh = {
        "title": "商标公告",
        "subtitle": "商标注册申请公告",
        "jurisdiction_label": "司法管辖区",
        "pub_date": "公告日期", "opp_deadline": "异议截止日期",
        "pub_no": "公告号", "app_no": "申请号", "app_date": "申请日期",
        "mark": "商标", "translit": "音译", "translation": "翻译",
        "applicant": "申请人", "rep": "法定代理人",
        "class": "类别", "goods": "商品/服务",
        "disclaimer": "放弃专用权声明", "nationality": "国籍",
        "source": "来源", "download": "下载源文件", "no": "序号",
        "entry": "条目", "applications": "申请数量",
        "pending": "[待翻译]",
        "note": "任何利害关系人可自公告日起三十（30）日内提出异议。",
        "footer": "本公告仅供异议监测之用。",
    }
    ar = {
        "title": "نشرة العلامات التجارية",
        "subtitle": "إشعار بطلبات تسجيل العلامات التجارية",
        "jurisdiction_label": "الاختصاص",
        "pub_date": "تاريخ النشر", "opp_deadline": "الموعد النهائي للاعتراض",
        "pub_no": "رقم النشر", "app_no": "رقم الطلب", "app_date": "تاريخ الإيداع",
        "mark": "العلامة", "translit": "النقحرة", "translation": "الترجمة",
        "applicant": "مقدم الطلب", "rep": "الممثل القانوني",
        "class": "الفئة/الفئات", "goods": "السلع / الخدمات",
        "disclaimer": "تنازل", "nationality": "الجنسية",
        "source": "المصدر", "download": "تنزيل الملف المصدر", "no": "رقم",
        "entry": "إدخال", "applications": "الطلبات",
        "pending": "[الترجمة قيد الإعداد]",
        "note": "يجوز لأي طرف ذي مصلحة تقديم اعتراض خلال ثلاثين (30) يومًا من تاريخ النشر.",
        "footer": "تُقدَّم هذه النشرة لأغراض مراقبة الاعتراضات.",
    }
    return {"fa": fa, "zh": zh, "ar": ar}.get(lang, en)


def _mark_primary(a, lang):
    """The headline mark string for an entry, in the target language."""
    if lang == "fa":
        return a.mark_text or a.mark_translit or "—"
    v = a.tr("mark_translit", lang) or a.tr("mark_translation", lang)
    return v or "[translation pending]"


def render_html(issue, applications, design="bulletin", lang="en", base_url="", embed_images=False):
    tpl = _env.get_template("report.html")
    return tpl.render(
        issue=issue, applications=applications, design=design, lang=lang,
        L=_labels(lang), rtl=(lang in RTL_LANGS), base_url=base_url,
        jurisdiction=config.JURISDICTION, mark_primary=_mark_primary,
        embed_images=embed_images,
        generated=dt.datetime.utcnow().strftime("%Y-%m-%d %H:%M UTC"),
    )


def render_pdf(issue, applications, design="bulletin", lang="en", base_url=""):
    from weasyprint import HTML
    # Embed images via local file paths so the PDF is self-contained.
    html = render_html(issue, applications, design, lang, base_url, embed_images=True)
    return HTML(string=html, base_url=base_url or TEMPLATE_DIR).write_pdf()


def render_docx(issue, applications, design="bulletin", lang="en", base_url=""):
    import io
    from docx import Document
    from docx.shared import Pt, RGBColor, Inches
    from docx.enum.text import WD_ALIGN_PARAGRAPH
    L = _labels(lang)
    doc = Document()

    # Letterhead
    t = doc.add_paragraph()
    t.alignment = WD_ALIGN_PARAGRAPH.CENTER
    r = t.add_run(L["title"].upper())
    r.bold = True; r.font.size = Pt(20); r.font.color.rgb = RGBColor(0x1b, 0x35, 0x4e)
    st = doc.add_paragraph(); st.alignment = WD_ALIGN_PARAGRAPH.CENTER
    rs = st.add_run(L["subtitle"]); rs.italic = True; rs.font.size = Pt(11)
    j = doc.add_paragraph(); j.alignment = WD_ALIGN_PARAGRAPH.CENTER
    j.add_run(f'{config.JURISDICTION.upper()}').bold = True

    meta = doc.add_paragraph()
    meta.alignment = WD_ALIGN_PARAGRAPH.CENTER
    meta.add_run(f'{L["pub_date"]}: {issue.publication_date}     '
                 f'{L["opp_deadline"]}: {issue.opposition_deadline}     '
                 f'{L["applications"]}: {len(applications)}')
    note = doc.add_paragraph(); note.add_run(L["note"]).italic = True
    doc.add_paragraph("")

    for idx, a in enumerate(applications, 1):
        h = doc.add_paragraph()
        hr = h.add_run(f'{L["entry"]} {idx} — {_mark_primary(a, lang)}')
        hr.bold = True; hr.font.size = Pt(13); hr.font.color.rgb = RGBColor(0x1b, 0x35, 0x4e)

        tbl = doc.add_table(rows=0, cols=2)
        tbl.style = "Light List Accent 1"
        def row(label, value):
            if not value:
                return
            cells = tbl.add_row().cells
            cells[0].text = label
            cells[1].text = str(value)
            for p in cells[0].paragraphs:
                for run in p.runs:
                    run.bold = True
        row(L["pub_no"], a.pub_number)
        row(L["app_no"], a.app_number)
        row(L["app_date"], a.app_date)
        if a.mark_translit:
            row(L["translit"], a.mark_translit)
        if a.mark_translation:
            row(L["translation"], a.mark_translation)
        row(L["applicant"], a.applicant_en or a.applicant)
        row(L["rep"], a.legal_rep)
        row(L["nationality"], a.nationality)
        row(L["class"], a.nice_class)
        row(L["goods"], a.goods_services_en or a.goods_services)
        row(L["disclaimer"], a.disclaimer_en or a.disclaimer)
        if base_url:
            row(L["source"], f"{base_url}/source/{a.id}")
        doc.add_paragraph("")

    foot = doc.add_paragraph(); fr = foot.add_run(
        f'{config.JURISDICTION} · {issue.publication_date} · {L["footer"]}')
    fr.italic = True; fr.font.size = Pt(8); fr.font.color.rgb = RGBColor(0x99, 0x99, 0x99)

    buf = io.BytesIO(); doc.save(buf)
    return buf.getvalue()


def render_xlsx(issue, applications, design="bulletin", lang="en", base_url=""):
    import io
    from openpyxl import Workbook
    from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
    L = _labels(lang)
    wb = Workbook(); ws = wb.active; ws.title = "Trademark Publications"

    ws.append([L["title"]])
    ws["A1"].font = Font(bold=True, size=16, color="1B354E")
    ws.append([L["subtitle"]]); ws["A2"].font = Font(italic=True, size=11)
    ws.append([config.JURISDICTION, "", L["pub_date"], str(issue.publication_date),
               L["opp_deadline"], str(issue.opposition_deadline)])
    ws.append([])

    headers = [L["no"], L["pub_no"], L["app_no"], L["app_date"], L["translit"],
               L["translation"], L["applicant"], L["rep"], L["class"],
               L["goods"], L["disclaimer"], L["source"]]
    ws.append(headers)
    hr = ws.max_row
    thin = Side(style="thin", color="CCCCCC")
    for c in range(1, len(headers) + 1):
        cell = ws.cell(row=hr, column=c)
        cell.font = Font(bold=True, color="FFFFFF")
        cell.fill = PatternFill("solid", fgColor="1B354E")
        cell.alignment = Alignment(horizontal="left", vertical="center", wrap_text=True)
        cell.border = Border(bottom=thin)
    for idx, a in enumerate(applications, 1):
        link = f"{base_url}/source/{a.id}" if base_url else (a.source_pdf_name or "")
        ws.append([idx, a.pub_number, a.app_number, str(a.app_date or ""),
                   a.mark_translit, a.mark_translation,
                   a.applicant_en or a.applicant, a.legal_rep, a.nice_class,
                   a.goods_services_en or a.goods_services,
                   a.disclaimer_en or a.disclaimer, link])
        for c in range(1, len(headers) + 1):
            ws.cell(row=ws.max_row, column=c).alignment = Alignment(
                vertical="top", wrap_text=True)
    widths = [5, 18, 18, 12, 18, 18, 26, 22, 12, 44, 30, 30]
    for i, w in enumerate(widths, 1):
        ws.column_dimensions[chr(64 + i)].width = w
    ws.freeze_panes = f"A{hr + 1}"
    buf = io.BytesIO(); wb.save(buf)
    return buf.getvalue()


RENDERERS = {"html": render_html, "pdf": render_pdf,
             "docx": render_docx, "xlsx": render_xlsx}

CONTENT_TYPES = {
    "html": "text/html",
    "pdf": "application/pdf",
    "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
}


def generate(issue, applications, fmt="pdf", design="bulletin", lang="en", base_url=""):
    out = RENDERERS[fmt](issue, applications, design=design, lang=lang, base_url=base_url)
    if isinstance(out, str):
        out = out.encode("utf-8")
    return out
