from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from sqlalchemy.orm import Session from typing import List from datetime import date from app.core.database import get_db from app.core.security import decode_access_token from app.models.health import HealthMetric from app.schemas.health import HealthMetricCreate, HealthMetricResponse, HealthMetricUpdate router = APIRouter() security = HTTPBearer() def get_current_user_id(credentials: HTTPAuthorizationCredentials = Depends(security)) -> str: """Extrai user_id do token JWT""" token = credentials.credentials payload = decode_access_token(token) if not payload: raise HTTPException(status_code=401, detail="Token inválido") return payload.get("sub") @router.post("/", response_model=HealthMetricResponse, status_code=status.HTTP_201_CREATED) async def create_health_metric( metric_data: HealthMetricCreate, user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Criar nova métrica de saúde""" new_metric = HealthMetric( user_id=user_id, measurement_date=metric_data.measurement_date, measurement_time=metric_data.measurement_time, weight=metric_data.weight, height=metric_data.height, body_fat_percentage=metric_data.body_fat_percentage, muscle_mass=metric_data.muscle_mass, waist=metric_data.waist, chest=metric_data.chest, hips=metric_data.hips, notes=metric_data.notes ) db.add(new_metric) db.commit() db.refresh(new_metric) return new_metric @router.get("/", response_model=List[HealthMetricResponse]) async def list_health_metrics( user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db), limit: int = 100 ): """Listar todas as métricas de saúde do usuário""" metrics = db.query(HealthMetric).filter( HealthMetric.user_id == user_id ).order_by(HealthMetric.measurement_date.desc()).limit(limit).all() return metrics @router.get("/latest", response_model=HealthMetricResponse) async def get_latest_metric( user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Obter última métrica registrada""" metric = db.query(HealthMetric).filter( HealthMetric.user_id == user_id ).order_by(HealthMetric.measurement_date.desc()).first() if not metric: raise HTTPException(status_code=404, detail="Nenhuma métrica encontrada") return metric @router.get("/{metric_id}", response_model=HealthMetricResponse) async def get_health_metric( metric_id: str, user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Obter métrica específica""" metric = db.query(HealthMetric).filter( HealthMetric.id == metric_id, HealthMetric.user_id == user_id ).first() if not metric: raise HTTPException(status_code=404, detail="Métrica não encontrada") return metric @router.put("/{metric_id}", response_model=HealthMetricResponse) async def update_health_metric( metric_id: str, metric_data: HealthMetricUpdate, user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Atualizar métrica de saúde""" metric = db.query(HealthMetric).filter( HealthMetric.id == metric_id, HealthMetric.user_id == user_id ).first() if not metric: raise HTTPException(status_code=404, detail="Métrica não encontrada") # Atualizar campos update_data = metric_data.dict(exclude_unset=True) for field, value in update_data.items(): setattr(metric, field, value) db.commit() db.refresh(metric) return metric @router.delete("/{metric_id}") async def delete_health_metric( metric_id: str, user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Deletar métrica de saúde""" metric = db.query(HealthMetric).filter( HealthMetric.id == metric_id, HealthMetric.user_id == user_id ).first() if not metric: raise HTTPException(status_code=404, detail="Métrica não encontrada") db.delete(metric) db.commit() return {"message": "Métrica deletada com sucesso"} @router.get("/stats/summary") async def get_health_stats( user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Estatísticas e resumo de saúde""" latest = db.query(HealthMetric).filter( HealthMetric.user_id == user_id ).order_by(HealthMetric.measurement_date.desc()).first() # Pegar primeira e última medição para calcular diferença first = db.query(HealthMetric).filter( HealthMetric.user_id == user_id, HealthMetric.weight.isnot(None) ).order_by(HealthMetric.measurement_date.asc()).first() stats = { "current_weight": float(latest.weight) if latest and latest.weight else None, "current_height": float(latest.height) if latest and latest.height else None, "current_body_fat": float(latest.body_fat_percentage) if latest and latest.body_fat_percentage else None, "weight_change": None, "total_measurements": db.query(HealthMetric).filter(HealthMetric.user_id == user_id).count() } if latest and first and latest.weight and first.weight: stats["weight_change"] = float(latest.weight - first.weight) return stats