from datetime import datetime, timedelta, timezone from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from sqlmodel import Session, select from app.core.db import get_session from app.models import GoogleAccount, AuditLog from app.google.client import get_service router = APIRouter() class CreateEventIn(BaseModel): title: str = "Reunión" minutes_from_now: int = 10 duration_minutes: int = 60 timezone: str = "America/Lima" attendees: list[str] = [] def get_account(session: Session, email: str) -> GoogleAccount: acc = session.exec(select(GoogleAccount).where(GoogleAccount.email == email)).first() if not acc: raise HTTPException(status_code=404, detail="Cuenta no autorizada. Primero usa /auth/google/start.") return acc @router.post("/events") def create_event(payload: CreateEventIn, account_email: str, session: Session = Depends(get_session)): acc = get_account(session, account_email) cal = get_service("calendar", "v3", acc.token_json) # Usamos ISO con timezone local (Google acepta timeZone separado) start_dt = datetime.now(timezone.utc) + timedelta(minutes=payload.minutes_from_now) end_dt = start_dt + timedelta(minutes=payload.duration_minutes) event = { "summary": payload.title, "start": {"dateTime": start_dt.isoformat(), "timeZone": payload.timezone}, "end": {"dateTime": end_dt.isoformat(), "timeZone": payload.timezone}, "attendees": [{"email": a} for a in payload.attendees], "conferenceData": { "createRequest": { "requestId": f"meet-{int(datetime.utcnow().timestamp())}", "conferenceSolutionKey": {"type": "hangoutsMeet"}, } } } try: created = cal.events().insert( calendarId="primary", body=event, conferenceDataVersion=1, sendUpdates="all" if payload.attendees else "none", ).execute() meet_link = created.get("hangoutLink") session.add(AuditLog(account_email=account_email, action="calendar_create_event", detail=f"meet={meet_link}")) session.commit() return { "status": "created", "eventId": created.get("id"), "htmlLink": created.get("htmlLink"), "meetLink": meet_link, } except Exception as e: raise HTTPException(status_code=400, detail=str(e))