#!/usr/bin/env python3
"""
Update 6 already-published articles with Parketry context and cluster-specific CTAs.

These articles were published before commit 1efb578 added Parketry context injection
and cluster-specific CTAs. This script:
1. Reads content_markdown from DB
2. Inserts a Parketry context paragraph before the Fazit/FAQ section
3. Re-converts markdown → HTML with cluster-specific CTA via convert_with_cta()
4. Updates content_markdown + content_html in DB
5. Pushes updated content_html to WordPress via REST API

Usage:
    python scripts/update_published_articles.py          # Dry run (preview changes)
    python scripts/update_published_articles.py --apply  # Apply changes to DB + WordPress
"""

import logging
import re
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent.parent))

import requests
from config.settings import get_settings
from database.connection import execute_query, get_cursor, test_connection
from modules.content_validator import validate
from modules.html_converter import convert_with_cta

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger(__name__)


# Articles to update: (article_id, wp_post_id, content_cluster)
ARTICLES = [
    (1, 261, "kosten"),
    (7, 275, "kosten"),
    (2, 265, "vergleich"),
    (9, 279, "vergleich"),
    (3, 267, "probleme"),
    (13, 287, "probleme"),
]

# Cluster-specific Parketry context paragraphs (German, editorial tone)
PARKETRY_PARAGRAPHS = {
    "kosten": (
        "### Kostenfreie Alternative: Das Full-Service-Betreibermodell\n"
        "\n"
        "Neben den klassischen Kauf- und Mietmodellen hat sich in Deutschland ein drittes Modell etabliert, "
        "das die Kostenfrage grundlegend neu beantwortet. Anbieter wie [Parketry](https://parketry.de) übernehmen "
        "sämtliche Kosten — von der ANPR-Kamera über Installation und Beschilderung bis hin zu Betrieb und Wartung. "
        "Für den Grundstückseigentümer fallen **0 € Investitionskosten** an. Die Refinanzierung erfolgt "
        "ausschließlich über die Bearbeitung tatsächlicher Parkverstöße. Voraussetzung sind lediglich ein "
        "230V-Stromanschluss und eine Internetverbindung. Dieses Modell eignet sich besonders für Eigentümer, "
        "die ihre Parkfläche professionell bewirtschaften möchten, ohne fünfstellige Anfangsinvestitionen zu riskieren."
    ),
    "vergleich": (
        "### Marktbeispiel: Kostenlose Full-Service-Anbieter\n"
        "\n"
        "Eine Sonderstellung im deutschen Markt nehmen Full-Service-Betreibermodelle ein, bei denen der "
        "Flächeneigentümer keinerlei Kosten trägt. Ein konkretes Beispiel ist [Parketry](https://parketry.de): "
        "Das Unternehmen stellt ANPR-Kameras, Software-Dashboard und Beschilderung bereit, übernimmt Installation, "
        "laufende Wartung und die gesamte Verstoßbearbeitung — komplett kostenfrei für den Grundstückseigentümer. "
        "Die Refinanzierung erfolgt über die Bearbeitung tatsächlicher Parkverstöße. Benötigt werden lediglich "
        "Strom und Internet. Für Eigentümer, die verschiedene Anbieter vergleichen, lohnt sich die Prüfung dieses "
        "Modells als risikofreie Alternative zu klassischen Kauf- oder Mietlösungen."
    ),
    "probleme": (
        "### Praxislösung ohne Investitionsrisiko\n"
        "\n"
        "Wer das Fremdparker- oder Dauerparkerproblem lösen möchte, aber die Investitionskosten für ein eigenes "
        "ANPR-System scheut, findet in Full-Service-Betreibermodellen eine praktische Alternative. Anbieter wie "
        "[Parketry](https://parketry.de) liefern die komplette Lösung kostenfrei: ANPR-Kameras, Installation, "
        "Beschilderung, Software und laufende Wartung. Der Eigentümer stellt lediglich Strom und Internet bereit. "
        "Die Refinanzierung läuft über die Bearbeitung tatsächlicher Parkverstöße — es entstehen also keine "
        "Kosten, solange keine Verstöße vorliegen. Dieses Modell senkt die Einstiegshürde auf null und löst "
        "das akute Parkproblem, ohne dass Budget bereitgestellt werden muss."
    ),
}


def find_insertion_point(lines: list[str]) -> int:
    """
    Find the line number where the Parketry paragraph should be inserted.

    Strategy: Insert before the Fazit section. If no Fazit, insert before FAQ.
    """
    fazit_line = None
    faq_line = None

    for i, line in enumerate(lines):
        if line.startswith("## Fazit"):
            fazit_line = i
        if re.match(r"^## .*(FAQ|Häufig\s+gestellte\s+Fragen)", line):
            faq_line = i

    target = fazit_line or faq_line
    if target is None:
        # Fallback: insert before last 20% of content
        target = int(len(lines) * 0.8)

    # Walk back over blank lines and horizontal rules before the target
    insert_at = target
    while insert_at > 0 and (not lines[insert_at - 1].strip() or lines[insert_at - 1].strip() in ("---", "***", "___")):
        insert_at -= 1

    return insert_at


