"""Genere un fichier Word avec le tableau de correspondance Tag V3 -> Rule Type + QQL/Regex.

Usage:
    python tools/gen_tags_v3_docx.py [chemin_sortie.docx]
"""
import sys
from pathlib import Path

try:
    from docx import Document
    from docx.shared import Pt, RGBColor, Inches, Cm
    from docx.enum.table import WD_ALIGN_VERTICAL
    from docx.oxml.ns import qn
    from docx.oxml import OxmlElement
except ImportError:
    print("[ERR] pip install python-docx")
    sys.exit(1)


TAGS = [
    # (tag, rule_type, value, couleur)
    ("OS-LIN", "Operating System", "Linux", "#4CAF50"),
    ("OS-WIN", "Operating System", "Windows", "#2196F3"),
    ("OS-WIN-SRV", "Operating System", "Windows Server", "#1976D2"),
    ("OS-ESX", "Operating System", "ESXi", "#9C27B0"),
    ("ENV-PRD", "Asset Search", 'name: vp* or name: sp* or name: lp* or name: ls-*', "#F44336"),
    ("ENV-REC", "Asset Search", 'name: vr* or name: sr* or name: lr*', "#FF9800"),
    ("ENV-PPR", "Asset Search", 'name: vi* or name: si* or name: vo*', "#FFC107"),
    ("ENV-TST", "Asset Search", 'name: vv* or name: vt*', "#CDDC39"),
    ("ENV-DEV", "Asset Search", 'name: vd* or name: sd*', "#8BC34A"),
    ("EQT-VIR", "Asset Search", 'name: v*', "#00BCD4"),
    ("EQT-SRV", "Asset Search", 'name: l* or name: s*', "#03A9F4"),
    ("EQT-SWI", "Asset Search", 'name: n*', "#4DD0E1"),
    ("POS-FL", "Asset Search", 'name: "*bot*" or name: "*boo*" or name: "*boc*" or name: "*afl*" or name: "*sup*"', "#009688"),
    ("POS-INF", "Asset Search", 'name: "*dsi*" or name: "*cyb*" or name: "*iad*" or name: "*bur*" or name: "*ecm*" or name: "*log*" or name: "*vid*" or name: "*ges*" or name: "*mon*"', "#3F51B5"),
    ("POS-PEA", "Asset Search", 'name: "*pea*" or name: "*osa*" or name: "*svp*" or name: "*adv*" or name: "*rpa*" or name: "*rpn*" or name: "ls-*"', "#673AB7"),
    ("POS-TRA", "Asset Search", 'name: "*ame*" or name: "*tra*" or name: "*dai*" or name: "*pat*" or name: "*rau*" or name: "*dep*" or name: "*exp*" or name: "*sig*" or name: "*air*"', "#E91E63"),
    ("POS-BI", "Asset Search", 'name: "*dec*" or name: "*sas*" or name: "*bip*" or name: "*apt*" or name: "*pbi*" or name: "*rep*"', "#FF5722"),
    ("POS-GES", "Asset Search", 'name: "*int*" or name: "*agt*" or name: "*pin*" or name: "*ech*"', "#795548"),
    ("POS-DMZ", "Asset Search", 'name: "*ssi*"', "#607D8B"),
    ("TAG-OBS", "Operating System", r"Windows Server 2008|Windows Server 2012|CentOS release 6|Red Hat Enterprise Linux Server release 6", "#B71C1C"),
    ("TAG-EMV", "Asset Search", 'name: "*emv*" or name: "*pci*"', "#D500F9"),
]

STATIC_MANUAL = [
    ("TAG-SED", "Securite Exposition Directe — IP publique / NAT direct", "#C62828"),
    ("TAG-SEI", "Securite Exposition Indirecte — derriere frontal", "#EF6C00"),
    ("TAG-DEC", "Decommissionnement en cours", "#6D4C41"),
    ("TAG-INT", "Integration / Implementation en cours", "#FDD835"),
    ("TAG-SIC", "Zone SIC — Systeme Information Classifie", "#1A237E"),
    ("TAG-SIA", "Zone SIA — Systeme Information Administration", "#283593"),
]


def _shade_cell(cell, hex_color):
    """Ajoute une couleur de fond a une cellule (style surligneur)."""
    tc_pr = cell._tc.get_or_add_tcPr()
    shd = OxmlElement("w:shd")
    shd.set(qn("w:val"), "clear")
    shd.set(qn("w:color"), "auto")
    shd.set(qn("w:fill"), hex_color.replace("#", ""))
    tc_pr.append(shd)


