#!/usr/bin/env python3
"""Folie 4 (eingehängt nach Folie 3) – Architektur der Modularisierung:
Modularer Monolith vs. Microservices, anschaulich im Containerumfeld.
Links: 1 Container, Module mit In-Process-Calls, 1 geteilte DB.
Rechts: N Container, Services über Netzwerk, DB je Service.
Unten: kompakte Gegenüberstellung der wesentlichen Unterschiede."""

import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from adesso_style import (WHITE, INK, BLUE, TEAL, GREEN, CORAL, LIGHT, MUTE, RECF,
                          F, FC, paint_background, chrome)

NAVY   = INK
ACCENT = CORAL
LINEC  = LIGHT

prs = Presentation()
prs.slide_width  = Inches(13.333)
prs.slide_height = Inches(7.5)
s = prs.slides.add_slide(prs.slide_layouts[6])
paint_background(s, prs.slide_width, prs.slide_height)


def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), rot=0):
    sh = s.shapes.add_shape(kind, x, y, w, h)
    if fill is None: sh.fill.background()
    else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
    if line is None: sh.line.fill.background()
    else: sh.line.color.rgb = line; sh.line.width = lw
    if rot: sh.rotation = rot
    sh.shadow.inherit = False
    return sh


def boxtext(sh, t, size=14, color=INK, bold=False):
    tf = sh.text_frame; tf.word_wrap = True
    tf.vertical_anchor = MSO_ANCHOR.MIDDLE
    tf.margin_left = tf.margin_right = Pt(3); tf.margin_top = tf.margin_bottom = Pt(1)
    p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER
    r = p.add_run(); r.text = t
    r.font.size = Pt(size); r.font.bold = bold; r.font.name = F; r.font.color.rgb = color


def txt(x, y, w, h, t, size=14, color=INK, bold=False, italic=False,
        align=PP_ALIGN.LEFT, spc=None):
    tb = s.shapes.add_textbox(x, y, w, h); tf = tb.text_frame
    tf.word_wrap = True; tf.vertical_anchor = MSO_ANCHOR.MIDDLE
    tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
    p = tf.paragraphs[0]; p.alignment = align
    r = p.add_run(); r.text = t
    r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic
    r.font.name = F; r.font.color.rgb = color
    if spc: r.font._rPr.set('spc', str(spc))
    return tb


def vline(x, y, h, color=LINEC, weight=Pt(1.4)):
    shp(MSO_SHAPE.RECTANGLE, x - weight / 2, y, weight, h, fill=color)


def hline(x, y, w, color=LINEC, weight=Pt(1.4)):
    shp(MSO_SHAPE.RECTANGLE, x, y - weight / 2, w, weight, fill=color)


# ---- Kopf + Kernaussage ----------------------------------------------------
chrome(s, "Architektur der Modularisierung", 4)
txt(Inches(1.25), Inches(0.98), Inches(11.6), Inches(0.34),
    "Gleiche fachlichen Schnitte – der Unterschied ist die Laufzeit- und Deployment-Grenze.",
    size=14, color=LIGHT, italic=True)

DOT = [TEAL, GREEN, BLUE]   # gleiche Module/Services beidseitig farblich verankert
LET = ["A", "B", "C"]

# ===========================================================================
# Spalten-Titel
# ===========================================================================
cL = Inches(3.6)            # Mittelpunkt linke Spalte
cR = Inches(9.75)           # Mittelpunkt rechte Spalte

txt(Inches(0.95), Inches(1.5), Inches(5.3), Inches(0.32), "Modularer Monolith",
    size=18, color=WHITE, bold=True, align=PP_ALIGN.CENTER)
txt(Inches(0.95), Inches(1.84), Inches(5.3), Inches(0.26), "1 Deployable · 1 Prozess",
    size=11.5, color=LIGHT, align=PP_ALIGN.CENTER)

txt(Inches(7.0), Inches(1.5), Inches(5.5), Inches(0.32), "Microservices",
    size=18, color=WHITE, bold=True, align=PP_ALIGN.CENTER)
txt(Inches(7.0), Inches(1.84), Inches(5.5), Inches(0.26), "N Deployables · N Prozesse",
    size=11.5, color=LIGHT, align=PP_ALIGN.CENTER)

# ===========================================================================
# LINKS – Modularer Monolith: 1 Container, Module, geteilte DB
# ===========================================================================
cx_x, cx_w, cx_y, cx_h = Inches(0.95), Inches(5.3), Inches(2.2), Inches(1.6)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, cx_x, cx_y, cx_w, cx_h, line=WHITE, lw=Pt(1.5))
txt(cx_x + Inches(0.15), cx_y + Inches(0.05), Inches(2.0), Inches(0.26), "1 Container",
    size=11, color=LIGHT, bold=True)

mw, mh, my = Inches(1.35), Inches(0.8), Inches(2.62)
mcx = [Inches(2.05), Inches(3.6), Inches(5.15)]
for i, mx in enumerate(mcx):
    sh = shp(MSO_SHAPE.ROUNDED_RECTANGLE, mx - mw / 2, my, mw, mh, fill=WHITE, line=LINEC, lw=Pt(1))
    boxtext(sh, "Modul " + LET[i], size=13, color=INK, bold=True)
    shp(MSO_SHAPE.OVAL, mx - Inches(0.07), my + Inches(0.12), Inches(0.14), Inches(0.14), fill=DOT[i])
