from reportlab.lib import colors
from reportlab.lib.enums import TA_LEFT, TA_CENTER
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import mm
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak, KeepTogether
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
from pathlib import Path

OUT = Path('/home/agent/insurance_work/Helvetia_Offerte_vs_aktuelle_Police_Analyse_2026-06-30.pdf')
OUT.parent.mkdir(parents=True, exist_ok=True)

# Fonts: use DejaVu for CHF/apostrophes and German umlauts.
pdfmetrics.registerFont(TTFont('DejaVu', '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'))
pdfmetrics.registerFont(TTFont('DejaVu-Bold', '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf'))

styles = getSampleStyleSheet()
styles.add(ParagraphStyle(name='TitleWhite', parent=styles['Title'], fontName='DejaVu-Bold', fontSize=22, leading=26, textColor=colors.white, alignment=TA_LEFT))
styles.add(ParagraphStyle(name='H1x', parent=styles['Heading1'], fontName='DejaVu-Bold', fontSize=15, leading=18, spaceBefore=10, spaceAfter=7, textColor=colors.HexColor('#7B1E3A')))
styles.add(ParagraphStyle(name='H2x', parent=styles['Heading2'], fontName='DejaVu-Bold', fontSize=12, leading=15, spaceBefore=8, spaceAfter=5, textColor=colors.HexColor('#333333')))
styles.add(ParagraphStyle(name='Bodyx', parent=styles['BodyText'], fontName='DejaVu', fontSize=8.4, leading=11.2, spaceAfter=4))
styles.add(ParagraphStyle(name='Smallx', parent=styles['BodyText'], fontName='DejaVu', fontSize=7.4, leading=9.5, spaceAfter=3))
styles.add(ParagraphStyle(name='Boldx', parent=styles['BodyText'], fontName='DejaVu-Bold', fontSize=8.4, leading=11.2, spaceAfter=4))
styles.add(ParagraphStyle(name='Cell', parent=styles['BodyText'], fontName='DejaVu', fontSize=7.1, leading=8.6))
styles.add(ParagraphStyle(name='CellBold', parent=styles['BodyText'], fontName='DejaVu-Bold', fontSize=7.1, leading=8.6))
styles.add(ParagraphStyle(name='CellSmall', parent=styles['BodyText'], fontName='DejaVu', fontSize=6.5, leading=7.8))

burgundy = colors.HexColor('#7B1E3A')
light_burg = colors.HexColor('#F4E8ED')
green = colors.HexColor('#E7F4EA')
red = colors.HexColor('#FCE8E6')
yellow = colors.HexColor('#FFF4CE')
blue = colors.HexColor('#E8F0FE')
grey = colors.HexColor('#F5F5F5')

def P(text, style='Bodyx'):
    text = str(text).replace('\n','<br/>')
    return Paragraph(text, styles[style])

def money(v):
    return f"CHF {v:,.2f}".replace(',', "'")

def intch(v):
    return f"{int(v):,}".replace(',', "'")

def table(data, widths=None, repeatRows=1, font=7.1):
    conv = []
    for r,row in enumerate(data):
        out=[]
        for c,val in enumerate(row):
            if isinstance(val, Paragraph):
                out.append(val)
            else:
                out.append(P(val, 'CellBold' if r==0 else ('CellSmall' if font < 7 else 'Cell')))
        conv.append(out)
    t = Table(conv, colWidths=widths, repeatRows=repeatRows, hAlign='LEFT')
    t.setStyle(TableStyle([
        ('BACKGROUND',(0,0),(-1,0),burgundy),
        ('TEXTCOLOR',(0,0),(-1,0),colors.white),
        ('FONTNAME',(0,0),(-1,0),'DejaVu-Bold'),
        ('ALIGN',(1,1),(-1,-1),'RIGHT'),
        ('VALIGN',(0,0),(-1,-1),'TOP'),
        ('GRID',(0,0),(-1,-1),0.25,colors.HexColor('#CCCCCC')),
        ('ROWBACKGROUNDS',(0,1),(-1,-1),[colors.white, grey]),
        ('LEFTPADDING',(0,0),(-1,-1),4),('RIGHTPADDING',(0,0),(-1,-1),4),
        ('TOPPADDING',(0,0),(-1,-1),3),('BOTTOMPADDING',(0,0),(-1,-1),3),
    ]))
    return t

