from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Image, PageBreak, KeepTogether
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
from PIL import Image as PILImage, ImageDraw, ImageFont
from pathlib import Path

OUT = Path('/home/agent/Helvetia_Lebensversicherung_Finanzberaterbericht_Update_Hypothek_2026-06-26.pdf')
WORK = Path('/home/agent/insurance_work/life3a_review/update_hypothek')
WORK.mkdir(parents=True, exist_ok=True)

# Inputs from previous verified report / OCR
start_year = 2025
end_year = 2050
n = 25
annual_contribution = 2400.0
surrender = 31090.65  # Rückkaufswert inkl. Überschuss gemäss bisheriger Arbeitsgrundlage
paidup_sum = 43736.0
guarantee = 112662.0
paid_in = 38400.0
loss = paid_in - surrender
stock_r = 0.05
mortgage_r = 0.0077
annual_interest_saving = surrender * mortgage_r

# Future values aligned with prior report: yearly contributions 2025–2049 grow to 2050
contrib_fv = sum(annual_contribution * (1 + stock_r) ** (end_year - y) for y in range(start_year, end_year))
surrender_fv = surrender * (1 + stock_r) ** n
interest_savings_nominal = annual_interest_saving * n
interest_savings_fv = sum(annual_interest_saving * (1 + stock_r) ** (end_year - y) for y in range(start_year, end_year))

variants = {
    'A Rückkauf/3a-Transfer + Beiträge': surrender_fv + contrib_fv,
    'B Prämienfrei + Beiträge': paidup_sum + contrib_fv,
    'E Hypothek tilgen + Beiträge + Zinsersparnis': surrender + contrib_fv + interest_savings_fv,
    'C Nur Rückkaufswert investieren': surrender_fv,
    'D Weiterführen Garantie': guarantee,
}

# Yearly trajectories for plots
years = list(range(start_year, end_year + 1))
def fv_contrib_until(year):
    return sum(annual_contribution * (1 + stock_r) ** (year - y) for y in range(start_year, min(year, end_year)))
def fv_interest_until(year):
    return sum(annual_interest_saving * (1 + stock_r) ** (year - y) for y in range(start_year, min(year, end_year)))
A = [surrender * (1 + stock_r) ** (y - start_year) + fv_contrib_until(y) for y in years]
B = [paidup_sum + fv_contrib_until(y) for y in years]
C = [surrender * (1 + stock_r) ** (y - start_year) for y in years]
E = [surrender + fv_contrib_until(y) + fv_interest_until(y) for y in years]

# Lightweight chart drawing with Pillow (no matplotlib dependency)
font_reg = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 22)
font_sm = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 18)
font_b = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', 24)
font_title = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', 30)

def chf_k(v):
    return f"{v/1000:.0f}k"
def draw_text_center(draw, xy, text, font, fill):
    x, y = xy
    box = draw.textbbox((0,0), text, font=font)
    draw.text((x-(box[2]-box[0])/2, y), text, font=font, fill=fill)

def make_canvas(w=1500, h=820):
    return PILImage.new('RGB', (w, h), 'white')

