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, datetime from app.core.database import get_db from app.core.security import decode_access_token from app.models.user import User from app.models.habit import Habit, HabitCompletion from app.schemas.habit import HabitCreate, HabitResponse, HabitCompletionCreate router = APIRouter(prefix="/habits", tags=["habits"]) 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=HabitResponse, status_code=status.HTTP_201_CREATED) async def create_habit( habit_data: HabitCreate, user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Criar novo hábito""" new_habit = Habit( user_id=user_id, name=habit_data.name, description=habit_data.description, frequency_type=habit_data.frequency_type, target_count=habit_data.target_count, reminder_time=habit_data.reminder_time, start_date=habit_data.start_date or date.today() ) db.add(new_habit) db.commit() db.refresh(new_habit) return new_habit @router.get("/", response_model=List[HabitResponse]) async def list_habits( user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Listar todos os hábitos do usuário""" habits = db.query(Habit).filter( Habit.user_id == user_id, Habit.is_active == True ).all() return habits @router.post("/{habit_id}/complete", status_code=status.HTTP_201_CREATED) async def complete_habit( habit_id: str, user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Marcar hábito como completo para hoje""" # Verificar se já completou hoje today = date.today() existing = db.query(HabitCompletion).filter( HabitCompletion.habit_id == habit_id, HabitCompletion.user_id == user_id, HabitCompletion.completion_date == today ).first() if existing: raise HTTPException(status_code=400, detail="Hábito já completado hoje") # Criar completion completion = HabitCompletion( habit_id=habit_id, user_id=user_id, completion_date=today, completion_time=datetime.now().time() ) db.add(completion) db.commit() return {"message": "Hábito completado!", "date": today} @router.delete("/{habit_id}/complete") async def uncomplete_habit( habit_id: str, user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Desmarcar hábito de hoje""" today = date.today() completion = db.query(HabitCompletion).filter( HabitCompletion.habit_id == habit_id, HabitCompletion.user_id == user_id, HabitCompletion.completion_date == today ).first() if not completion: raise HTTPException(status_code=404, detail="Completion não encontrado") db.delete(completion) db.commit() return {"message": "Completion removido"} @router.get("/stats") async def get_habit_stats( user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Estatísticas de hábitos""" from sqlalchemy import func total_habits = db.query(func.count(Habit.id)).filter( Habit.user_id == user_id, Habit.is_active == True ).scalar() completed_today = db.query(func.count(HabitCompletion.id)).filter( HabitCompletion.user_id == user_id, HabitCompletion.completion_date == date.today() ).scalar() return { "total_habits": total_habits, "completed_today": completed_today, "pending_today": total_habits - completed_today } @router.delete("/{habit_id}") async def delete_habit( habit_id: str, user_id: str = Depends(get_current_user_id), db: Session = Depends(get_db) ): """Deletar hábito""" habit = db.query(Habit).filter( Habit.id == habit_id, Habit.user_id == user_id ).first() if not habit: raise HTTPException(status_code=404, detail="Hábito não encontrado") db.delete(habit) db.commit() return {"message": "Hábito deletado"}