# app/api/paypal_ipn.py
import httpx, urllib.parse, os, re
from fastapi import APIRouter, Request, Response, Depends, HTTPException
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.models.topup import Topup, TopupStatus
from app.models.user import User

router = APIRouter(prefix="/paypal", tags=["paypal"])

PP_IPN_VERIFY_URL = "https://ipnpb.paypal.com/cgi-bin/webscr"  # live
# Sandbox: "https://ipnpb.sandbox.paypal.com/cgi-bin/webscr"

def parse_custom(s: str):
    # erwartet "topup:<id>|code:<CODE>"
    data = {}
    for part in (s or "").split("|"):
        if ":" in part:
            k,v = part.split(":",1)
            data[k.strip()] = v.strip()
    return data

@router.post("/ipn")
async def handle_ipn(request: Request, db: Session = Depends(get_db)):
    raw = await request.body()
    params = urllib.parse.parse_qs(raw.decode("utf-8"), keep_blank_values=True)
    # 1) an PayPal zurückposten:
    verify_payload = "cmd=_notify-validate&" + raw.decode("utf-8")
    async with httpx.AsyncClient(timeout=15) as c:
        vr = await c.post(PP_IPN_VERIFY_URL, data=verify_payload,
                          headers={"Content-Type":"application/x-www-form-urlencoded"})
    if vr.text.strip() != "VERIFIED":
        return Response("ignored", status_code=400)

    payment_status = (params.get("payment_status",[None])[0] or "").lower()
    receiver_email = (params.get("receiver_email",[None])[0] or "").lower()
    mc_currency = params.get("mc_currency",[None])[0] or ""
    mc_gross = params.get("mc_gross",[None])[0] or ""
    custom = params.get("custom",[None])[0] or ""
    item_name = params.get("item_name",[None])[0] or ""
    txn_id = params.get("txn_id",[None])[0] or ""

    # Grundvalidierungen
    if payment_status != "completed": 
        return {"ok": True}  # nur completed interessiert
    # Optional: Empfänger-Email prüfen (gegen Config)
    # if receiver_email != CONFIG.paypal_receiver.lower(): return Response("wrong receiver", 400)
    if mc_currency != "EUR": 
        return Response("wrong currency", 400)

    meta = parse_custom(custom)
    topup_id = int(meta.get("topup") or 0)
    code = meta.get("code") or ""

    t = db.query(Topup).filter(Topup.id == topup_id).first()
    if not t or t.status == TopupStatus.confirmed:
        return {"ok": True}

    # Betrag prüfen
    try:
        cents_from_paypal = int(round(float(mc_gross.replace(",", ".")) * 100))
    except Exception:
        return Response("bad amount", 400)
    if int(t.amount_cents or 0) != cents_from_paypal:
        return Response("amount mismatch", 400)

    # Sicherheits-Match: Code im item_name?
    if code and code not in (item_name or ""):
        # nicht hart abbrechen, aber flaggen wäre möglich
        pass

    # Topup bestätigen + Saldo buchen (idempotent)
    t.status = TopupStatus.confirmed
    u = db.query(User).filter(User.id == t.user_id).first()
    u.balance_cents = int(u.balance_cents or 0) + int(t.amount_cents or 0)
    # Optional: t.paypal_txn_id = txn_id
    db.commit()

    return {"ok": True}