def save_line_chart(path):
    w,h=1500,840; img=make_canvas(w,h); d=ImageDraw.Draw(img)
    left,right,top,bottom=115,70,100,115
    d.text((left,28),'Variantenentwicklung bis 2050 bei 5 % Aktienrendite und 0.77 % Hypothekarzins',font=font_title,fill='#12344D')
    maxv=max(max(A),max(B),max(C),max(E),guarantee)*1.08; minv=0
    def X(y): return left+(y-start_year)/(end_year-start_year)*(w-left-right)
    def Y(v): return h-bottom-(v-minv)/(maxv-minv)*(h-top-bottom)
    # grid
    for val in range(0,260000,50000):
        y=Y(val); d.line((left,y,w-right,y), fill='#D9E1E8', width=1); d.text((20,y-10),chf_k(val),font=font_sm,fill='#555')
    for yr in [2025,2030,2035,2040,2045,2050]:
        x=X(yr); d.line((x,top,x,h-bottom), fill='#EEF2F5', width=1); draw_text_center(d,(x,h-bottom+18),str(yr),font_sm,'#555')
    d.line((left,top,left,h-bottom), fill='#777', width=2); d.line((left,h-bottom,w-right,h-bottom), fill='#777', width=2)
    series=[('A Rückkauf/3a-Transfer + Beiträge',A,'#0B5CAD',4),('B Prämienfrei + Beiträge',B,'#8A1C2B',4),('E Hypothek tilgen + Beiträge + Zinsersparnis',E,'#1B7F3A',4),('C Nur Rückkaufswert',C,'#F0A202',3)]
    for name, vals, col, width in series:
        pts=[(X(y),Y(v)) for y,v in zip(years,vals)]
        d.line(pts, fill=col, width=width, joint='curve')
        d.text((pts[-1][0]-115, pts[-1][1]-26), name.split(' ')[0], font=font_b, fill=col)
    gy=Y(guarantee)
    for x in range(left, w-right, 22): d.line((x,gy,x+11,gy), fill='#555555', width=3)
    # legend
    lx,ly=left,top+10
    for name, vals, col, width in series:
        d.rectangle((lx,ly,lx+28,ly+12), fill=col); d.text((lx+38,ly-5),name,font=font_sm,fill='#222'); ly+=30
    d.line((lx,ly+6,lx+28,ly+6), fill='#555', width=3); d.text((lx+38,ly-5),'D Weiterführen: Garantie 2050',font=font_sm,fill='#222')
    img.save(path)

def save_bar_chart(path):
    w,h=1500,760; img=make_canvas(w,h); d=ImageDraw.Draw(img)
    left,right,top,bottom=105,55,95,135
    d.text((left,28),'Endwerte 2050 im Vergleich',font=font_title,fill='#12344D')
    labels=['A\nTransfer','B\nPrämienfrei','E\nHypothek','C\nRückkaufswert','D\nGarantie']
    vals=[variants['A Rückkauf/3a-Transfer + Beiträge'], variants['B Prämienfrei + Beiträge'], variants['E Hypothek tilgen + Beiträge + Zinsersparnis'], variants['C Nur Rückkaufswert investieren'], variants['D Weiterführen Garantie']]
    cols=['#0B5CAD','#8A1C2B','#1B7F3A','#F0A202','#555555']
    maxv=max(vals)*1.18
    def Y(v): return h-bottom-v/maxv*(h-top-bottom)
    for val in range(0,260000,50000):
        y=Y(val); d.line((left,y,w-right,y),fill='#D9E1E8'); d.text((22,y-10),chf_k(val),font=font_sm,fill='#555')
    plotw=w-left-right; step=plotw/len(vals); bw=step*.56
    for i,(lab,v,col) in enumerate(zip(labels,vals,cols)):
        x=left+i*step+step*.22; y=Y(v)
        d.rectangle((x,y,x+bw,h-bottom), fill=col)
        draw_text_center(d,(x+bw/2,y-34),f"CHF {v:,.0f}".replace(',', '’'),font_sm,'#111')
        for k,part in enumerate(lab.split('\n')): draw_text_center(d,(x+bw/2,h-bottom+18+22*k),part,font_sm,'#333')
    d.line((left,top,left,h-bottom), fill='#777', width=2); d.line((left,h-bottom,w-right,h-bottom), fill='#777', width=2)
    img.save(path)

