/**
 * CalendarSyncProvider interface — calendar-module.
 *
 * Provider-neutral contract implemented by GoogleCalendarProvider and
 * OutlookCalendarProvider. All token manipulation is done outside (the caller
 * is responsible for refreshing before calling these methods).
 */
import type { CalendarProvider } from './types'

export interface ExternalEvent {
  externalId: string
  externalCalendarId: string
  title: string
  description: string | null
  startAt: string
  endAt: string
  allDay: boolean
  location: string | null
}

export interface CalendarListItem {
  id: string
  name: string
  isPrimary: boolean
}

export interface TokenRefreshResult {
  accessToken: string
  expiresAt: string // ISO string
}

/**
 * Provider-neutral calendar sync interface.
 * Implementations: GoogleCalendarProvider, OutlookCalendarProvider.
 */
export interface CalendarSyncProvider {
  readonly provider: CalendarProvider

  /** Exchange a refresh token for a new access token */
  refreshAccessToken(refreshToken: string): Promise<TokenRefreshResult>

  /** List all calendars visible to the authenticated user */
  listCalendars(accessToken: string): Promise<CalendarListItem[]>

  /** Push a new event to the provider calendar; returns the provider event id */
  pushEvent(
    accessToken: string,
    calendarId: string,
    ev: Omit<ExternalEvent, 'externalId' | 'externalCalendarId'>,
  ): Promise<{ externalId: string }>

  /** Update an existing event in the provider calendar */
  updateEvent(
    accessToken: string,
    calendarId: string,
    externalId: string,
    ev: Omit<ExternalEvent, 'externalId' | 'externalCalendarId'>,
  ): Promise<void>

  /** Delete an event in the provider calendar */
  deleteEvent(
    accessToken: string,
    calendarId: string,
    externalId: string,
  ): Promise<void>

  /** Fetch changed events since a sync token / timestamp; null = full sync */
  fetchChanges(
    accessToken: string,
    calendarId: string,
    since: string | null,
  ): Promise<ExternalEvent[]>

  /**
   * Register a push-notification watch channel (Google) or subscription (Outlook).
   * Optional — providers that don't support it omit implementation.
   */
  registerWatch?(
    accessToken: string,
    calendarId: string,
    callbackUrl: string,
    metadata?: Record<string, string>,
  ): Promise<{ channelId?: string; resourceId?: string }>
}
