from datetime import datetime, timezone from typing import Any from zoneinfo import ZoneInfo from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel, Field from sqlalchemy.orm import Session from app.auth.deps import get_current_user from app.db.base import get_db from app.db.models import User from app.homelab.context import resolve_timezone from app.reminders_scoped.service import RemindersService router = APIRouter() class ReminderCreate(BaseModel): title: str = Field(min_length=1, max_length=255) due_at: str = Field(description="ISO datetime, например 2027-05-12T12:16:00") notes: str = "" all_day: bool = False recurrence: str = "none" class ReminderUpdate(BaseModel): title: str | None = Field(default=None, min_length=1, max_length=255) due_at: str | None = None notes: str | None = None all_day: bool | None = None recurrence: str | None = None enabled: bool | None = None @router.get("") def get_snapshot(db: Session = Depends(get_db), user: User = Depends(get_current_user)) -> dict[str, Any]: return RemindersService(db, user.id).snapshot() @router.get("/upcoming") def list_upcoming( limit: int = Query(30, ge=1, le=100), db: Session = Depends(get_db), user: User = Depends(get_current_user), ) -> list[dict[str, Any]]: return RemindersService(db, user.id).list_upcoming(limit=limit) @router.get("/calendar") def calendar( year: int = Query(..., ge=2000, le=2100), month: int = Query(..., ge=1, le=12), db: Session = Depends(get_db), user: User = Depends(get_current_user), ) -> dict[str, Any]: tz_name = resolve_timezone(db, user.id) try: tz = ZoneInfo(tz_name) except Exception: tz = ZoneInfo("Europe/Moscow") start = datetime(year, month, 1, tzinfo=tz) if month == 12: end = datetime(year + 1, 1, 1, tzinfo=tz) else: end = datetime(year, month + 1, 1, tzinfo=tz) service = RemindersService(db, user.id) items = service.list_in_range( date_from=start.astimezone(timezone.utc), date_to=end.astimezone(timezone.utc), ) return { "year": year, "month": month, "timezone": tz_name, "reminders": items, } @router.post("") def create_reminder(payload: ReminderCreate, db: Session = Depends(get_db), user: User = Depends(get_current_user)) -> dict[str, Any]: try: return RemindersService(db, user.id).create( title=payload.title, due_at=payload.due_at, notes=payload.notes, all_day=payload.all_day, recurrence=payload.recurrence, ) except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc @router.patch("/{reminder_id}") def update_reminder( reminder_id: int, payload: ReminderUpdate, db: Session = Depends(get_db), user: User = Depends(get_current_user), ) -> dict[str, Any]: try: return RemindersService(db, user.id).update( reminder_id, title=payload.title, due_at=payload.due_at, notes=payload.notes, all_day=payload.all_day, recurrence=payload.recurrence, enabled=payload.enabled, ) except ValueError as exc: raise HTTPException(status_code=404, detail=str(exc)) from exc @router.delete("/{reminder_id}") def delete_reminder(reminder_id: int, db: Session = Depends(get_db), user: User = Depends(get_current_user)) -> dict[str, Any]: try: return RemindersService(db, user.id).delete(reminder_id) except ValueError as exc: raise HTTPException(status_code=404, detail=str(exc)) from exc @router.post("/{reminder_id}/complete") def complete_reminder(reminder_id: int, db: Session = Depends(get_db), user: User = Depends(get_current_user)) -> dict[str, Any]: try: return RemindersService(db, user.id).complete(reminder_id) except ValueError as exc: raise HTTPException(status_code=404, detail=str(exc)) from exc