def save_composition_chart(path):
    w,h=1500,740; img=make_canvas(w,h); d=ImageDraw.Draw(img)
    left,right,top,bottom=110,60,150,125
    d.text((left,28),'Werttreiber der drei relevanten Umsetzungsvarianten',font=font_title,fill='#12344D')
    comp={'A Transfer':[surrender_fv,contrib_fv,0],'B Prämienfrei':[paidup_sum,contrib_fv,0],'E Hypothek':[surrender,contrib_fv,interest_savings_fv]}
    cols=['#7895B2','#93C47D','#F6B26B']; names=['Startkapital/Garantie/Schuldreduktion','Folgebeiträge Aktien','reinvestierte Zinsersparnis']
    totals=[sum(v) for v in comp.values()]; maxv=max(totals)*1.18
    def Y(v): return h-bottom-v/maxv*(h-top-bottom)
    for val in range(0,260000,50000):
        y=Y(val); d.line((left,y,w-right,y),fill='#D9E1E8'); d.text((22,y-10),chf_k(val),font=font_sm,fill='#555')
    plotw=w-left-right; step=plotw/3; bw=step*.5
    for i,(lab,parts) in enumerate(comp.items()):
        x=left+i*step+step*.25; acc=0
        for p,col in zip(parts,cols):
            if p<=0: continue
            y1=Y(acc+p); y2=Y(acc)
            d.rectangle((x,y1,x+bw,y2), fill=col)
            acc += p
        draw_text_center(d,(x+bw/2,Y(acc)-32),f"CHF {acc:,.0f}".replace(',', '’'),font_sm,'#111')
        draw_text_center(d,(x+bw/2,h-bottom+20),lab,font_sm,'#333')
    # legend above the plot area
    lx,ly=left,82
    for name,col in zip(names,cols):
        d.rectangle((lx,ly,lx+26,ly+14), fill=col); d.text((lx+36,ly-5),name,font=font_sm,fill='#222'); ly+=30
    d.line((left,top,left,h-bottom), fill='#777', width=2); d.line((left,h-bottom,w-right,h-bottom), fill='#777', width=2)
    img.save(path)

line_path = WORK / 'varianten_update_line.png'
bar_path = WORK / 'varianten_update_bar.png'
comp_path = WORK / 'varianten_update_composition.png'
save_line_chart(line_path)
save_bar_chart(bar_path)
save_composition_chart(comp_path)

# ReportLab setup
for fp, name in [('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf','DejaVuSans'),('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf','DejaVuSans-Bold')]:
    try: pdfmetrics.registerFont(TTFont(name, fp))
    except Exception: pass
base='DejaVuSans'; bold='DejaVuSans-Bold'
styles = getSampleStyleSheet()
for st in styles.byName.values():
    if hasattr(st, 'fontName'): st.fontName = base
styles['Title'].fontName = bold; styles['Title'].fontSize = 18; styles['Title'].leading = 22; styles['Title'].alignment = TA_CENTER; styles['Title'].textColor = colors.HexColor('#12344D')
styles['Heading1'].fontName = bold; styles['Heading1'].fontSize = 13; styles['Heading1'].leading = 16; styles['Heading1'].spaceBefore = 8; styles['Heading1'].spaceAfter = 5; styles['Heading1'].textColor = colors.HexColor('#12344D')
styles['Heading2'].fontName = bold; styles['Heading2'].fontSize = 11; styles['Heading2'].leading = 14; styles['Heading2'].spaceBefore = 6; styles['Heading2'].spaceAfter = 3; styles['Heading2'].textColor = colors.HexColor('#8A1C2B')
styles['Normal'].fontName = base; styles['Normal'].fontSize = 8.8; styles['Normal'].leading = 11.4
small = ParagraphStyle('small', parent=styles['Normal'], fontSize=7.4, leading=9.2)
cell = ParagraphStyle('cell', parent=styles['Normal'], fontSize=7.4, leading=9.2)
head = ParagraphStyle('head', parent=cell, fontName=bold, textColor=colors.white)
box = ParagraphStyle('box', parent=styles['Normal'], backColor=colors.HexColor('#EEF4F8'), borderColor=colors.HexColor('#12344D'), borderWidth=0.8, borderPadding=7, leading=11.5)

story=[]
def P(txt, style=None):
    story.append(Paragraph(txt, style or styles['Normal']))
