# -*- coding: utf-8 -*-
"""
webhook_app.py - Empfaengt den WooCommerce-Bestell-Webhook.

Ablauf:
  1) Signatur pruefen (HMAC-SHA256 mit WC_WEBHOOK_SECRET) -> Schutz vor Faelschungen
  2) Bestelldaten parsen: gekaufte Produkt-IDs + Geburtsdaten aus den Checkout-Feldern
  3) Pro relevantem Band einen Job als JSON-Datei in JOBS_DIR/pending ablegen
  4) SOFORT mit 200 antworten - die eigentliche PDF-Erstellung macht der Worker

Die App rechnet und mailt NICHTS selbst - sie nimmt nur entgegen und stellt in
die Warteschlange. Das haelt den Webhook schnell (kein Timeout bei WooCommerce).

Umgebungsvariablen:
  WC_WEBHOOK_SECRET   geheime Zeichenkette (identisch in WooCommerce hinterlegt)
  JOBS_DIR            Verzeichnis fuer die Job-Warteschlange (default: ./jobs)

Die Geburtsdaten erwartet die App in den WooCommerce-Order-Meta-Feldern:
  _geburtsdatum   (TT.MM.JJJJ)
  _geburtszeit    (HH:MM)
  _geburtsort     (Klartext, z.B. 'Hamburg')
(Diese Feldnamen richten wir spaeter im Checkout ein.)
"""
import os
import json
import hmac
import base64
import hashlib
import time
import uuid
from flask import Flask, request, abort

app = Flask(__name__)

HERE = os.path.dirname(os.path.abspath(__file__))
JOBS_DIR = os.environ.get("JOBS_DIR", os.path.join(HERE, "jobs"))
PENDING = os.path.join(JOBS_DIR, "pending")
os.makedirs(PENDING, exist_ok=True)

# Welche Produkt-IDs loesen welchen Band aus.
# Start: nur Band I (11865). Pakete/weitere Baende spaeter ergaenzen.
PRODUCT_BAND_MAP = {
    11865: ["I"],            # Band I: Grundprofil
    # 11866: ["II"],         # Band II: Energie Timeline
    # 11867: ["III"],        # Band III: Business & Finanzen
    # 11868: ["IV"],         # Band IV: Liebe & Partnerschaft
    # 11869: ["V"],          # Band V: Familie & Beziehungen
    # 11870: ["I", "II"],    # Startpaket
    # 11871: ["I", "II", "III", "IV", "V"],  # Komplettpaket
}


def _verify_signature(raw_body):
    """Prueft die WooCommerce-Webhook-Signatur (Base64(HMAC-SHA256(body, secret)))."""
    secret = os.environ.get("WC_WEBHOOK_SECRET")
    if not secret:
        # Ohne gesetztes Secret lehnen wir grundsaetzlich ab - sicherer Default.
        return False
    sig_header = request.headers.get("X-WC-Webhook-Signature", "")
    expected = base64.b64encode(
        hmac.new(secret.encode("utf-8"), raw_body, hashlib.sha256).digest()
    ).decode("utf-8")
    return hmac.compare_digest(sig_header, expected)


def _extract_meta(order, key):
    """Liest ein Order-Meta-Feld aus der WooCommerce-Payload."""
    for m in order.get("meta_data", []):
        if m.get("key") == key:
            return (m.get("value") or "").strip()
    return ""


@app.route("/webhook/order", methods=["POST"])
def order_webhook():
    raw = request.get_data()  # roher Body fuer die Signaturpruefung
    if not _verify_signature(raw):
        abort(401, "Ungueltige Signatur.")

    try:
        order = json.loads(raw.decode("utf-8"))
    except Exception:
        abort(400, "Kein gueltiges JSON.")

    # Nur bezahlte/abgeschlossene Bestellungen verarbeiten
    status = order.get("status")
    if status not in ("processing", "completed"):
        return ("ignoriert (Status %s)" % status, 200)

    order_id = order.get("id")
    billing = order.get("billing", {}) or {}
    email = (billing.get("email") or "").strip()
    name = (f"{billing.get('first_name','')} {billing.get('last_name','')}").strip()

    geburtsdatum = _extract_meta(order, "_geburtsdatum")
    geschlecht = _extract_meta(order, "_geschlecht")
    geburtszeit = _extract_meta(order, "_geburtszeit")
    geburtsort = _extract_meta(order, "_geburtsort")
    geburtsland = _extract_meta(order, "_geburtsland")
    geburts_plz = _extract_meta(order, "_geburts_plz")
    geburt_lat = _extract_meta(order, "_geburt_lat")
    geburt_lon = _extract_meta(order, "_geburt_lon")

    # Welche Baende wurden gekauft?
    baende = []
    for item in order.get("line_items", []):
        pid = item.get("product_id")
        if pid in PRODUCT_BAND_MAP:
            baende.extend(PRODUCT_BAND_MAP[pid])
    baende = list(dict.fromkeys(baende))  # Duplikate raus, Reihenfolge halten

    if not baende:
        return ("keine relevanten Produkte", 200)

    # Pro Band einen Job ablegen
    erstellt = []
    for band in baende:
        job = {
            "job_id": uuid.uuid4().hex,
            "order_id": order_id,
            "band": band,
            "kunde_name": name,
            "kunde_email": email,
            "geschlecht": geschlecht,
            "geburtsdatum": geburtsdatum,
            "geburtszeit": geburtszeit,
            "geburtsort": geburtsort,
            "geburtsland": geburtsland,
            "geburts_plz": geburts_plz,
            "geburt_lat": geburt_lat,
            "geburt_lon": geburt_lon,
            "created_at": time.time(),
            "attempts": 0,
        }
        path = os.path.join(PENDING, f"{job['job_id']}.json")
        tmp = path + ".tmp"
        with open(tmp, "w", encoding="utf-8") as f:
            json.dump(job, f, ensure_ascii=False, indent=2)
        os.rename(tmp, path)  # atomar - der Worker sieht nur fertige Dateien
        erstellt.append(job["job_id"])

    return ({"status": "queued", "jobs": erstellt}, 200)


@app.route("/health", methods=["GET"])
def health():
    return ({"ok": True, "pending": len(os.listdir(PENDING))}, 200)
