from fastapi import APIRouter, Depends, HTTPException, status from pydantic import BaseModel, Field from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from app.core.deps import get_current_active_user, get_db from app.core.security import get_password_hash, verify_password from app.models.favorite import Favorite from app.models.rating import Rating from app.models.spot import Spot from app.models.user import User from app.schemas.user import UserInfo, UserUpdate router = APIRouter() class UserStats(BaseModel): spot_count: int = 0 approved_count: int = 0 favorite_count: int = 0 rating_received: int = 0 class ChangePassword(BaseModel): old_password: str = Field(..., min_length=6) new_password: str = Field(..., min_length=6) @router.get("/me", response_model=UserInfo) async def get_me(current_user: User = Depends(get_current_active_user)): return current_user @router.get("/me/stats", response_model=UserStats) async def get_my_stats( current_user: User = Depends(get_current_active_user), db: AsyncSession = Depends(get_db), ): spot_count = (await db.execute( select(func.count(Spot.id)).where(Spot.creator_id == current_user.id) )).scalar() or 0 approved_count = (await db.execute( select(func.count(Spot.id)).where( Spot.creator_id == current_user.id, Spot.audit_status == "approved" ) )).scalar() or 0 favorite_count = (await db.execute( select(func.count(Favorite.id)).where(Favorite.user_id == current_user.id) )).scalar() or 0 rating_received = (await db.execute( select(func.count(Rating.id)).where( Rating.spot_id.in_( select(Spot.id).where(Spot.creator_id == current_user.id) ) ) )).scalar() or 0 return UserStats( spot_count=spot_count, approved_count=approved_count, favorite_count=favorite_count, rating_received=rating_received, ) @router.put("/me", response_model=UserInfo) async def update_me( payload: UserUpdate, current_user: User = Depends(get_current_active_user), db: AsyncSession = Depends(get_db), ): update_data = payload.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(current_user, field, value) db.add(current_user) await db.commit() await db.refresh(current_user) return current_user @router.post("/me/change-password") async def change_password( payload: ChangePassword, current_user: User = Depends(get_current_active_user), db: AsyncSession = Depends(get_db), ): if not verify_password(payload.old_password, current_user.password_hash): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="旧密码不正确", ) current_user.password_hash = get_password_hash(payload.new_password) db.add(current_user) await db.commit() return {"code": 0, "message": "密码修改成功"} @router.get("/{user_id}", response_model=UserInfo) async def get_user(user_id: int, db: AsyncSession = Depends(get_db)): result = await db.execute(select(User).where(User.id == user_id)) user = result.scalar_one_or_none() if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found", ) return user