# In-Process-Pfeile zwischen den Modulen
for ax in (Inches(2.725), Inches(4.275)):
    shp(MSO_SHAPE.RIGHT_ARROW, ax, my + mh / 2 - Inches(0.09), Inches(0.2), Inches(0.18), fill=ACCENT)
txt(cx_x, cx_y + cx_h - Inches(0.34), cx_w, Inches(0.26), "In-Process-Aufrufe · Nanosekunden",
    size=11, color=LIGHT, align=PP_ALIGN.CENTER)

# geteilte Datenbank
db_w, db_h, db_y = Inches(1.5), Inches(0.95), Inches(4.0)
vline(cL, cx_y + cx_h, db_y - (cx_y + cx_h), color=LINEC, weight=Pt(1.4))
sh = shp(MSO_SHAPE.CAN, cL - db_w / 2, db_y, db_w, db_h, fill=WHITE, line=LINEC, lw=Pt(1))
boxtext(sh, "DB", size=14, color=INK, bold=True)
txt(cx_x, db_y + db_h + Inches(0.06), cx_w, Inches(0.28), "1 geteilte Datenbank",
    size=12.5, color=WHITE, bold=True, align=PP_ALIGN.CENTER)

# ===========================================================================
# RECHTS – Microservices: Netzwerk-Bus, N Container, DB je Service
# ===========================================================================
bar_x, bar_w, bar_y, bar_h = Inches(7.1), Inches(5.3), Inches(2.2), Inches(0.26)
bar = shp(MSO_SHAPE.ROUNDED_RECTANGLE, bar_x, bar_y, bar_w, bar_h, fill=NAVY)
boxtext(bar, "Netzwerk-Grenze · HTTP / gRPC / Events", size=11, color=WHITE, bold=True)

scx = [Inches(7.95), Inches(9.75), Inches(11.55)]
sc_w, sc_h, sc_y = Inches(1.5), Inches(1.2), Inches(2.62)
sdb_w, sdb_h, sdb_y = Inches(0.85), Inches(0.7), Inches(3.97)
for i, cx in enumerate(scx):
    vline(cx, bar_y + bar_h, sc_y - (bar_y + bar_h), color=LINEC, weight=Pt(1.1))
    shp(MSO_SHAPE.ROUNDED_RECTANGLE, cx - sc_w / 2, sc_y, sc_w, sc_h, line=WHITE, lw=Pt(1.5))
    sh = shp(MSO_SHAPE.ROUNDED_RECTANGLE, cx - Inches(0.55), sc_y + Inches(0.3),
             Inches(1.1), Inches(0.62), fill=WHITE, line=LINEC, lw=Pt(1))
    boxtext(sh, "Svc " + LET[i], size=12.5, color=INK, bold=True)
    shp(MSO_SHAPE.OVAL, cx - Inches(0.06), sc_y + Inches(0.4), Inches(0.12), Inches(0.12), fill=DOT[i])
    # eigene DB je Service
    vline(cx, sc_y + sc_h, sdb_y - (sc_y + sc_h), color=LINEC, weight=Pt(1.1))
    sh = shp(MSO_SHAPE.CAN, cx - sdb_w / 2, sdb_y, sdb_w, sdb_h, fill=WHITE, line=LINEC, lw=Pt(1))
    boxtext(sh, "DB", size=11, color=INK, bold=True)
txt(bar_x, sdb_y + sdb_h + Inches(0.06), bar_w, Inches(0.28), "Datenbank je Service",
    size=12.5, color=WHITE, bold=True, align=PP_ALIGN.CENTER)

# ===========================================================================
# Trenner + vs.
# ===========================================================================
vline(Inches(6.65), Inches(1.55), Inches(3.5), color=LINEC, weight=Pt(1))
vs = shp(MSO_SHAPE.OVAL, Inches(6.65) - Inches(0.31), Inches(3.05), Inches(0.62), Inches(0.46),
         line=WHITE, lw=Pt(1.5))
vs.fill.background()
boxtext(vs, "vs.", size=13, color=WHITE, bold=True)

# ===========================================================================
# Gegenüberstellung – wesentliche Unterschiede
# ===========================================================================
rows = [
    ("Skalierung",   "als Ganzes (mehr Replicas)", "je Service gezielt"),
    ("Datenhaltung", "1 geteilte DB",              "DB je Service"),
    ("Deployment",   "gemeinsam, 1 Pipeline",      "unabhängig je Service"),
    ("Konsistenz",   "ACID, lokal",                "eventual / Saga"),
]
ry = Inches(5.5)
rh = Inches(0.33)
chip_w = Inches(1.95)
for i, (dim, mono, ms) in enumerate(rows):
    y = ry + rh * i
    chip = shp(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(6.65) - chip_w / 2, y, chip_w, Inches(0.28),
               line=LINEC, lw=Pt(0.75))
    chip.fill.background()
    boxtext(chip, dim, size=11, color=LIGHT, bold=True)
    txt(Inches(2.5), y - Inches(0.02), Inches(3.1), Inches(0.32), mono,
        size=12, color=WHITE, align=PP_ALIGN.RIGHT)
    txt(Inches(7.72), y - Inches(0.02), Inches(3.1), Inches(0.32), ms,
        size=12, color=WHITE, align=PP_ALIGN.LEFT)

out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Folie3b.pptx")
prs.save(out)
print("saved", out)
