from pathlib import Path

from docx import Document
from docx.enum.section import WD_SECTION
from docx.enum.table import WD_CELL_VERTICAL_ALIGNMENT, WD_TABLE_ALIGNMENT
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import Inches, Pt, RGBColor


ROOT = Path(__file__).resolve().parents[1]
OUTPUT = ROOT / "storage" / "subscriber_contracts" / "templates" / "default-subscriber-contract.docx"
FONT = "Arial"  # Named Arabic-readability override to standard_business_brief.
BLUE = "123A5A"
LIGHT = "EAF1F7"
MUTED = "5F6B76"


def set_run(run, size=11, bold=False, color="000000"):
    run.font.name = FONT
    run._element.get_or_add_rPr().get_or_add_rFonts().set(qn("w:ascii"), FONT)
    run._element.rPr.rFonts.set(qn("w:hAnsi"), FONT)
    run._element.rPr.rFonts.set(qn("w:cs"), FONT)
    run.font.size = Pt(size)
    run.bold = bold
    run.font.color.rgb = RGBColor.from_string(color)


def rtl(paragraph, align=WD_ALIGN_PARAGRAPH.RIGHT):
    paragraph.alignment = align
    p_pr = paragraph._p.get_or_add_pPr()
    if p_pr.find(qn("w:bidi")) is None:
        p_pr.append(OxmlElement("w:bidi"))


def set_cell_shading(cell, fill):
    tc_pr = cell._tc.get_or_add_tcPr()
    shd = tc_pr.find(qn("w:shd"))
    if shd is None:
        shd = OxmlElement("w:shd")
        tc_pr.append(shd)
    shd.set(qn("w:fill"), fill)


def set_cell_margins(cell, top=100, start=140, bottom=100, end=140):
    tc_pr = cell._tc.get_or_add_tcPr()
    tc_mar = tc_pr.first_child_found_in("w:tcMar")
    if tc_mar is None:
        tc_mar = OxmlElement("w:tcMar")
        tc_pr.append(tc_mar)
    for side, value in (("top", top), ("start", start), ("bottom", bottom), ("end", end)):
        node = tc_mar.find(qn(f"w:{side}"))
        if node is None:
            node = OxmlElement(f"w:{side}")
            tc_mar.append(node)
        node.set(qn("w:w"), str(value))
        node.set(qn("w:type"), "dxa")


def fixed_table(table, widths_dxa):
    table.alignment = WD_TABLE_ALIGNMENT.CENTER
    table.autofit = False
    tbl_pr = table._tbl.tblPr
    layout = tbl_pr.first_child_found_in("w:tblLayout")
    if layout is None:
        layout = OxmlElement("w:tblLayout")
        tbl_pr.append(layout)
    layout.set(qn("w:type"), "fixed")
    tbl_w = tbl_pr.first_child_found_in("w:tblW")
    tbl_w.set(qn("w:w"), str(sum(widths_dxa)))
    tbl_w.set(qn("w:type"), "dxa")
    tbl_ind = tbl_pr.first_child_found_in("w:tblInd")
    if tbl_ind is None:
        tbl_ind = OxmlElement("w:tblInd")
        tbl_pr.append(tbl_ind)
    tbl_ind.set(qn("w:w"), "120")
    tbl_ind.set(qn("w:type"), "dxa")
    grid = table._tbl.tblGrid
    for child in list(grid):
        grid.remove(child)
    for width in widths_dxa:
        col = OxmlElement("w:gridCol")
        col.set(qn("w:w"), str(width))
        grid.append(col)
    for row in table.rows:
        for idx, cell in enumerate(row.cells):
            tc_w = cell._tc.get_or_add_tcPr().first_child_found_in("w:tcW")
            tc_w.set(qn("w:w"), str(widths_dxa[idx]))
            tc_w.set(qn("w:type"), "dxa")
            set_cell_margins(cell)
            cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER


def set_cell_text(cell, text, label=False):
    p = cell.paragraphs[0]
    rtl(p)
    p.paragraph_format.space_before = Pt(0)
    p.paragraph_format.space_after = Pt(0)
    run = p.add_run(text)
    set_run(run, 10.5, label, BLUE if label else "000000")


def add_heading(doc, text):
    p = doc.add_paragraph()
    rtl(p)
    p.paragraph_format.space_before = Pt(12)
    p.paragraph_format.space_after = Pt(6)
    run = p.add_run(text)
    set_run(run, 13, True, BLUE)
    return p


def add_body(doc, text, after=6):
    p = doc.add_paragraph()
    rtl(p)
    p.paragraph_format.space_before = Pt(0)
    p.paragraph_format.space_after = Pt(after)
    p.paragraph_format.line_spacing = 1.15
    run = p.add_run(text)
    set_run(run, 11)
    return p


def add_numbered(doc, text):
    p = doc.add_paragraph(style="List Number")
    rtl(p)
    p.paragraph_format.left_indent = Inches(0)
    p.paragraph_format.right_indent = Inches(0.5)
    p.paragraph_format.first_line_indent = Inches(-0.25)
    p.paragraph_format.space_after = Pt(6)
    p.paragraph_format.line_spacing = 1.1
    set_run(p.add_run(text), 11)