def S(h=6): story.append(Spacer(1,h))
def CHF(x): return f"CHF {x:,.0f}".replace(',', '’')
def CHF2(x): return f"CHF {x:,.2f}".replace(',', '’')
def table(data, widths=None):
    d=[]
    for r, row in enumerate(data):
        d.append([Paragraph(str(c), head if r==0 else cell) for c in row])
    if widths is None:
        widths=[(A4[0]-3.2*cm)/len(data[0])]*len(data[0])
    t=Table(d, colWidths=widths, repeatRows=1, hAlign='LEFT')
    t.setStyle(TableStyle([
        ('BACKGROUND',(0,0),(-1,0),colors.HexColor('#12344D')),
        ('GRID',(0,0),(-1,-1),0.25,colors.HexColor('#B9C2C9')),
        ('VALIGN',(0,0),(-1,-1),'TOP'),
        ('LEFTPADDING',(0,0),(-1,-1),4),('RIGHTPADDING',(0,0),(-1,-1),4),
        ('TOPPADDING',(0,0),(-1,-1),3),('BOTTOMPADDING',(0,0),(-1,-1),3),
        ('ROWBACKGROUNDS',(0,1),(-1,-1),[colors.white, colors.HexColor('#F6F8FA')]),
    ]))
    story.append(t); S(7)

# Cover
P('Finanzberaterbericht – Update Hypothekvariante', styles['Title'])
P('Helvetia Lebensversicherung Säule 3a: Rückkauf, Prämienfreistellung, Weiterführung und Einsatz zur Hypothekaramortisation', ParagraphStyle('sub', parent=styles['Normal'], alignment=TA_CENTER, fontSize=10.5, leading=13, textColor=colors.HexColor('#555555')))
S(14)
# KPI table as cards
kpis = [
    ['Hypothekarzins aktuell', '0.77 % p.a.', 'Bruttokostenersparnis bei Amortisation'],
    ['3a-Kapital aus Police', CHF2(surrender), 'Arbeitswert Rückkauf inkl. Überschuss'],
    ['Zinsersparnis p.a.', CHF2(annual_interest_saving), 'indirekter Gewinn vor Steuereffekt'],
    ['Endwert Variante E', CHF(variants['E Hypothek tilgen + Beiträge + Zinsersparnis']), 'mit Reinvestition der Zinsersparnis zu 5 %'],
]
table([['Kennzahl','Wert','Einordnung']] + kpis, [5*cm,4*cm,7*cm])
P('<b>Kurzurteil.</b> Die Hypothekaramortisation mit dem 3a-Kapital ist risikoarm, aber bei einem Hypothekarzins von nur 0.77 % finanziell nicht die stärkste Lösung. Sie schlägt die reine Weiterführung der Police deutlich, liegt aber rund CHF 62’000 unter der Variante Rückkauf/3a-Transfer mit Anlage des Startkapitals zu 5 %. Sie ist ungefähr gleich stark wie die Prämienfreistellung plus Anlage der Folgebeiträge.', box)
S(8)
table([
    ['Priorität','Empfehlung','Begründung'],
    ['1','3a-Transfer in Wertschriftenlösung prüfen','höchster erwarteter Endwert bei 5 % und langer Restlaufzeit'],
    ['2','Wenn Sicherheits-/Schuldenabbau wichtig ist: Hypothekvariante als defensive Alternative','garantierte Zinsersparnis, tiefes Risiko, aber tiefer Opportunitätswert'],
    ['3','Prämienfreistellung als einfacher Mittelweg','ähnlicher Endwert wie Hypothekvariante, ohne 3a-Vorbezug für Eigenheim'],
], [2.3*cm,5.1*cm,8.6*cm])
P('Berichtsdatum: 26.06.2026', small)
story.append(PageBreak())