old = {'gross':1178.80,'net':1116.70,'stamp':55.90,'firetax':6.20,'service':12.60,'household':285.10,'liability':68.30,'legal':301.00,'building':449.70,
       'household_sum':124100,'contents_follow':24820,'liability_sum':5000000,'building_sum':893200,'building_follow':178640}
new = {'gross':2061.90,'net':1954.60,'stamp':97.70,'firetax':9.60,'service':19.40,'household':584.30,'liability':88.90,'legal':301.00,'building':961.00,
       'household_sum':191000,'contents_follow':38200,'liability_sum':10000000,'building_sum':1325000,'building_follow':265000}

def diff(oldv, newv, pct=True):
    d = newv-oldv
    if pct:
        return f"{money(d)} / {d/oldv*100:+.1f}%"
    return money(d)

def foot(canvas, doc):
    canvas.saveState()
    canvas.setFont('DejaVu', 7)
    canvas.setFillColor(colors.HexColor('#666666'))
    canvas.drawString(12*mm, 8*mm, 'Helvetia Offerte vs. aktuelle Police – Analyse durch JARVIS, keine Rechts-/Versicherungsberatung; Basis: ausgelesene PDF-Dokumente')
    canvas.drawRightString(285*mm, 8*mm, f'Seite {doc.page}')
    canvas.restoreState()

story=[]
# Cover banner
banner = Table([[P('Helvetia Offerte vs. aktuelle Police', 'TitleWhite')],[P('Detaillierte Vergleichsanalyse – Hausrat, Privathaftpflicht, Rechtsschutz, Gebäude, Serviceleistungen', 'TitleWhite')]], colWidths=[260*mm])
banner.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,-1),burgundy),('LEFTPADDING',(0,0),(-1,-1),10),('RIGHTPADDING',(0,0),(-1,-1),10),('TOPPADDING',(0,0),(-1,-1),8),('BOTTOMPADDING',(0,0),(-1,-1),8)]))
story.append(banner)
story.append(Spacer(1,8))
story.append(P('<b>Ausgangslage:</b> Vergleich der laufenden Helvetia Privatkundenversicherung 2024 mit der aktualisierten Offerte/Antrag vom 26.06.2026. Die neue Offerte ersetzt die bisherige Policennummer und läuft bis 01.06.2032; kündbar auf Ende des dritten oder jedes weiteren Versicherungsjahres.', 'Bodyx'))
story.append(P('<b>Kurzfazit:</b> Die neue Offerte verbessert den Schutz deutlich (höhere Hausrat-/Gebäudesummen, 10 Mio. Privathaftpflicht, Cyber, Erdbeben/Vulkanausbruch im Gebäude, Unterversicherungsverzicht Hausrat). Dafür steigt die Bruttoprämie um CHF 883.10/Jahr bzw. rund 75%. Der grösste Kostentreiber ist Gebäude (+CHF 511.30) und Hausrat (+CHF 299.20).', 'Bodyx'))

summary = [
['Entscheidpunkt','Bewertung','Begründung'],
['Schutzqualität','besser','Mehr Deckung und modernere AVB/Deckungen; besonders PH 10 Mio., Cyber, Gebäude-Erdbeben, höhere Versicherungssummen.'],
['Preis/Leistung','gemischt','Prämie steigt fast proportional/überproportional zur Deckung; Hausrat und Gebäude werden deutlich teurer.'],
['Risiko Unterversicherung','besser','Hausrat 191k statt 124.1k; Gebäudesumme 1.325 Mio. statt 893.2k. Aber Gebäude bleibt provisorisch geschätzt.'],
['Flexibilität/Laufzeit','schlechter','Neue Laufzeit bis 2032; faktisch wieder Bindung mit Kündigung erst nach 3 Jahren bzw. danach jährlich.'],
['Empfehlung','bedingt annehmen / nachverhandeln','Annahme sinnvoll, wenn Gebäudeschätzung plausibel und Cyber/Erdbeben gewünscht. Vor Unterschrift Prämientreiber und Kündigungstermin schriftlich klären.']
]
story.append(table(summary, [42*mm,36*mm,182*mm]))

