"""Author RAG — Support Service. Business logic for admin support: publish-help request orchestration. """ from datetime import datetime, timezone import structlog from fastapi import HTTPException from sqlalchemy.ext.asyncio import AsyncSession from app.config import get_settings from app.models.user import User from app.repositories.book_repo import BookRepository from app.schemas.admin import ContactRequest, PublishHelpRequest from app.services.book_url_scraper import PLATFORM_DISPLAY from app.services.platform_presence import SCORED_PLATFORMS logger = structlog.get_logger(__name__) _PLATFORM_NAMES = { p["platform_id"]: p["display_name"] for p in SCORED_PLATFORMS } class SupportService: """Orchestrates publish-help requests and support config.""" def __init__(self, db: AsyncSession) -> None: self._db = db self._books = BookRepository(db) @staticmethod def get_config() -> dict: """Return support contact info for the admin UI.""" cfg = get_settings() return { "support_email": str(cfg.SUPPORT_EMAIL) if cfg.SUPPORT_EMAIL else None, } async def queue_publish_help_request( self, user: User, body: PublishHelpRequest ) -> dict: """Validate, build payload, and queue publish-help email to support.""" cfg = get_settings() if not cfg.SUPPORT_EMAIL: raise HTTPException(503, "Support email is not configured") book_meta = await self._resolve_book_meta(user.id, body) platform_names = [ _PLATFORM_NAMES.get(pid, PLATFORM_DISPLAY.get(pid, pid.replace("_", " ").title())) for pid in body.platform_ids ] payload = { "author_name": user.full_name or user.email, "author_email": user.email, "book_title": body.book_title, "book_id": body.book_id, "isbn": (book_meta or {}).get("isbn"), "book_author": (book_meta or {}).get("book_author"), "source_url": body.source_url or (book_meta or {}).get("source_url"), "platform_names": platform_names, "message": body.message, "submitted_at": datetime.now(timezone.utc).isoformat(), } from app.tasks.email_task import send_publish_help_request as send_publish_help_task send_publish_help_task.delay(payload) logger.info( "Publish help request queued", author_id=user.id, book_id=body.book_id, platforms=body.platform_ids, ) return {"message": "Request received — we'll reply within 24 hours"} async def queue_contact_request( self, user: User, body: ContactRequest ) -> dict: """Validate and queue a general contact email to support.""" cfg = get_settings() if not cfg.SUPPORT_EMAIL: raise HTTPException(503, "Support email is not configured") category_labels = { "general": "General", "billing": "Billing", "technical": "Technical", "publishing": "Publishing", } payload = { "author_name": user.full_name or user.email, "author_email": user.email, "category": category_labels.get(body.category, body.category), "message": body.message, "submitted_at": datetime.now(timezone.utc).isoformat(), } from app.tasks.email_task import send_contact_request as send_contact_task send_contact_task.delay(payload) logger.info("Contact request queued", author_id=user.id, category=body.category) return {"message": "Message sent — we'll reply within 24 hours"} async def _resolve_book_meta( self, author_id: str, body: PublishHelpRequest ) -> dict | None: """Load ISBN/author/source_url from DB when book_id is provided.""" if not body.book_id: return None book = await self._books.get_by_id(body.book_id) if not book or book.author_id != author_id: raise HTTPException(404, "Book not found") return { "isbn": book.isbn, "source_url": book.source_url or body.source_url, "book_author": book.book_author, }