# Ausgangslage
P('1. Ausgangslage und ergänzte Annahme', styles['Heading1'])
table([
    ['Position','Wert'],
    ['Vertragsbeginn / Ablauf','01.05.2009 / 01.05.2050'],
    ['Jahresprämie','CHF 2’400'],
    ['Rückkaufswert inkl. Überschuss per 01.05.2025', CHF2(surrender)],
    ['Prämienfreie Versicherungssumme', CHF(paidup_sum)],
    ['Garantiertes Kapital 2050 bei Weiterführung', CHF(guarantee)],
    ['Neue Zusatzannahme','3a-Kapital wird zur Hypothekaramortisation genutzt; Folgebeiträge werden zu 5 % p.a. in Aktien angelegt'],
    ['Hypothekarzins','0.77 % p.a. brutto'],
], [6.2*cm,9.8*cm])
P('Die neue Variante behandelt den Rückkaufs-/Transferwert nicht als Aktienanlage, sondern als Schuldreduktion. Der ökonomische Nutzen besteht aus zwei Komponenten: erstens der dauerhaft tieferen Hypothekarschuld, zweitens der jährlich eingesparten Hypothekarzinsen. Bei 0.77 % ergibt sich auf dem eingesetzten Kapital eine Bruttoersparnis von rund <b>CHF 239 pro Jahr</b>.')
S(12)
P('Wichtig für die Einordnung: Die Amortisation einer selbstbewohnten Hypothek ist innerhalb Säule 3a grundsätzlich als Wohneigentumsförderung möglich. Es ist aber kein freier Cash-out. Die Auszahlung muss sauber als 3a-Vorbezug oder direkte Amortisation abgewickelt werden; ausserdem fällt bei 3a-Bezug eine separate Kapitalleistungssteuer an, die in den nachfolgenden Zahlen noch nicht abgezogen ist.', box)
story.append(PageBreak())

# New variant details
P('2. Neue Variante E: 3a-Kapital zur Hypothekartilgung', styles['Heading1'])
P('Variante E verwendet das verfügbare 3a-Kapital aus der Lebensversicherung zur Reduktion der Hypothek. Die künftigen Beiträge von CHF 2’400 pro Jahr werden nicht mehr in die Police bezahlt, sondern in Aktien mit 5 % erwarteter Rendite investiert. Zusätzlich entsteht durch die tiefere Hypothek ein indirekter Gewinn in Form tieferer Zinskosten.')
S(4)
table([
    ['Baustein','Berechnung','Wert 2050'],
    ['Schuldreduktion durch Amortisation', f'{CHF2(surrender)} bleibt als tiefere Hypothek bestehen', CHF2(surrender)],
    ['Folgebeiträge Aktien', 'CHF 2’400 jährlich 2025–2049 zu 5 % p.a.', CHF2(contrib_fv)],
    ['Hypothekarzins-Ersparnis', f'{CHF2(annual_interest_saving)} p.a.; bei Reinvestition zu 5 %', CHF2(interest_savings_fv)],
    ['Gesamtwert Variante E', 'Schuldreduktion + Aktienvermögen + reinvestierte Zinsersparnis', CHF2(variants['E Hypothek tilgen + Beiträge + Zinsersparnis'])],
], [4.8*cm,7.2*cm,4*cm])
P(f'Ohne Reinvestition der Zinsersparnis beträgt die nominale Zinsersparnis über 25 Jahre rund <b>{CHF2(interest_savings_nominal)}</b>. Wird diese Ersparnis ebenfalls zu 5 % investiert, steigt ihr Endwert auf rund <b>{CHF2(interest_savings_fv)}</b>.')
S(6)
story.append(Image(str(comp_path), width=16*cm, height=7.7*cm)); S(4)
story.append(PageBreak())

# Variant comparison
P('3. Aktualisierter Variantenvergleich bei 5 % p.a.', styles['Heading1'])
table([
    ['Variante','Startlogik','Endwert 2050','Einordnung'],
    ['A Rückkauf/Transfer + Beiträge','Rückkaufswert wird in 3a-Wertschriftenlösung investiert; künftige Beiträge ebenfalls', CHF(variants['A Rückkauf/3a-Transfer + Beiträge']), 'höchster erwarteter Endwert'],
    ['B Prämienfreistellung + Beiträge','prämienfreie Endleistung plus separates Depot künftiger Beiträge', CHF(variants['B Prämienfrei + Beiträge']), 'Mittelweg mit Garantieanteil'],
    ['E Hypothek tilgen + Beiträge + Zinsersparnis','Rückkaufswert reduziert Hypothek; künftige Beiträge und Zinsersparnis werden investiert', CHF(variants['E Hypothek tilgen + Beiträge + Zinsersparnis']), 'defensiv; ähnlich B, aber deutlich unter A'],
    ['C Nur Rückkaufswert investieren','nur heutiger Rückkaufswert wird investiert', CHF(variants['C Nur Rückkaufswert investieren']), 'isolierte Betrachtung ohne neue Beiträge'],
    ['D Weiterführen','Prämien werden weiter bezahlt; Garantie 2050', CHF(guarantee), 'Garantie-/Risikovariant'],
], [3.4*cm,6.5*cm,2.8*cm,3.3*cm])
story.append(Image(str(bar_path), width=16*cm, height=8*cm)); S(4)
story.append(PageBreak())