story.append(P('1. Prämienvergleich', 'H1x'))
premium_rows=[['Position','Aktuelle Police','Neue Offerte','Differenz','Einordnung'],
['Serviceleistungen',money(old['service']),money(new['service']),diff(old['service'],new['service']),'teurer; Leistungen ähnlich, Detailtexte leicht erweitert/aktualisiert'],
['Hausrat',money(old['household']),money(new['household']),diff(old['household'],new['household']),'massiv teurer; dafür 54% höhere Summe plus Cyber/All-Risk-Aufteilung'],
['Privathaftpflicht',money(old['liability']),money(new['liability']),diff(old['liability'],new['liability']),'moderat teurer; dafür 10 Mio. statt 5 Mio. und Cyber 100k'],
['Rechtsschutz',money(old['legal']),money(new['legal']),diff(old['legal'],new['legal']),'unverändert; gleiche Versicherungssumme/SB'],
['Gebäudesach',money(old['building']),money(new['building']),diff(old['building'],new['building']),'grösster Kostensprung; 48% höhere Gebäudesumme plus Erdbeben/Vulkanausbruch'],
['Total netto',money(old['net']),money(new['net']),diff(old['net'],new['net']),'Prämie +75.0%'],
['Abgaben',money(old['stamp']+old['firetax']),money(new['stamp']+new['firetax']),diff(old['stamp']+old['firetax'],new['stamp']+new['firetax']),'Folge der höheren Prämie/Summen'],
['Total brutto/Jahr',money(old['gross']),money(new['gross']),diff(old['gross'],new['gross']),'Mehrkosten CHF 883.10/Jahr = CHF 73.59/Monat']]
story.append(table(premium_rows, [42*mm,27*mm,27*mm,38*mm,126*mm]))

story.append(P('2. Deckungssummen und Selbstbehalte', 'H1x'))
coverage_rows=[['Bereich','Aktuelle Police','Neue Offerte','Veränderung','Besser/schlechter'],
['Hausrat',"CHF 124'100; SB 500", "CHF 191'000; SB 500", "+CHF 66'900 / +53.9%", 'besser: deutlich mehr Substanzdeckung'],
['Folge-/Schadenverhütungskosten Hausrat',"CHF 24'820; SB 500", "CHF 38'200; SB 500", "+CHF 13'380 / +53.9%", 'besser, proportional zur Hausratsumme'],
['Einfacher Diebstahl auswärts',"CHF 2'000; SB 200", "CHF 2'000; SB 200", 'unverändert', 'neutral; Limite bleibt eher Basis'],
['Einfacher Diebstahl auswärts PLUS',"CHF 2'000; SB 200", "CHF 2'000; SB 200", 'unverändert', 'neutral'],
['All Risks Hausrat',"Hausrat all risks CHF 2'000; SB 200", "Unterhaltungselektronik, Optikerwaren/Hörgeräte, übriger Hausrat je CHF 2'000; SB 200", 'strukturell besser/transparent', 'tendenziell besser, aber Limiten bleiben tief'],
['Fahrräder/E-Bikes bis 25 km/h',"nicht separat sichtbar", "Diebstahl auswärts CHF 2'000 + all risks CHF 2'000; SB 200", 'neu/ausdrücklich', 'besser für Velos/E-Bikes'],
['Cyber Hausrat',"nicht sichtbar", "CHF 5'000; SB 300", 'neu', 'besser, aber niedrige Limite'],
['Privathaftpflicht Basis',"CHF 5 Mio.; SB 500", "CHF 10 Mio.; SB 500", '+100% Deckungssumme', 'klar besser; Prämienanstieg nur CHF 20.60'],
['PH Schäden an fremden Motorfahrzeugen',"CHF 5 Mio.; SB 500", "CHF 10 Mio.; SB 500", '+100%', 'besser'],
['Cyber PH',"nicht sichtbar", "CHF 100'000; SB 0", 'neu', 'besser; genaue AVB-Ausschlüsse prüfen'],
['Rechtsschutz',"CHF 500'000 pro Fall; SB 0", "CHF 500'000 pro Fall; SB 0", 'unverändert', 'neutral'],
['Gebäude',"CHF 893'200; SB 200", "CHF 1'325'000; SB 200", "+CHF 431'800 / +48.3%", 'besser, falls Schätzung realistisch'],
['Folgekosten Gebäude',"CHF 178'640; SB 200", "CHF 265'000; SB 200", "+CHF 86'360 / +48.3%", 'besser'],
['Gebäude Glasbruch',"versichert; SB 0", "versichert; SB 0", 'unverändert', 'neutral'],
['Erdbeben/Vulkanausbruch Gebäude',"nicht sichtbar", "Gebäude CHF 1'325'000; SB 10%, min. CHF 20'000; Folgekosten etc. CHF 265'000", 'neu', 'besserer Katastrophenschutz, aber hoher Selbstbehalt']]
story.append(table(coverage_rows, [39*mm,42*mm,47*mm,38*mm,94*mm], font=6.5))

