#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""v1.3 SAFE-REBUILD polish — JvG training + master.

PowerPoint-safe: uitsluitend reguliere python-pptx API-constructies die ook in
v1.1 voorkomen. GEEN effectLst (geen shadow API), GEEN a:alpha, GEEN rot.
Inhoud (tekst-runs) wordt NOOIT gewijzigd — alleen opmaak.

(a) titelfolie : solide rects #003366 (full-bleed) + #0a1628 (bovenband)
                 gelaagd, oranje diagonaal accentvlak via
                 MSO_SHAPE.PARALLELOGRAM (solide #FF6D00, geen lijn, geen rot)
(b) elke slide : accentbalk plain rect 0.04" (#FF6D00, geen lijn) direct
                 onder het titelblok
(c) bullet-panelen: fill.solid() #F8F9FA + lijn #E5E7EB 0.75pt
(d) tabelheaders : #003366 wit bold + zebra FFFFFF/F8F9FA
(e) runs beginnend met vinkje: kleur #00A859 + bold (run wordt NIET
    gesplitst, zodat de run-set identiek aan v1.1 blijft)
"""
import json

from pptx import Presentation
from pptx.util import Emu, Pt
from pptx.dml.color import RGBColor
from pptx.enum.shapes import MSO_SHAPE

NAVY   = RGBColor(0x00, 0x33, 0x66)
NAVY2  = RGBColor(0x0A, 0x16, 0x28)
ORANGE = RGBColor(0xFF, 0x6D, 0x00)
CARD   = RGBColor(0xF8, 0xF9, 0xFA)
BORDER = RGBColor(0xE5, 0xE7, 0xEB)
GREEN  = RGBColor(0x00, 0xA8, 0x59)
WHITE  = RGBColor(0xFF, 0xFF, 0xFF)

SW, SH = 9144000, 5143500            # 16:9
BAND_H    = 1600200                  # 1.75" bovenband 0a1628
PARA_H    = 457200                   # 0.50" parallelogram op de naad
PARA_SKEW = 114300                   # 0.25 * PARA_H (default adj 25000)
BAR_H     = 36576                    # 0.04" accentbalk
BAR_GAP   = 45720                    # 0.05" onder header
BAR_W     = 1463040                  # 1.6" breed (conform master v1.1)


def solid(shape, color):
    shape.fill.solid()
    shape.fill.fore_color.rgb = color
    shape.line.fill.background()


def card_style(shape):
    shape.fill.solid()
    shape.fill.fore_color.rgb = CARD
    shape.line.color.rgb = BORDER
    shape.line.width = Pt(0.75)


# ---------------------------------------------------------------- (a)
def polish_title_slide(prs, log):
    s1 = prs.slides[0]
    spTree = s1.shapes._spTree

    base = None
    for sh in s1.shapes:
        try:
            if int(sh.width) == SW and int(sh.height) == SH and str(sh.shape_type).startswith('AUTO'):
                base = sh
                break
        except Exception:
            pass

    if base is not None:
        solid(base, NAVY)                       # laag 1: bestaand full-bleed
        insert_at = list(spTree).index(base._element) + 1
        log['reused_fullbleed'] = base.shape_id
    else:
        a = s1.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, SW, SH)
        solid(a, NAVY)                          # laag 1
        sp = a._element
        sp.getparent().remove(sp)
        spTree.insert(2, sp)                    # achter alles
        insert_at = 3
        log['added_fullbleed'] = a.shape_id

    b = s1.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, SW, BAND_H)
    solid(b, NAVY2)                             # laag 2: donkere bovenband
    sp = b._element
    sp.getparent().remove(sp)
    spTree.insert(insert_at, sp)
    log['band_0a1628'] = b.shape_id

    c = s1.shapes.add_shape(MSO_SHAPE.PARALLELOGRAM,
                            -PARA_SKEW, BAND_H - PARA_H // 2,
                            SW + 2 * PARA_SKEW, PARA_H)
    solid(c, ORANGE)                            # laag 3: diagonale accent
    sp = c._element
    sp.getparent().remove(sp)
    spTree.insert(insert_at + 1, sp)
    log['parallelogram'] = c.shape_id

    # titelruns die navy zijn -> wit (leesbaarheid op donkere achtergrond)
    n = 0
    for sh in s1.shapes:
        if not sh.has_text_frame:
            continue
        for para in sh.text_frame.paragraphs:
            for run in para.runs:
                try:
                    if run.font.color and run.font.color.type is not None \
                            and run.font.color.rgb == NAVY:
                        run.font.color.rgb = WHITE
                        n += 1
                except Exception:
                    pass
    log['title_runs_recolored_white'] = n


# ---------------------------------------------------------------- (b)
def header_bottom(slide):
    bottoms = []
    for sh in slide.shapes:
        if not sh.has_text_frame or not sh.text_frame.text.strip():
            continue
        if sh.top is None or sh.left is None:
            continue
        if sh.top < 1000000 and sh.left > 200000:
            bottoms.append(int(sh.top + sh.height))
    return max(bottoms) if bottoms else None


def polish_bars(prs, log):
    log['normalized'] = []
    log['added'] = []
    for i, slide in enumerate(prs.slides, 1):
        if i == 1:
            continue
        hb = header_bottom(slide)
        if hb is None:
            continue
        bar_top = hb + BAR_GAP
        done = False
        for sh in slide.shapes:
            try:
                h, w, t = int(sh.height), int(sh.width), int(sh.top)
            except Exception:
                continue
            if 30000 <= h <= 60000 and 1000000 <= w <= 2000000 \
                    and 900000 <= t <= 1400000:
                sh.height = Emu(BAR_H)
                solid(sh, ORANGE)
                log['normalized'].append(i)
                done = True
                break
        if not done:
            left = None
            for sh in slide.shapes:
                if sh.has_text_frame and sh.text_frame.text.strip() \
                        and sh.top is not None and sh.top < 1000000 \
                        and sh.left is not None and sh.left > 200000:
                    if left is None or sh.left < left:
                        left = sh.left
            bar = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE,
                                         Emu(left if left is not None else 457200),
                                         Emu(bar_top), Emu(BAR_W), Emu(BAR_H))
            solid(bar, ORANGE)
            log['added'].append(i)


# ---------------------------------------------------------------- (c)
def polish_bullets(prs, log):
    log['panels'] = 0
    for slide in prs.slides:
        for sh in slide.shapes:
            if not sh.has_text_frame:
                continue
            if sh.text_frame.text.strip().startswith('\u2022'):
                card_style(sh)
                log['panels'] += 1


# ---------------------------------------------------------------- (d)
def polish_tables(prs, log):
    log['tables'] = []
    for i, slide in enumerate(prs.slides, 1):
        for sh in slide.shapes:
            if not sh.has_table:
                continue
            tbl = sh.table
            for r, row in enumerate(tbl.rows):
                for cell in row.cells:
                    cell.fill.solid()
                    if r == 0:
                        cell.fill.fore_color.rgb = NAVY
                    else:
                        cell.fill.fore_color.rgb = CARD if r % 2 == 0 else WHITE
                    for para in cell.text_frame.paragraphs:
                        for run in para.runs:
                            if r == 0:
                                run.font.color.rgb = WHITE
                                run.font.bold = True
            log['tables'].append([i, len(tbl.rows), len(tbl.columns)])


# ---------------------------------------------------------------- (e)
def polish_checks(prs, log):
    log['check_runs'] = 0
    for slide in prs.slides:
        for sh in slide.shapes:
            if not sh.has_text_frame:
                continue
            for para in sh.text_frame.paragraphs:
                for run in para.runs:
                    if run.text.startswith('\u2713'):
                        run.font.color.rgb = GREEN
                        run.font.bold = True
                        log['check_runs'] += 1


def polish(path):
    prs = Presentation(path)
    log = {'file': path.split('/')[-1], 'slides': len(prs.slides)}
    log['title'] = {}
    polish_title_slide(prs, log['title'])
    log['bars'] = {}
    polish_bars(prs, log['bars'])
    polish_bullets(prs, log)
    polish_tables(prs, log)
    polish_checks(prs, log)
    prs.save(path)
    return log


if __name__ == '__main__':
    import sys
    results = [polish(p) for p in sys.argv[1:]]
    print(json.dumps(results, indent=1, ensure_ascii=False))
