import logging from typing import Annotated from fastapi import APIRouter, Depends, HTTPException, Request, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.api.deps import get_current_active_user from app.core.config import settings from app.core.database import get_db from app.core.email import EmailService from app.core.rate_limit import limiter from app.models.user import User from app.models.account import Account from app.models.feedback import Feedback from app.schemas.feedback import FeedbackSubmission, FeedbackResponse logger = logging.getLogger(__name__) router = APIRouter(tags=["feedback"]) # TODO: Post-session contextual feedback prompt — when building the post-session # feedback flow, reuse this endpoint by adding optional session_id/tree_id fields # to FeedbackSubmission. The Feedback model and email infrastructure are already # in place. See design doc for details. @router.post("/feedback", response_model=FeedbackResponse) @limiter.limit("1/minute") async def submit_feedback( request: Request, data: FeedbackSubmission, current_user: Annotated[User, Depends(get_current_active_user)], db: Annotated[AsyncSession, Depends(get_db)], ): """Submit user feedback. Saves to DB and sends notification email.""" if not settings.FEEDBACK_EMAIL: raise HTTPException( status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Feedback submission is not configured", ) # Get account info for the email account_name = None account_code = None if current_user.account_id: result = await db.execute( select(Account).where(Account.id == current_user.account_id) ) account = result.scalar_one_or_none() if account: account_name = account.name account_code = account.display_code # Always persist to DB first — email failure should not lose feedback feedback_record = Feedback( account_id=current_user.account_id, user_id=current_user.id, email=data.email, feedback_type=data.feedback_type.value, message=data.message, ) db.add(feedback_record) await db.commit() # Send notification email to admin (best-effort) sent = await EmailService.send_feedback_email( to_email=settings.FEEDBACK_EMAIL, reply_to_email=data.email, feedback_type=data.feedback_type.value, message=data.message, user_email=current_user.email, account_name=account_name, account_code=account_code, ) if not sent: logger.warning("Feedback saved to DB but notification email failed for user %s", current_user.email) # Send confirmation email to submitter (fire-and-forget) message_preview = data.message[:100] + ("..." if len(data.message) > 100 else "") await EmailService.send_feedback_confirmation_email( to_email=data.email, feedback_type=data.feedback_type.value, message_preview=message_preview, ) return FeedbackResponse(success=True, message="Thank you! Your feedback has been submitted.")