story.append(PageBreak())
story.append(P('3. Wo fährst du besser?', 'H1x'))
better=[['Verbesserung','Warum relevant','Bewertung'],
['Privathaftpflicht 10 Mio. statt 5 Mio.','Personenschäden/Sachschäden können sehr teuer werden; 10 Mio. ist marktgerechter als 5 Mio.','sehr gut – Mehrprämie relativ klein'],
['Hausratsumme 191k statt 124.1k','Weniger Risiko, dass Ersatzwert von Möbeln, Technik, Kleidung, Werkzeug, Velo etc. unterschätzt ist.','gut, wenn euer realer Hausratwert Richtung 191k geht'],
['Unterversicherungsverzicht Hausrat','Neue Offerte enthält besondere Bedingung: Helvetia verzichtet mit Ausnahme Elementarschäden unabhängig der Schadenhöhe auf Unterversicherung.','klar positiv, aber Ausnahme Elementar wichtig'],
['Cyber neu sichtbar','Hausrat Cyber CHF 5k und PH Cyber CHF 100k sind neu/ausdrücklich in der Offerte.','positiv, aber Limiten/Ausschlüsse kritisch prüfen'],
['Fahrrad/E-Bike-Deckung separat','Diebstahl auswärts und All Risks für Fahrräder/E-Bikes bis 25 km/h sind explizit aufgeführt.','gut, falls teure Bikes vorhanden'],
['Gebäudesumme 1.325 Mio. statt 893.2k','Baukosten/ Wiederherstellungskosten sind stark gestiegen; alte Summe könnte zu tief sein.','sehr wichtig, falls Neubewertung plausibel'],
['Erdbeben/Vulkanausbruch Gebäude','Neue Offerte enthält diese Deckung; alte Police zeigt sie nicht.','objektiv besser, aber mit 10%/min. 20k SB'],
['Aktuellere AVB','Gemeinsame Bestimmungen 09/2025; Hausrat/PH 09/2025 statt 09/2021.','besser, u.a. wegen Update/Modernisierung']]
story.append(table(better, [50*mm,140*mm,70*mm]))

