#!/usr/bin/env python3
"""
P39 Phase B — Fix actual content gaps in legal templates.

For each template with a genuine content gap (identified by P39 audit),
insert the missing mandatory section. Targeted edits — does NOT
overwrite the full template content.

Templates fixed:
  - data_protection_policy: add "Verantwortlicher" section (Art. 13(1)(a))
  - applicant_dsi:          add "Drittlandtransfer" section (Art. 13(1)(f))
  - employee_dsi:           add "Drittlandtransfer" section (Art. 13(1)(f))
  - cookie_policy:          add concrete cookie table example
  - dsfa:                   add LfDI / Aufsichtsbehoerden-Referenz
  - widerruf:               add §312k BGB Online-Kuendigungsbutton clause

Run inside container:
    docker exec bp-compliance-backend python /app/scripts/fix_template_content.py
    (dry-run by default; pass --apply to UPDATE the DB)
"""

from __future__ import annotations

import os
import sys

import psycopg2
from psycopg2.extras import RealDictCursor


# Sentinels: each fix has (a) where to insert, (b) what to insert,
# (c) a check string to verify the insertion already happened (idempotent).

FIXES = [
    {
        "document_type": "data_protection_policy",
        "language": "de",
        "already_done_marker": "## 1. Verantwortlicher",
        "anchor": None,  # Insert at top (after first heading)
        "insert_block": """## 1. Verantwortlicher

Verantwortlich fuer die in dieser Richtlinie beschriebene Verarbeitung personenbezogener Daten im Sinne der DSGVO ist:

**{{company_legal_name}}**
{{company_address}}
{{company_postal}} {{company_city}}, {{company_country}}

E-Mail: {{company_email}}
Telefon: {{company_phone}}

Datenschutzbeauftragte/r: {{dpo_name}} ({{dpo_email}})

""",
    },
    {
        "document_type": "applicant_dsi",
        "language": "de",
        "already_done_marker": "## 7. Drittlandtransfer",
        "anchor": "## 7.",  # generic; we insert before whatever 7 is
        "insert_block": """## 7. Drittlandtransfer (Art. 13(1)(f) DSGVO)

Eine Uebermittlung Ihrer Bewerberdaten in Laender ausserhalb der Europaeischen Union oder des Europaeischen Wirtschaftsraums (Drittland) findet **nicht** statt. Saemtliche Verarbeitung erfolgt ausschliesslich auf Servern innerhalb der EU.

Sollten in Ausnahmefaellen Drittlandtransfers erforderlich werden (z.B. Konzern-Verbund mit US-Schwestergesellschaft), erfolgen diese ausschliesslich auf Basis von EU-Standardvertragsklauseln (Art. 46(2)(c) DSGVO) oder eines Angemessenheitsbeschlusses der EU-Kommission (Art. 45 DSGVO).

""",
    },
    {
        "document_type": "employee_dsi",
        "language": "de",
        "already_done_marker": "## 7. Drittlandtransfer",
        "anchor": "## 7.",
        "insert_block": """## 7. Drittlandtransfer (Art. 13(1)(f) DSGVO)

Eine Uebermittlung Ihrer Beschaeftigtendaten in Laender ausserhalb der Europaeischen Union oder des Europaeischen Wirtschaftsraums (Drittland) findet grundsaetzlich **nicht** statt. Eine Ausnahme bilden Cloud-Dienste, die ggf. auf US-Server zugreifen — in diesem Fall erfolgt die Uebermittlung auf Basis von EU-Standardvertragsklauseln (Art. 46(2)(c) DSGVO) oder unter dem EU-US Data Privacy Framework (Angemessenheitsbeschluss vom 10.07.2023, Art. 45 DSGVO).

Empfaengerland und Schutzmechanismus pro genutztem Dienst: siehe Verarbeitungsverzeichnis (VVT).

""",
    },
    {
        "document_type": "cookie_policy",
        "language": "de",
        "already_done_marker": "### 4.1 Konkrete Cookie-Tabelle",
        "anchor": None,  # append before the final heading or at end
        "insert_block": """### 4.1 Konkrete Cookie-Tabelle (Beispiel)

| Name | Anbieter | Zweck | Speicherdauer | Typ |
|---|---|---|---|---|
| `__session` | {{company_legal_name}} | Sitzungs-Authentifizierung | Sitzungsende | First-Party, technisch notwendig |
| `cookie_consent` | {{company_legal_name}} | Speicherung der Cookie-Einwilligung | 12 Monate | First-Party, technisch notwendig |
| `_ga` | Google Ireland Ltd. | Webanalyse (Google Analytics) | 2 Jahre | Third-Party, Statistik — Einwilligung erforderlich |
| `_fbp` | Meta Platforms Ireland Ltd. | Marketing / Conversion-Tracking | 90 Tage | Third-Party, Marketing — Einwilligung erforderlich |

> Hinweis: Die obenstehende Tabelle ist beispielhaft. Die tatsaechlich von Ihrer Website gesetzten Cookies pflegen Sie im Backend Ihres Consent-Tools (z.B. Cookiebot, Usercentrics, Borlabs). Die DSK-Orientierungshilfe Telemedien 2024 fordert je Cookie: Name, Anbieter, Zweck, Speicherdauer, Typ (First-/Third-Party).

""",
    },
    {
        "document_type": "dsfa",
        "language": "de",
        "already_done_marker": "### 0.2 Beruecksichtigung Landesaufsichtsbehoerden",
        "anchor": None,
        "insert_block": """### 0.2 Beruecksichtigung Landesaufsichtsbehoerden (LfDI) und DSK-Liste

Diese DSFA beruecksichtigt:

- **DSK-Positivliste** nach Art. 35(4) DSGVO: Die Datenschutzkonferenz (DSK) hat eine Liste von Verarbeitungen veroeffentlicht, die zwingend eine DSFA erfordern. Pruefen Sie, ob Ihre Verarbeitung dort gelistet ist.
- **Landesbeauftragte fuer Datenschutz (LfDI)**: Jedes Bundesland (BfDI, BlnBDI, LfDI BW, LfDI BY, etc.) veroeffentlicht eigene Orientierungshilfen und Branchen-Stellungnahmen. Zustaendige Behoerde: {{supervisory_authority}}.
- **EDPB Guidelines** (insbesondere WP248 — Kriterien fuer DSFA-Erforderlichkeit, Art. 29-Datenschutzgruppe).
- **Branchenspezifische Aufsichtsempfehlungen** (z.B. Telemedien: DSK-OH 2024, Gesundheit: BfDI-Empfehlungen).

""",
    },
    {
        "document_type": "widerruf",
        "language": "de",
        "already_done_marker": "## §312k BGB",
        "anchor": None,
        "insert_block": """## §312k BGB — Online-Kuendigungsbutton (bei Dauerschuldverhaeltnissen)

Bietet der Unternehmer Vertraege ueber **Dauerschuldverhaeltnisse** (Abonnements, Mitgliedschaften, SaaS-Subscriptions) auf seiner Website an, muss er nach §312k BGB einen Kuendigungsbutton bereitstellen.

**Anforderungen** (BGH-Rechtsprechung 2023):

- Der Button muss deutlich beschriftet sein mit "Vertraege hier kuendigen" oder gleichwertig.
- Direkt nach Klick muss eine Bestaetigungsseite folgen mit Angaben zu Vertragsart, Vertragspartnern und Kuendigungstermin.
- Nach Bestaetigung muss eine Bestaetigung der Kuendigung per E-Mail oder dauerhaft auf einem Datentraeger zur Verfuegung gestellt werden.

**Verstoss**: Eine Kuendigung kann auch ohne den Button per E-Mail/Brief jederzeit erfolgen — fehlt der Button, kann der Vertrag zudem von der zustaendigen Verbraucherzentrale abgemahnt werden (§312k Abs. 6 BGB).

**Ausnahme**: §312k gilt nur fuer Verbraucherkunden (B2C). Bei reinen B2B-Vertraegen besteht keine Pflicht.

""",
    },
]