def _set_col_widths(table, widths_cm):
    for row in table.rows:
        for i, cell in enumerate(row.cells):
            if i < len(widths_cm):
                cell.width = Cm(widths_cm[i])


def main():
    out = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("SANEF_Qualys_Tags_V3_RuleTypes.docx")

    doc = Document()
    # Marges reduites
    for section in doc.sections:
        section.left_margin = Cm(1.5)
        section.right_margin = Cm(1.5)
        section.top_margin = Cm(1.5)
        section.bottom_margin = Cm(1.5)

    # Titre
    h = doc.add_heading("Qualys Tags V3 — Correspondance Rule Type / Valeur", level=1)

    p = doc.add_paragraph()
    r = p.add_run("Référence : SANEF DSI / Sécurité Opérationnelle — Plan d'action Qualys V3\n")
    r.italic = True
    r.font.size = Pt(9)
    p.add_run("Chemin Qualys : AssetView > Tags > New Tag > cocher Dynamic, "
              "puis choisir le Rule Type et copier la valeur.\n").font.size = Pt(10)

    # Section 1 : Tags dynamiques
    doc.add_heading("1. Tags dynamiques (DYN) — à créer en console Qualys", level=2)
    doc.add_paragraph("L'API Qualys ne permet pas de créer des tags dynamiques. "
                      "Ces 21 tags doivent être créés manuellement via la console web.").runs[0].font.size = Pt(10)

    table = doc.add_table(rows=1, cols=4)
    table.style = "Light Grid Accent 1"
    hdr = table.rows[0].cells
    hdr[0].text = "Tag"
    hdr[1].text = "Couleur"
    hdr[2].text = "Rule Type"
    hdr[3].text = "Valeur à saisir"
    for c in hdr:
        for p in c.paragraphs:
            for r in p.runs:
                r.bold = True

    for tag, rule, value, color in TAGS:
        row = table.add_row().cells
        row[0].text = tag
        row[1].text = color
        row[2].text = rule
        row[3].text = value
        # Font mono pour tag + valeur
        for r in row[0].paragraphs[0].runs:
            r.font.name = "Consolas"
            r.bold = True
        for r in row[3].paragraphs[0].runs:
            r.font.name = "Consolas"
            r.font.size = Pt(9)
        _shade_cell(row[1], color)
        # Texte couleur en blanc pour cellule sombre
        for r in row[1].paragraphs[0].runs:
            r.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
            r.font.size = Pt(9)

    _set_col_widths(table, [2.5, 2.0, 3.5, 10.5])

    # Section 2 : Tags statiques manuels
    doc.add_paragraph()
    doc.add_heading("2. Tags statiques manuels (STAT) — création via API ou SQATM", level=2)
    doc.add_paragraph("Ces tags sont nominatifs et necessitent une decision humaine. "
                      "Ils peuvent être créés via PatchCenter (/qualys/tagsv3/gap) "
                      "ou via SQATM.").runs[0].font.size = Pt(10)

    table2 = doc.add_table(rows=1, cols=3)
    table2.style = "Light Grid Accent 1"
    h2 = table2.rows[0].cells
    h2[0].text = "Tag"
    h2[1].text = "Couleur"
    h2[2].text = "Signification"
    for c in h2:
        for p in c.paragraphs:
            for r in p.runs:
                r.bold = True

    for tag, desc, color in STATIC_MANUAL:
        row = table2.add_row().cells
        row[0].text = tag
        row[1].text = color
        row[2].text = desc
        for r in row[0].paragraphs[0].runs:
            r.font.name = "Consolas"
            r.bold = True
        _shade_cell(row[1], color)
        for r in row[1].paragraphs[0].runs:
            r.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
            r.font.size = Pt(9)

    _set_col_widths(table2, [2.5, 2.0, 13.5])

    # Section 3 : Préfixes statiques à la demande
    doc.add_paragraph()
    doc.add_heading("3. Préfixes statiques à la demande", level=2)
    for prefix, desc in [
        ("APP-xxx", "Application hebergee — APP-SAT, APP-JIRA, APP-GLPI..."),
        ("BDD-xxx", "Type de base de donnees — BDD-ORA, BDD-PG, BDD-SQL..."),
        ("VRF-xxx", "VRF reseau — VRF-TRAFIC, VRF-EMV..."),
        ("MID-xxx", "Middleware — MID-TOMCAT, MID-HAPROXY..."),
    ]:
        p = doc.add_paragraph(style="List Bullet")
        r = p.add_run(f"{prefix} ")
        r.font.name = "Consolas"
        r.bold = True
        p.add_run(f"— {desc}")

    doc.save(out)
    print(f"[OK] Genere: {out.resolve()}")


if __name__ == "__main__":
    main()