P('4. Entwicklung bis 2050', styles['Heading1'])
story.append(Image(str(line_path), width=16.5*cm, height=9.4*cm)); S(8)
P('Die Hypothekvariante startet ökonomisch höher als die reine Prämienfreistellung, weil der Rückkaufswert sofort als Schuldreduktion wirkt. Über die Zeit bleibt sie aber hinter Variante A zurück, weil 0.77 % Hypothekarzins deutlich unter der angenommenen Aktienrendite von 5 % liegt. Der Renditehebel auf dem Startkapital fehlt.')
S(4)
P(f'Gegenüber der garantierten Weiterführung liegt Variante E um rund <b>{CHF(variants["E Hypothek tilgen + Beiträge + Zinsersparnis"] - guarantee)}</b> höher. Gegenüber Variante A liegt sie um rund <b>{CHF(variants["A Rückkauf/3a-Transfer + Beiträge"] - variants["E Hypothek tilgen + Beiträge + Zinsersparnis"])}</b> tiefer.', box)
story.append(PageBreak())

P('5. Finanzielle Interpretation der Hypothekvariante', styles['Heading1'])
P('Die Hypothekvariante ist weniger eine Renditeoptimierung als eine Bilanzoptimierung. Sie reduziert sichere Fremdkapitalkosten und senkt die laufende Belastung. Bei 0.77 % ist der sichere Ertrag allerdings sehr niedrig. Der entscheidende Punkt ist der Opportunitätsvergleich: Jeder Franken, der zur Tilgung eingesetzt wird, verdient wirtschaftlich nur 0.77 % brutto, während die Aktienannahme im Bericht 5 % beträgt.')
S(4)
table([
    ['Kriterium','Bewertung Variante E'],
    ['Risikoprofil','sehr defensiv; Zinsersparnis ist planbar'],
    ['Liquidität','Hypothekarschuld sinkt, aber Kapital bleibt im Eigenheim gebunden'],
    ['Renditehebel','niedrig, solange Hypothekarzins bei 0.77 % bleibt'],
    ['Steuern','3a-Vorbezug für Wohneigentum löst Kapitalleistungssteuer aus; zudem fallen weniger Schuldzinsen zum Abzug an'],
    ['Psychologischer Nutzen','höhere Schuldenfreiheit und tiefere Fixkosten'],
    ['Finanzieller Nutzen bei 5 %-Annahme','gut gegenüber Weiterführung, aber klar schwächer als 3a-Wertschriften-Transfer'],
], [5*cm,11*cm])
P('Bei höherem Hypothekarzins würde sich die Bewertung ändern. Ab einem Hypothekarzins nahe der erwarteten Nachsteuer-Aktienrendite wäre Amortisation deutlich attraktiver. Bei 0.77 % ist die Zinsersparnis zu klein, um den Renditeverzicht auf dem Startkapital zu kompensieren.')
story.append(PageBreak())

P('6. Aktualisierte Empfehlung', styles['Heading1'])
P('<b>Primäre Empfehlung:</b> Zuerst weiterhin den steuerneutralen bzw. gebundenen Transfer in eine kostengünstige 3a-Wertschriftenlösung abklären. Diese Variante bleibt unter der 5 %-Annahme mit Abstand die stärkste Vermögensvariante.')
S(5)
P('<b>Defensive Alternative:</b> Wenn Schuldenabbau, geringere Fixkosten und Sicherheit stärker gewichtet werden als Maximalrendite, ist die Hypothekvariante plausibel. Sie ist besonders attraktiv, wenn du die eingesparten Hypothekarzinsen konsequent zusätzlich investierst und nicht konsumierst.')
S(5)
P('<b>Vergleich zu Prämienfreistellung:</b> Variante E liegt mit rund CHF 163’360 praktisch auf Höhe der Prämienfreistellungslösung mit CHF 164’008. Der Unterschied ist gering. Die Entscheidung zwischen B und E ist deshalb weniger eine Renditefrage, sondern eine Strukturfrage: Garantie in der Police behalten oder Hypothek senken.')
S(8)
table([
    ['Entscheidungsregel','Umsetzung'],
    ['Maximaler erwarteter Vermögensaufbau','A: Rückkauf/3a-Transfer + Beiträge in Aktien'],
    ['Defensive Bilanz und tiefere Fixkosten','E: 3a-Kapital zur Hypothekartilgung + Folgebeiträge Aktien'],
    ['Einfacher Mittelweg ohne WEF-Vorbezug','B: Prämienfreistellung + Folgebeiträge Aktien'],
    ['Nur weiterführen bei hohem Wert des Risikoschutzes','D: bestehende Police unverändert lassen'],
], [6*cm,10*cm])
story.append(PageBreak())