def apply_fix(content: str, fix: dict) -> tuple[str, str]:
    """Returns (new_content, status). Status: 'unchanged'/'inserted'/'already-fixed'."""
    if fix["already_done_marker"] in content:
        return content, "already-fixed"
    anchor = fix["anchor"]
    if anchor and anchor in content:
        # Insert BEFORE the anchor
        new_content = content.replace(anchor, fix["insert_block"] + anchor, 1)
    else:
        # Append at end
        new_content = content.rstrip() + "\n\n" + fix["insert_block"]
    return new_content, "inserted"


def main(apply: bool):
    dsn = os.environ.get("DATABASE_URL") or os.environ.get("COMPLIANCE_DATABASE_URL")
    if not dsn:
        print("ERROR: DATABASE_URL not set", file=sys.stderr)
        return 1
    conn = psycopg2.connect(dsn)
    cur = conn.cursor(cursor_factory=RealDictCursor)
    summary = []
    for fix in FIXES:
        cur.execute(
            "SELECT id, content FROM compliance.compliance_legal_templates "
            "WHERE document_type=%s AND language=%s AND status='published'",
            (fix["document_type"], fix["language"]),
        )
        rows = cur.fetchall()
        if not rows:
            summary.append((fix["document_type"], fix["language"], "not-found", 0))
            continue
        for row in rows:
            new_content, status = apply_fix(row["content"], fix)
            if status == "inserted" and apply:
                cur.execute(
                    "UPDATE compliance.compliance_legal_templates "
                    "SET content=%s, updated_at=now() WHERE id=%s",
                    (new_content, row["id"]),
                )
            summary.append((fix["document_type"], fix["language"], status,
                            len(new_content) - len(row["content"])))
    if apply:
        conn.commit()
    print(f"\n== Template Content Fixes ({'APPLIED' if apply else 'DRY-RUN'}) ==")
    for doc_type, lang, status, delta in summary:
        marker = "✓" if status == "inserted" else ("·" if status == "already-fixed" else "✗")
        print(f"  {marker} {doc_type:30s} [{lang}] {status:14s} (+{delta} chars)")
    return 0


if __name__ == "__main__":
    apply = "--apply" in sys.argv
    sys.exit(main(apply))