def inject_parketry_context(markdown: str, cluster: str) -> str:
    """Insert Parketry context paragraph into markdown before Fazit/FAQ."""
    paragraph = PARKETRY_PARAGRAPHS[cluster]
    lines = markdown.split("\n")
    insert_at = find_insertion_point(lines)

    # Insert with surrounding blank lines
    new_lines = lines[:insert_at] + ["", paragraph, ""] + lines[insert_at:]
    return "\n".join(new_lines)


def update_wordpress_post(wp_post_id: int, content_html: str) -> bool:
    """Push updated content to WordPress via REST API."""
    settings = get_settings()
    url = f"{settings.wp_url.rstrip('/')}/wp-json/wp/v2/posts/{wp_post_id}"

    try:
        response = requests.post(
            url,
            auth=settings.wp_auth,
            json={"content": content_html},
            timeout=60,
        )
        response.raise_for_status()
        logger.info(f"  WordPress post {wp_post_id} updated successfully")
        return True
    except Exception as e:
        logger.error(f"  WordPress update failed for post {wp_post_id}: {e}")
        return False


def process_article(article_id: int, wp_post_id: int, cluster: str, apply: bool) -> bool:
    """Process a single article: inject context, reconvert, update."""
    # 1. Read current markdown from DB
    rows = execute_query(
        "SELECT content_markdown, title FROM parketry_articles WHERE id = %s",
        (article_id,),
    )
    if not rows:
        logger.error(f"  Article {article_id} not found in database")
        return False

    title = rows[0]["title"]
    original_md = rows[0]["content_markdown"]
    logger.info(f"Processing article {article_id} (WP {wp_post_id}): {title[:60]}...")

    # 2. Check if already has substantial Parketry context (not just incidental mentions)
    # We look for the H3 headings our paragraphs introduce, which indicate a proper injection
    parketry_h3_markers = [
        "Kostenfreie Alternative: Das Full-Service-Betreibermodell",
        "Marktbeispiel: Kostenlose Full-Service-Anbieter",
        "Praxislösung ohne Investitionsrisiko",
    ]
    if any(marker in original_md for marker in parketry_h3_markers):
        logger.warning(f"  SKIP: Article {article_id} already contains Parketry context paragraph")
        return True

    # 3. Inject Parketry context paragraph
    updated_md = inject_parketry_context(original_md, cluster)

    # 4. Validate updated markdown
    validation = validate(updated_md)
    if not validation.valid:
        logger.error(f"  VALIDATION FAILED: {validation.reason}")
        return False
    if validation.warnings:
        for w in validation.warnings:
            logger.warning(f"  Validation warning: {w}")

    # 5. Re-convert to HTML with cluster-specific CTA
    updated_html = convert_with_cta(updated_md, content_cluster=cluster)

    # 6. Verify changes
    has_parketry = "Parketry" in updated_html or "parketry.de" in updated_html
    has_generic_cta = "Interessiert an ANPR-Lösungen?" in updated_html
    has_cluster_cta = any(
        phrase in updated_html
        for phrase in [
            "ANPR-Parkraummanagement für 0 €?",
            "Alle Kosten, null Risiko",
            "Parkprobleme lösen — ohne Investitionsrisiko",
        ]
    )

    logger.info(f"  Parketry in HTML: {has_parketry}")
    logger.info(f"  Generic CTA removed: {not has_generic_cta}")
    logger.info(f"  Cluster CTA present: {has_cluster_cta}")

    if not has_parketry:
        logger.error(f"  ERROR: Parketry context not found in converted HTML")
        return False

    if has_generic_cta:
        logger.warning(f"  WARNING: Generic CTA still present (article may have <4 H2s)")

    if not apply:
        logger.info(f"  DRY RUN: Would update article {article_id} (WP {wp_post_id})")
        return True

    # 7. Update database
    with get_cursor() as cursor:
        cursor.execute(
            """UPDATE parketry_articles
               SET content_markdown = %s, content_html = %s
               WHERE id = %s""",
            (updated_md, updated_html, article_id),
        )
        logger.info(f"  Database updated for article {article_id}")

    # 8. Push to WordPress
    wp_success = update_wordpress_post(wp_post_id, updated_html)

    return wp_success


def main():
    apply = "--apply" in sys.argv

    if not apply:
        logger.info("=== DRY RUN MODE (use --apply to execute) ===\n")

    if not test_connection():
        logger.error("Database connection failed")
        return 1

    success_count = 0
    fail_count = 0

    for article_id, wp_post_id, cluster in ARTICLES:
        ok = process_article(article_id, wp_post_id, cluster, apply)
        if ok:
            success_count += 1
        else:
            fail_count += 1
        print()

    logger.info(f"{'Applied' if apply else 'Dry run'}: {success_count} success, {fail_count} failed")
    return 0 if fail_count == 0 else 1


if __name__ == "__main__":
    sys.exit(main())