story.append(P('4. Wo fährst du schlechter oder hast Nachteile?', 'H1x'))
worse=[['Nachteil/Risiko','Konkrete Auswirkung','Meine Einschätzung'],
['Bruttoprämie +CHF 883.10/Jahr','Von CHF 1\'178.80 auf CHF 2\'061.90; monatlich +CHF 73.59.','Das ist der zentrale Trade-off. Schutz besser, aber nicht günstig.'],
['Gebäudeprämie +113.7%','Von CHF 449.70 auf CHF 961.00.','Nur akzeptieren, wenn die neue Gebäudesumme/Erdbebendeckung gewollt und plausibel ist.'],
['Hausratprämie +104.9%','Von CHF 285.10 auf CHF 584.30.','Deutlich über Deckungssummenerhöhung (+53.9%); nachverhandeln/Begründung verlangen.'],
['Neue Vertragslaufzeit bis 2032','Kündbar erst Ende des 3. Versicherungsjahres bzw. danach jährlich.','Schlechtere Flexibilität; vor Unterschrift Kündigungstermin bestätigen lassen.'],
['Gebäude weiterhin provisorisch geschätzt','Definitive Summe/Prämie muss spätestens innert 2 Jahren dokumentiert werden.','Risiko späterer Prämien-/Summenanpassung. Schriftlich klären.'],
['Selbstbehalte Hausrat/PH bleiben gleich','Hausrat/PH weiterhin SB 500; Diebstahl/All Risks 200; Cyber Hausrat 300.','Kein Vorteil trotz höherer Prämie. SB-Reduktion verhandeln.'],
['Elementarschäden vom Unterversicherungsverzicht ausgenommen','Bei Elementar kann Unterversicherung weiterhin ein Problem sein.','Wichtig in CH; Summe muss trotzdem realistisch bleiben.'],
['Cyber-Limite Hausrat nur CHF 5k','Für reale Online-Betrugs-/Phishingfälle kann das knapp sein.','Als Basis ok, nicht als starke Cyberlösung verkaufen lassen.'],
['Erdbeben-Selbstbehalt hoch','10%, mindestens CHF 20k.','Deckung ist besser als keine, aber Eigenanteil im Katastrophenfall beträchtlich.']]
story.append(table(worse, [58*mm,100*mm,102*mm]))

story.append(P('5. Produktbereich: Einordnung im Detail', 'H1x'))
details=[['Bereich','Analyse','Empfehlung'],
['Hausrat','Die neue Summe 191k reduziert Unterversicherungsrisiko klar. Positiv ist die sichtbarere Aufteilung von All Risks und Bikes. Kritisch: Prämie steigt doppelt so stark wie die Summe; Cyber nur 5k.','Akzeptabel, wenn Hausratwert realistisch hoch ist. Sonst Summe/Prämie optimieren lassen. SB 500/200 verhandeln.'],
['Privathaftpflicht','Sehr guter Upgrade: 10 Mio. statt 5 Mio. für nur +CHF 20.60/Jahr. Cyber 100k zusätzlich.','Behalten/akzeptieren. Falls möglich: SB 0 oder tiefere SB anfragen.'],
['Rechtsschutz','Gleich teuer, gleiche Leistung: 500k pro Fall, SB 0, inkl. Arbeitnehmer-/Eigentümer-/Verkehrsbausteine.','Neutral. Prüfen, ob aktuelle Rechtsschutz-AVB oder bessere Arbeitnehmer-/Strafrechtsschutzdeckung möglich ist.'],
['Gebäude','Neue Summe 1.325 Mio. kann wegen Baukosten plausibel sein. Erdbeben/Vulkanausbruch ist neu. Aber Prämie +113.7% und weiterhin provisorische Schätzung.','Nur unterschreiben, wenn Helvetia/Berater die Gebäudesumme und Prämie nachvollziehbar begründet. Gebäude-Schätzung verlangen.'],
['Serviceleistungen','Ähnliche Services, Prämie +CHF 6.80. Neue Details enthalten z.B. bei Türöffnung/Wespennest teils Selbstbehalt CHF 100 und Kostenlimite CHF 1k ohne Vermittlung.','Ok, aber kein Hauptargument für höhere Gesamtprämie.']]
story.append(table(details, [38*mm,148*mm,74*mm]))