def build():
    OUTPUT.parent.mkdir(parents=True, exist_ok=True)
    doc = Document()
    section = doc.sections[0]
    section.page_width = Inches(8.5)
    section.page_height = Inches(11)
    section.top_margin = Inches(0.72)
    section.bottom_margin = Inches(0.72)
    section.left_margin = Inches(0.78)
    section.right_margin = Inches(0.78)
    section.header_distance = Inches(0.35)
    section.footer_distance = Inches(0.35)

    normal = doc.styles["Normal"]
    normal.font.name = FONT
    normal._element.rPr.rFonts.set(qn("w:ascii"), FONT)
    normal._element.rPr.rFonts.set(qn("w:hAnsi"), FONT)
    normal._element.rPr.rFonts.set(qn("w:cs"), FONT)
    normal.font.size = Pt(11)

    header = section.header.paragraphs[0]
    rtl(header)
    header.paragraph_format.space_after = Pt(0)
    set_run(header.add_run("{{company_name}}  |  إدارة عقود المشتركين"), 9, True, MUTED)

    footer = section.footer.paragraphs[0]
    rtl(footer, WD_ALIGN_PARAGRAPH.CENTER)
    set_run(footer.add_run("رقم العقد: {{contract_number}}  |  تاريخ الإنشاء: {{contract_date}}"), 8.5, False, MUTED)

    title = doc.add_paragraph()
    rtl(title, WD_ALIGN_PARAGRAPH.CENTER)
    title.paragraph_format.space_before = Pt(4)
    title.paragraph_format.space_after = Pt(3)
    set_run(title.add_run("{{contract_title}}"), 20, True, BLUE)

    subtitle = doc.add_paragraph()
    rtl(subtitle, WD_ALIGN_PARAGRAPH.CENTER)
    subtitle.paragraph_format.space_after = Pt(12)
    set_run(subtitle.add_run("عقد رقم {{contract_number}} - بتاريخ {{contract_date}}"), 10.5, True, MUTED)

    meta = doc.add_table(rows=4, cols=4)
    meta.style = "Table Grid"
    rows = [
        ("اسم المشترك", "{{full_name}}", "رقم المشترك", "{{subscriber_id}}"),
        ("الرقم الوطني", "{{national_id}}", "رقم الهاتف", "{{phone}}"),
        ("العنوان", "{{address}}", "تاريخ الميلاد", "{{birth_date}}"),
        ("اسم الأم", "{{mother_name}}", "رقم القيد", "{{record_number}}"),
    ]
    for row, values in zip(meta.rows, rows):
        for idx, value in enumerate(values):
            set_cell_text(row.cells[idx], value, idx % 2 == 0)
            if idx % 2 == 0:
                set_cell_shading(row.cells[idx], LIGHT)
    fixed_table(meta, [1400, 3280, 1400, 3280])

    add_heading(doc, "تمهيد")
    add_body(doc, "اتفق الطرف الأول {{company_name}} والطرف الثاني المشترك {{full_name}} على تقديم خدمة الإنترنت وفق البيانات والشروط المبينة في هذا العقد.")

    add_heading(doc, "بيانات الخدمة")
    service = doc.add_table(rows=3, cols=4)
    service.style = "Table Grid"
    service_rows = [
        ("حساب PPPoE", "{{pppoe_username}}", "كلمة المرور", "{{pppoe_password}}"),
        ("السرعة", "{{speed}}", "الباقة", "{{package}}"),
        ("العنوان الثابت", "{{static_ip}}", "القطاع", "{{sector}}"),
    ]
    for row, values in zip(service.rows, service_rows):
        for idx, value in enumerate(values):
            set_cell_text(row.cells[idx], value, idx % 2 == 0)
            if idx % 2 == 0:
                set_cell_shading(row.cells[idx], LIGHT)
    fixed_table(service, [1400, 3280, 1400, 3280])

    add_heading(doc, "شروط العقد")
    clauses = [
        "يلتزم الطرف الأول بتقديم الخدمة ضمن الإمكانات الفنية المتاحة وإبلاغ المشترك بأي توقف مخطط له متى كان ذلك ممكناً.",
        "يلتزم المشترك بصحة بياناته والمحافظة على بيانات الدخول وعدم مشاركتها بصورة تخالف سياسة الاستخدام.",
        "تخضع السرعة الفعلية لجودة الربط والتغطية والازدحام والعوامل الفنية الخارجة عن السيطرة المباشرة للطرف الأول.",
        "تستحق الرسوم وفق الباقة ودورة الفوترة المعتمدة، ويجوز تعليق الخدمة عند وجود مبالغ مستحقة بعد الإشعار.",
        "يُعد توقيع الطرفين إقراراً بقراءة الشروط وقبولها، وتُحفظ نسخة من العقد في سجل المشترك.",
    ]
    for clause in clauses:
        add_numbered(doc, clause)

    add_heading(doc, "ملاحظات وتعديلات خاصة")
    add_body(doc, "{{contract_notes}}", after=10)

    signatures = doc.add_table(rows=2, cols=2)
    signatures.style = "Table Grid"
    set_cell_text(signatures.cell(0, 0), "الطرف الأول - {{company_name}}", True)
    set_cell_text(signatures.cell(0, 1), "الطرف الثاني - {{full_name}}", True)
    set_cell_text(signatures.cell(1, 0), "التوقيع: {{company_signature}}\nالختم: {{company_stamp}}")
    set_cell_text(signatures.cell(1, 1), "التوقيع: ____________________")
    fixed_table(signatures, [4680, 4680])

    doc.core_properties.title = "قالب عقد مشترك"
    doc.core_properties.subject = "قالب قابل للتعبئة من نظام إدارة المشتركين"
    doc.core_properties.author = "Network Customers"
    doc.save(OUTPUT)
    print(OUTPUT)


if __name__ == "__main__":
    build()
