from fastapi import APIRouter, Depends, HTTPException, Request
from pydantic import BaseModel
from sqlalchemy.orm import Session
from database import get_db, DiscountCode
import datetime
import logging
from gmail_service import GmailService
import re
router = APIRouter(prefix="/api/publish-request", tags=["publish-request"])
logger = logging.getLogger("publish-request")
class CodesUpload(BaseModel):
codes: str # comma separated
@router.get("/stats")
def get_stats(db: Session = Depends(get_db)):
total = db.query(DiscountCode).count()
used = db.query(DiscountCode).filter(DiscountCode.is_used == 1).count()
available = total - used
return {"total": total, "used": used, "available": available}
@router.post("/codes")
def upload_codes(data: CodesUpload, db: Session = Depends(get_db)):
codes_list = [c.strip() for c in data.codes.split(",") if c.strip()]
added = 0
for code in set(codes_list):
existing = db.query(DiscountCode).filter(DiscountCode.code == code).first()
if not existing:
new_code = DiscountCode(code=code, is_used=0)
db.add(new_code)
added += 1
db.commit()
return {"status": "success", "added": added}
class WebhookData(BaseModel):
email: str
@router.post("/webhook")
async def handle_webhook(request: Request, db: Session = Depends(get_db)):
# Try to parse JSON from Google Forms webhook
try:
data = await request.json()
except:
raise HTTPException(status_code=400, detail="Invalid JSON")
# We expect {"email": "..."} or similar from the Google Apps Script
email = data.get("email") or data.get("Email")
if not email:
logger.error(f"Webhook received without email: {data}")
return {"status": "error", "message": "Email not found in webhook payload"}
email = email.strip().lower()
# Check if this email already got a code
already_assigned = db.query(DiscountCode).filter(DiscountCode.assigned_to_email == email).first()
if already_assigned:
logger.info(f"Email {email} already received code {already_assigned.code}")
return {"status": "success", "message": "Already sent"}
# Get a free code
free_code = db.query(DiscountCode).filter(DiscountCode.is_used == 0).first()
if not free_code:
logger.error("NO FREE DISCOUNT CODES LEFT!")
# Fallback logic: Notify admin?
return {"status": "error", "message": "No codes available"}
# Mark as used
free_code.is_used = 1
free_code.assigned_to_email = email
free_code.used_at = datetime.datetime.utcnow()
db.commit()
# Send Thank You Email with GmailService
service = GmailService(db)
subject = "Dankeschön für Eure Freigabe & Euer Rabattcode"
# HTML Signature from frontend
SIGNATURE_HTML = """
Liebe Grüße,
Euer Team von Kinderfotos Erding
Zierl Fotografen GmbH
Anton-Bruckner-Straße 5
85435 Erding
Hallo,
vielen Dank für Eure Unterstützung und das Ausfüllen der Freigabe!
Als kleines Dankeschön hier Euer 25 € Rabattcode für Eure Bestellung:
{free_code.code}
Bitte wartet mit Eurer Bestellung, falls Ihr noch nicht bestellt habt, bis Ihr diesen Code an der Kasse einlösen könnt.
{SIGNATURE_HTML} """ try: success = service.send_email(email, subject, body_html) if success: logger.info(f"Successfully sent code {free_code.code} to {email}") return {"status": "success", "message": "Email sent"} else: logger.error(f"Failed to send email to {email}") free_code.is_used = 0 free_code.assigned_to_email = None free_code.used_at = None db.commit() return {"status": "error", "message": "Failed to send email"} except Exception as e: logger.exception("Error sending webhook email") free_code.is_used = 0 free_code.assigned_to_email = None free_code.used_at = None db.commit() return {"status": "error", "message": str(e)}