story.append(P('6. Offene Punkte / Fragen an Helvetia vor Unterschrift', 'H1x'))
questions=[['Priorität','Frage','Warum'],
['hoch','Wie wurde die neue Gebäudesumme von CHF 1.325 Mio. berechnet? Gibt es eine Schätzung/Berechnungsgrundlage?','Grösster Prämientreiber; provisorische Schätzung kann später angepasst werden.'],
['hoch','Ist die Erdbeben-/Vulkandeckung optional und was kostet sie separat?','Vielleicht ist ein Teil der Gebäudeprämie dadurch erklärbar.'],
['hoch','Warum steigt Hausratprämie um 105%, obwohl die Summe nur um 54% steigt?','Preis-/Leistungshebel für Verhandlung.'],
['hoch','Was ist der nächstmögliche Kündigungstermin der neuen Police exakt?','Neue Laufzeit bis 2032; Flexibilität sichern.'],
['mittel','Welche Cyber-Fälle sind wirklich gedeckt: Phishing, Social Engineering, autorisierte Zahlungen, Anlage-/Krypto-Betrug?','Cyber wirkt gut auf Papier, Ausschlüsse entscheiden.'],
['mittel','Kann PH-Selbstbehalt oder Hausrat-SB reduziert werden ohne relevante Mehrprämie?','Du zahlst deutlich mehr, SB bleibt aber gleich.'],
['mittel','Sind 15% Kombinationsrabatt maximal oder gibt es Gesprächs-/Bestandskundenrabatt?','Du bündelst alle Sparten; Rabattargument.'],
['mittel','Gilt Update-Garantie auch für die aktualisierten AVB und in welchem Umfang?','Sicherstellen, dass neuere Verbesserungen tatsächlich anwendbar sind.']]
story.append(table(questions, [24*mm,138*mm,98*mm]))

story.append(P('7. Entscheidempfehlung', 'H1x'))
story.append(P('<b>Meine Empfehlung:</b> Nicht blind unterschreiben, aber die Offerte ist inhaltlich deutlich besser als die aktuelle Police. Ich würde sie als Verhandlungsbasis nehmen und vor Abschluss drei Punkte hart klären: (1) Gebäudesumme/Prämie/Erdbeben optional, (2) Hausrat-Mehrprämie begründen oder reduzieren, (3) Kündigungstermin und provisorische Schätzung schriftlich bestätigen.', 'Bodyx'))
final_rows=[['Wenn…','Dann…'],
['Gebäudewert 1.325 Mio. realistisch ist und Erdbeben gewünscht wird','Neue Offerte tendenziell annehmen, aber Rabatt/SB verhandeln.'],
['Gebäude-/Hausratsumme überhöht wirkt','Neue Offerte zurück an Berater: optimierte Variante mit tieferen Summen oder ohne optionale Bausteine verlangen.'],
['Cyber als Hauptgrund verkauft wird','Nicht überbewerten: CHF 5k Hausrat-Cyber ist Basis; PH-Cyber 100k klingt gut, Ausschlüsse prüfen.'],
['Du Flexibilität willst','Kürzere Bindung bzw. schriftlichen Kündigungstermin verlangen; sonst bindest du dich faktisch neu.']]
story.append(table(final_rows, [100*mm,160*mm]))
story.append(Spacer(1,6))
story.append(P('<b>Gesamturteil:</b> Schutz klar besser, Preis klar schlechter. Fair wäre die Offerte, wenn Helvetia die Gebäudesumme sauber belegt und bei Hausrat/Gebäude noch Prämie oder Selbstbehalte verbessert. Ohne diese Klärung ist das Paket zwar komfortabler, aber teuer.', 'Boldx'))


doc = SimpleDocTemplate(str(OUT), pagesize=landscape(A4), leftMargin=12*mm, rightMargin=12*mm, topMargin=12*mm, bottomMargin=14*mm, title='Helvetia Offerte vs aktuelle Police Analyse')
doc.build(story, onFirstPage=foot, onLaterPages=foot)
print(OUT)
