// Google Calendar OAuth wrapper
import { google } from 'googleapis';

export interface GoogleCalendarEvent {
  id: string;
  summary: string;
  description?: string;
  start: {
    dateTime?: string;
    date?: string;
  };
  end: {
    dateTime?: string;
    date?: string;
  };
  attendees?: Array<{
    email: string;
    displayName?: string;
    responseStatus?: string;
  }>;
  location?: string;
  colorId?: string;
  reminders?: {
    useDefault: boolean;
    overrides?: Array<{ method: string; minutes: number }>;
  };
  transparency?: string; // 'opaque' | 'transparent'
  visibility?: string; // 'default' | 'public' | 'private' | 'confidential'
}

export interface GoogleCalendar {
  id: string;
  summary: string;
  primary?: boolean;
  backgroundColor?: string;
}

/**
 * Initialize Google Calendar OAuth client
 */
export const initializeOAuth = (clientId: string, clientSecret: string, redirectUri: string) => {
  const oauth2Client = new google.auth.OAuth2(
    clientId,
    clientSecret,
    redirectUri
  );

  return oauth2Client;
};

/**
 * Get user calendar list using OAuth token
 */
export const getUserCalendars = async (
  oauth2Client: any,
  accessToken: string
): Promise<GoogleCalendar[]> => {
  // Set access token
  oauth2Client.setCredentials({ access_token: accessToken });

  try {
    const calendar = google.calendar({ version: 'v3', auth: oauth2Client });
    const response = await calendar.calendarList.list();

    return response.data.items?.map((item: any) => ({
      id: item.id,
      summary: item.summary,
      primary: item.primary,
      backgroundColor: item.backgroundColor,
    })) || [];
  } catch (error) {
    console.error('Error fetching user calendars:', error);
    throw new Error('Failed to fetch user calendars');
  }
};

/**
 * Get upcoming events for a specified time period
 */
export const getUpcomingEvents = async (
  oauth2Client: any,
  accessToken: string,
  calendarId: string,
  timeMin: string,
  timeMax: string
): Promise<GoogleCalendarEvent[]> => {
  // Set access token
  oauth2Client.setCredentials({ access_token: accessToken });

  try {
    const calendar = google.calendar({ version: 'v3', auth: oauth2Client });
    const response = await calendar.events.list({
      calendarId,
      timeMin,
      timeMax,
      singleEvents: true,
      orderBy: 'startTime',
    });

    return response.data.items?.map((item: any) => ({
      id: item.id,
      summary: item.summary,
      description: item.description,
      start: item.start,
      end: item.end,
      attendees: item.attendees?.map((a: any) => ({
        email: a.email,
        displayName: a.displayName,
        responseStatus: a.responseStatus,
      })),
      location: item.location,
      colorId: item.colorId,
      reminders: item.reminders,
      transparency: item.transparency,
      visibility: item.visibility,
    })) || [];
  } catch (error) {
    console.error('Error fetching upcoming events:', error);
    throw new Error('Failed to fetch upcoming events');
  }
};

/**
 * Create a new event
 */
export const createEvent = async (
  oauth2Client: any,
  accessToken: string,
  calendarId: string,
  event: Partial<GoogleCalendarEvent>
): Promise<GoogleCalendarEvent> => {
  oauth2Client.setCredentials({ access_token: accessToken });
  try {
    const calendar = google.calendar({ version: 'v3', auth: oauth2Client });
    const requestBody: any = {
        summary: event.summary,
        description: event.description,
        start: event.start,
        end: event.end,
        location: event.location,
    };
    if ((event as any).recurrence) requestBody.recurrence = (event as any).recurrence;
    if ((event as any).source) requestBody.source = (event as any).source;
    if (event.reminders) requestBody.reminders = event.reminders;
    if (event.transparency) requestBody.transparency = event.transparency;
    if (event.visibility) requestBody.visibility = event.visibility;
    if (event.attendees) requestBody.attendees = event.attendees;
    const response = await calendar.events.insert({
      calendarId,
      requestBody,
    });
    return response.data as any;
  } catch (error) {
    console.error('Error creating event:', error);
    throw new Error('Failed to create event');
  }
};

/**
 * Update an existing event
 */
export const updateEvent = async (
  oauth2Client: any,
  accessToken: string,
  calendarId: string,
  eventId: string,
  event: Partial<GoogleCalendarEvent>
): Promise<GoogleCalendarEvent> => {
  oauth2Client.setCredentials({ access_token: accessToken });
  try {
    const calendar = google.calendar({ version: 'v3', auth: oauth2Client });
    const requestBody: any = {
        summary: event.summary,
        description: event.description,
        start: event.start,
        end: event.end,
        location: event.location,
    };
    if ((event as any).recurrence) requestBody.recurrence = (event as any).recurrence;
    if ((event as any).source) requestBody.source = (event as any).source;
    if (event.reminders) requestBody.reminders = event.reminders;
    if (event.transparency) requestBody.transparency = event.transparency;
    if (event.visibility) requestBody.visibility = event.visibility;
    if (event.attendees) requestBody.attendees = event.attendees;
    const response = await calendar.events.patch({
      calendarId,
      eventId,
      requestBody,
    });
    return response.data as any;
  } catch (error) {
    console.error('Error updating event:', error);
    throw new Error('Failed to update event');
  }
};

/**
 * Delete an event
 */
export const deleteEvent = async (
  oauth2Client: any,
  accessToken: string,
  calendarId: string,
  eventId: string
): Promise<void> => {
  oauth2Client.setCredentials({ access_token: accessToken });
  try {
    const calendar = google.calendar({ version: 'v3', auth: oauth2Client });
    await calendar.events.delete({
      calendarId,
      eventId,
    });
  } catch (error) {
    console.error('Error deleting event:', error);
    throw new Error('Failed to delete event');
  }
};