from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from src.infrastructure.database import get_db from sqlalchemy import func from src.core.domain.schemas import FeedbackRequest, ChatSession from src.core.domain.db_models import ChatHistory, Feedback from src.core.security import get_current_user from src.core.domain.db_models import User from typing import Optional router = APIRouter() @router.get("/history/{session_id}") def get_chat_history(session_id: str, db: Session = Depends(get_db)): history = db.query(ChatHistory).filter( ChatHistory.session_id == session_id ).order_by(ChatHistory.timestamp.asc()).all() formatted_history = [] for h in history: formatted_history.append({ "id": h.id, "role": h.role, "content": h.content, "timestamp": h.timestamp, "pinned": getattr(h, "pinned", False), }) return {"session_id": session_id, "history": formatted_history} @router.post("/feedback") def submit_feedback(req: FeedbackRequest, db: Session = Depends(get_db)): msg = db.query(ChatHistory).filter( ChatHistory.id == req.message_id, ChatHistory.session_id == req.session_id ).first() if not msg: raise HTTPException(status_code=404, detail="Message not found in session") # Upsert: update existing feedback or create new existing = db.query(Feedback).filter( Feedback.message_id == req.message_id, Feedback.session_id == req.session_id ).first() if existing: existing.rating = req.rating existing.comment = req.comment else: feedback = Feedback( session_id=req.session_id, message_id=req.message_id, rating=req.rating, comment=req.comment ) db.add(feedback) db.commit() return {"status": "success", "message": "Feedback recorded."} @router.get("/feedback/{session_id}") def get_session_feedback(session_id: str, db: Session = Depends(get_db)): """Get all feedback ratings for a session (so UI can restore like/dislike state).""" feedbacks = db.query(Feedback).filter(Feedback.session_id == session_id).all() return {str(f.message_id): f.rating for f in feedbacks} @router.post("/pin/{message_id}") def pin_message(message_id: int, db: Session = Depends(get_db)): """Toggle pin on a message.""" msg = db.query(ChatHistory).filter(ChatHistory.id == message_id).first() if not msg: raise HTTPException(status_code=404, detail="Message not found") # Toggle pinned — add column if missing via getattr current = getattr(msg, "pinned", False) or False msg.pinned = not current db.commit() return {"pinned": msg.pinned} @router.get("/sessions") def get_chat_sessions( current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """Retrieve sessions for the authenticated user only.""" sessions = db.query( ChatHistory.session_id, func.count(ChatHistory.id).label("message_count"), func.max(ChatHistory.timestamp).label("last_active") ).filter( ChatHistory.user_id == current_user.id ).group_by(ChatHistory.session_id).order_by( func.max(ChatHistory.timestamp).desc() ).all() return [ ChatSession( session_id=s.session_id, message_count=s.message_count, last_active=s.last_active ) for s in sessions ] @router.delete("/sessions/{session_id}") def delete_chat_session( session_id: str, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """Delete session — only owner can delete.""" # Verify ownership owned = db.query(ChatHistory).filter( ChatHistory.session_id == session_id, ChatHistory.user_id == current_user.id ).first() if not owned: raise HTTPException(status_code=404, detail="Session not found") db.query(Feedback).filter(Feedback.session_id == session_id).delete() deleted_msgs = db.query(ChatHistory).filter(ChatHistory.session_id == session_id).delete() db.commit() return {"status": "success", "message": f"Deleted session {session_id} with {deleted_msgs} messages."}