""" Weight Tracking Endpoints for Mitai Jinkendo Handles weight log CRUD operations and statistics. """ import uuid from typing import Optional from fastapi import APIRouter, Header, Depends from db import get_db, get_cursor, r2d from auth import require_auth from models import WeightEntry from routers.profiles import get_pid router = APIRouter(prefix="/api/weight", tags=["weight"]) @router.get("") def list_weight(limit: int=365, x_profile_id: Optional[str]=Header(default=None), session: dict=Depends(require_auth)): """Get weight entries for current profile.""" pid = get_pid(x_profile_id) with get_db() as conn: cur = get_cursor(conn) cur.execute( "SELECT * FROM weight_log WHERE profile_id=%s ORDER BY date DESC LIMIT %s", (pid,limit)) return [r2d(r) for r in cur.fetchall()] @router.post("") def upsert_weight(e: WeightEntry, x_profile_id: Optional[str]=Header(default=None), session: dict=Depends(require_auth)): """Create or update weight entry (upsert by date).""" pid = get_pid(x_profile_id) with get_db() as conn: cur = get_cursor(conn) cur.execute("SELECT id FROM weight_log WHERE profile_id=%s AND date=%s", (pid,e.date)) ex = cur.fetchone() if ex: cur.execute("UPDATE weight_log SET weight=%s,note=%s WHERE id=%s", (e.weight,e.note,ex['id'])) wid = ex['id'] else: wid = str(uuid.uuid4()) cur.execute("INSERT INTO weight_log (id,profile_id,date,weight,note,created) VALUES (%s,%s,%s,%s,%s,CURRENT_TIMESTAMP)", (wid,pid,e.date,e.weight,e.note)) return {"id":wid,"date":e.date,"weight":e.weight} @router.put("/{wid}") def update_weight(wid: str, e: WeightEntry, x_profile_id: Optional[str]=Header(default=None), session: dict=Depends(require_auth)): """Update existing weight entry.""" pid = get_pid(x_profile_id) with get_db() as conn: cur = get_cursor(conn) cur.execute("UPDATE weight_log SET date=%s,weight=%s,note=%s WHERE id=%s AND profile_id=%s", (e.date,e.weight,e.note,wid,pid)) return {"id":wid} @router.delete("/{wid}") def delete_weight(wid: str, x_profile_id: Optional[str]=Header(default=None), session: dict=Depends(require_auth)): """Delete weight entry.""" pid = get_pid(x_profile_id) with get_db() as conn: cur = get_cursor(conn) cur.execute("DELETE FROM weight_log WHERE id=%s AND profile_id=%s", (wid,pid)) return {"ok":True} @router.get("/stats") def weight_stats(x_profile_id: Optional[str]=Header(default=None), session: dict=Depends(require_auth)): """Get weight statistics (last 90 days).""" pid = get_pid(x_profile_id) with get_db() as conn: cur = get_cursor(conn) cur.execute("SELECT date,weight FROM weight_log WHERE profile_id=%s ORDER BY date DESC LIMIT 90", (pid,)) rows = cur.fetchall() if not rows: return {"count":0,"latest":None,"prev":None,"min":None,"max":None,"avg_7d":None} w=[float(r['weight']) for r in rows] return {"count":len(rows),"latest":{"date":rows[0]['date'],"weight":float(rows[0]['weight'])}, "prev":{"date":rows[1]['date'],"weight":float(rows[1]['weight'])} if len(rows)>1 else None, "min":min(w),"max":max(w),"avg_7d":round(sum(w[:7])/min(7,len(w)),2)}