import { _authorizeCalendar, _listEvents, _createEvent, _updateEvent, _deleteEvent, _isCalendarAuthorized } from "agency-lang/stdlib-lib/calendar.js"

/** @module
  Read and write Google Calendar events from Agency code. Authorizes once
  via Google OAuth, then lists, creates, updates, and deletes events.

  Set `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` (OAuth 2.0 desktop
  credentials from the Google Cloud console). The first run opens a browser
  for consent. Agency stores the tokens locally and refreshes them automatically.

  ```ts
  import { authorizeCalendar, isCalendarAuthorized, listEvents, createEvent } from "std::calendar"
  import { env } from "std::system"

  node main() {
    if (!isCalendarAuthorized()) {
      authorizeCalendar(env("GOOGLE_CLIENT_ID"), env("GOOGLE_CLIENT_SECRET"))
    }

    print(listEvents())

    createEvent(
      summary: "Team meeting",
      start: "2026-05-10T10:00:00-07:00",
      end: "2026-05-10T11:00:00-07:00"
    )
  }
  ```

  Times use ISO 8601 with a timezone (e.g. "2026-05-10T10:00:00-07:00"), or a
  date only (e.g. "2026-05-10") for all-day events. Pair with `std::date`
  helpers like `tomorrow` and `atTime` for convenient date construction.
*/

// `authorizeCalendar` wraps `std::auth/oauth`: it runs the OAuth 2.0 code flow
// with PKCE, stores tokens under ~/.agency/oauth/google-calendar.json, and
// refreshes them as needed. Agency encrypts tokens at rest when a system keyring
// or AGENCY_OAUTH_KEY is available, otherwise stores them as plaintext. For custom
// scopes/ports, call `std::auth/oauth` directly. For all-day events, `end` is
// exclusive: a single day on May 10 is start="2026-05-10", end="2026-05-11".

type CalendarEvent = {
  id: string;
  summary: string;
  description: string;
  location: string;
  start: string;
  end: string;
  htmlLink: string
}

effect std::authorizeCalendar { clientId: string }
effect std::listEvents { maxResults: number, calendarId: string, query: string }
effect std::createEvent { summary: string, start: string, end: string, description: string, location: string }
effect std::updateEvent { eventId: string, summary: string, start: string, end: string }
effect std::deleteEvent { eventId: string, calendarId: string }

export def authorizeCalendar(clientId: string, clientSecret: string): Result {
  """
  Authorize access to Google Calendar. Opens a browser for the user to sign in and grant permission. Only needs to be run once. Agency stores the tokens locally and refreshes them automatically.

  @param clientId - Google OAuth client ID
  @param clientSecret - Google OAuth client secret
  """
  return interrupt std::authorizeCalendar("Are you sure you want to authorize access to Google Calendar?", {
    clientId: clientId
  })

  return try _authorizeCalendar(clientId, clientSecret)
}

export def isCalendarAuthorized(): boolean {
  """
  Check if Google Calendar has been authorized. Returns true if OAuth tokens exist locally.
  """
  return _isCalendarAuthorized()
}

export def listEvents(maxResults: number = 10, timeMin: string = "", timeMax: string = "", query: string = "", calendarId: string = "primary"): Result {
  """
  List upcoming events from Google Calendar. Returns an array of events, each with id, summary, description, location, start, end, and htmlLink.

  @param maxResults - Maximum number of events to return
  @param timeMin - Start of time range (ISO 8601)
  @param timeMax - End of time range (ISO 8601)
  @param query - Free-text search query
  @param calendarId - Calendar ID to query
  """
  return interrupt std::listEvents("Are you sure you want to read your Google Calendar events?", {
    maxResults: maxResults,
    calendarId: calendarId,
    query: query
  })

  return try _listEvents({
    maxResults: maxResults,
    timeMin: timeMin,
    timeMax: timeMax,
    query: query,
    calendarId: calendarId
  })
}

export def createEvent(summary: string, start: string, end: string, description: string = "", location: string = "", calendarId: string = "primary"): Result {
  """
  Create a new event on Google Calendar. Returns the created event.

  @param summary - Event title
  @param start - Start time (ISO 8601 or YYYY-MM-DD)
  @param end - End time (ISO 8601 or YYYY-MM-DD)
  @param description - Event description
  @param location - Event location
  @param calendarId - Calendar ID to create on
  """
  return interrupt std::createEvent("Are you sure you want to create this calendar event?", {
    summary: summary,
    start: start,
    end: end,
    description: description,
    location: location
  })

  destructive {
    return try _createEvent({
      summary: summary,
      start: start,
      end: end,
      description: description,
      location: location,
      calendarId: calendarId
    })
  }
}

export def updateEvent(eventId: string, summary: string = "", start: string = "", end: string = "", description: string = "", location: string = "", calendarId: string = "primary"): Result {
  """
  Update an existing event on Google Calendar. Pass the eventId and any fields to change. An empty string means "don't change". Returns the updated event.

  @param eventId - ID of the event to update
  @param summary - New title (empty to keep)
  @param start - New start time (empty to keep)
  @param end - New end time (empty to keep)
  @param description - New description (empty to keep)
  @param location - New location (empty to keep)
  @param calendarId - Calendar ID
  """
  return interrupt std::updateEvent("Are you sure you want to update this calendar event?", {
    eventId: eventId,
    summary: summary,
    start: start,
    end: end
  })

  destructive {
    return try _updateEvent({
      eventId: eventId,
      summary: summary,
      start: start,
      end: end,
      description: description,
      location: location,
      calendarId: calendarId
    })
  }
}

export def deleteEvent(eventId: string, calendarId: string = "primary"): Result {
  """
  Delete an event from Google Calendar by its event ID. Returns { deleted: true } on success.

  @param eventId - ID of the event to delete
  @param calendarId - Calendar ID
  """
  return interrupt std::deleteEvent("Are you sure you want to delete this calendar event?", {
    eventId: eventId,
    calendarId: calendarId
  })

  destructive {
    return try _deleteEvent(eventId, calendarId)
  }
}
