""" Social Features API routes - user follows and channel messages """ import logging from typing import List from datetime import datetime from fastapi import APIRouter, Depends, HTTPException, status, Query from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.models.db.user import User from app.models.schemas.social import UserFollowResponse, ChannelMessageCreate, ChannelMessageResponse from app.services.social_service import social_service from app.api.deps import get_current_active_user logger = logging.getLogger(__name__) router = APIRouter(prefix="/social", tags=["social"]) # --- User Follows --- @router.post("/follow/{body_id}", response_model=UserFollowResponse) async def follow_body( body_id: str, current_user: User = Depends(get_current_active_user), db: AsyncSession = Depends(get_db) ): """ Allow current user to follow a celestial body. User will then receive events and can post in the body's channel. """ try: follow = await social_service.follow_body(current_user.id, body_id, db) return follow except ValueError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) except Exception as e: logger.error(f"Error following body {body_id} by user {current_user.id}: {e}") raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to follow body") @router.delete("/follow/{body_id}", status_code=status.HTTP_204_NO_CONTENT) async def unfollow_body( body_id: str, current_user: User = Depends(get_current_active_user), db: AsyncSession = Depends(get_db) ): """Allow current user to unfollow a celestial body.""" try: unfollowed = await social_service.unfollow_body(current_user.id, body_id, db) if not unfollowed: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Not following this body") return None except Exception as e: logger.error(f"Error unfollowing body {body_id} by user {current_user.id}: {e}") raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to unfollow body") @router.get("/follows", response_model=List[UserFollowResponse]) async def get_user_follows( current_user: User = Depends(get_current_active_user), db: AsyncSession = Depends(get_db) ): """Get all celestial bodies currently followed by the user.""" follows = await social_service.get_user_follows_with_time(current_user.id, db) return follows @router.get("/follows/check/{body_id}") async def check_if_following( body_id: str, current_user: User = Depends(get_current_active_user), db: AsyncSession = Depends(get_db) ): """Check if the current user is following a specific celestial body.""" is_following = await social_service.get_follow(current_user.id, body_id, db) return {"is_following": is_following is not None} # --- Channel Messages --- @router.post("/channel/{body_id}/message", response_model=ChannelMessageResponse) async def post_channel_message( body_id: str, message: ChannelMessageCreate, current_user: User = Depends(get_current_active_user), db: AsyncSession = Depends(get_db) ): """ Post a message to a specific celestial body's channel. Only users following the body can post. """ try: channel_message = await social_service.post_channel_message(current_user.id, body_id, message.content, db) return channel_message except ValueError as e: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=str(e)) # 403 Forbidden for not following except Exception as e: logger.error(f"Error posting message to channel {body_id} by user {current_user.id}: {e}") raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to post message") @router.get("/channel/{body_id}/messages", response_model=List[ChannelMessageResponse]) async def get_channel_messages( body_id: str, limit: int = Query(50, ge=1, le=500), current_user: User = Depends(get_current_active_user), db: AsyncSession = Depends(get_db) ): """Get recent messages from a celestial body's channel.""" try: messages = await social_service.get_channel_messages(body_id, db, limit) return messages except Exception as e: logger.error(f"Error retrieving messages from channel {body_id}: {e}") raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to retrieve messages")