P('7. Konkreter Auftrag an Helvetia / Bank', styles['Heading1'])
table([
    ['Schritt','Auftrag','Ziel'],
    ['1','Helvetia: Rückkaufs-/Transferwert inklusive Überschüsse per aktuellem Datum bestätigen lassen','exakten Betrag für Transfer oder Amortisation kennen'],
    ['2','Helvetia: bestätigen lassen, ob direkte Auszahlung/Überweisung für selbstbewohntes Wohneigentum zur Hypothekaramortisation möglich ist','3a-konforme Abwicklung sichern'],
    ['3','Bank: bestätigen lassen, ob Amortisation der Hypothek möglich ist und welche Tranche betroffen wäre','Vertrags-/Trancheneinschränkungen vermeiden'],
    ['4','Steuerbetrag für 3a-Vorbezug berechnen lassen','Nettoeffekt der Hypothekvariante kennen'],
    ['5','Falls Variante E gewählt wird: Dauerauftrag für Folgebeiträge in 3a-Wertschriftenlösung einrichten','Renditehebel der künftigen Beiträge sicherstellen'],
], [1.5*cm,9*cm,5.5*cm])
P('Formulierung an Helvetia: Bitte bestätigen Sie mir den aktuellen Rückkaufs-/Transferwert meiner Säule-3a-Police und die Möglichkeit, diesen Wert direkt zur Amortisation einer selbstbewohnten Hypothek bzw. alternativ an eine anerkannte 3a-Stiftung zu übertragen. Bitte weisen Sie Gebühren, Abzüge, Überschüsse und die notwendigen Formulare separat aus.', box)
S(6)
P('Schlussurteil: Variante E ist eine gute defensive Ergänzung im Entscheidungsbaum, aber bei 0.77 % Hypothekarzins nicht die renditestärkste Lösung. Sie eignet sich, wenn Schuldenabbau und Fixkostenreduktion bewusst höher gewichtet werden als der erwartete Mehrertrag einer Aktien-3a-Lösung.', styles['Heading2'])

# Footer
def footer(canvas, doc):
    canvas.saveState()
    canvas.setFont(base, 7)
    canvas.setFillColor(colors.HexColor('#666666'))
    canvas.drawString(1.6*cm, 1.0*cm, 'Helvetia Lebensversicherung – Finanzberaterbericht Update Hypothekvariante')
    canvas.drawRightString(A4[0]-1.6*cm, 1.0*cm, f'Seite {doc.page}')
    canvas.restoreState()

doc = SimpleDocTemplate(str(OUT), pagesize=A4, leftMargin=1.6*cm, rightMargin=1.6*cm, topMargin=1.55*cm, bottomMargin=1.45*cm, title='Helvetia Lebensversicherung – Finanzberaterbericht Update Hypothekvariante', author='JARVIS')
doc.build(story, onFirstPage=footer, onLaterPages=footer)
print(OUT)
print('A', variants['A Rückkauf/3a-Transfer + Beiträge'])
print('B', variants['B Prämienfrei + Beiträge'])
print('E', variants['E Hypothek tilgen + Beiträge + Zinsersparnis'])
print('annual_interest_saving', annual_interest_saving)
print('interest_savings_fv', interest_savings_fv)
