import { google } from 'googleapis';
import { OAuth2Client } from 'google-auth-library';

export interface GoogleTaskList {
    id: string;
    title: string;
    updated: string;
}

export interface GoogleTask {
    id: string;
    title: string;
    notes?: string;
    status: string;
    due?: string;
    updated: string;
    parent?: string;
}

/**
 * Create an authenticated Google OAuth2 client
 */
export const createGoogleClient = (accessToken: string, refreshToken?: string): OAuth2Client => {
    const clientId = process.env.GOOGLE_CLIENT_ID;
    const clientSecret = process.env.GOOGLE_CLIENT_SECRET;
    const redirectUri = process.env.GOOGLE_REDIRECT_URI || `${process.env.NEXTAUTH_URL}/api/calendar/google/oauth`;

    const oauth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUri);
    oauth2Client.setCredentials({
        access_token: accessToken,
        refresh_token: refreshToken
    });

    return oauth2Client;
};

/**
 * Create a new task list
 */
export const createGoogleTaskList = async (client: OAuth2Client, title: string): Promise<GoogleTaskList> => {
    const service = google.tasks({ version: 'v1', auth: client });
    try {
        const response = await service.tasklists.insert({
            requestBody: { title }
        });
        const item = response.data;
        return {
            id: item.id!,
            title: item.title!,
            updated: item.updated!
        };
    } catch (error) {
        console.error('Error creating Google task list:', error);
        throw error;
    }
};

/**
 * Fetch all task lists for the user
 */
export const fetchGoogleTaskLists = async (client: OAuth2Client): Promise<GoogleTaskList[]> => {
    const service = google.tasks({ version: 'v1', auth: client });
    try {
        const response = await service.tasklists.list();
        return (response.data.items || []).map(item => ({
            id: item.id!,
            title: item.title!,
            updated: item.updated!
        }));
    } catch (error) {
        console.error('Error fetching Google Task lists:', error);
        throw error;
    }
};

/**
 * Fetch tasks from a specific task list
 */
export const fetchGoogleTasks = async (client: OAuth2Client, taskListId: string): Promise<GoogleTask[]> => {
    const service = google.tasks({ version: 'v1', auth: client });
    try {
        const response = await service.tasks.list({
            tasklist: taskListId,
            showCompleted: false, // We usually only want active tasks for import
            showHidden: false
        });

        return (response.data.items || []).map(item => ({
            id: item.id!,
            title: item.title!,
            notes: item.notes || undefined,
            status: item.status!,
            due: item.due || undefined,
            updated: item.updated!,
            parent: (item as any).parent || undefined,
        }));
    } catch (error) {
        console.error(`Error fetching Google Tasks from list ${taskListId}:`, error);
        throw error;
    }
};
/**
 * Update a Google Task status
 */
export const updateGoogleTask = async (client: OAuth2Client, taskListId: string, taskId: string, updates: { title?: string; notes?: string; status?: 'needsAction' | 'completed'; due?: string | null }): Promise<GoogleTask> => {
    const service = google.tasks({ version: 'v1', auth: client });
    try {
        const requestBody: any = {};
        if (updates.title !== undefined) requestBody.title = updates.title;
        if (updates.notes !== undefined) requestBody.notes = updates.notes;
        if (updates.due !== undefined) requestBody.due = updates.due;
        if (updates.status !== undefined) {
            requestBody.status = updates.status;
            requestBody.completed = updates.status === 'completed' ? new Date().toISOString() : null;
        }
        const response = await service.tasks.patch({
            tasklist: taskListId,
            task: taskId,
            requestBody,
        });
        const item = response.data;
        return {
            id: item.id!,
            title: item.title!,
            notes: item.notes || undefined,
            status: item.status!,
            due: item.due || undefined,
            updated: item.updated!,
            parent: (item as any).parent || undefined,
        };
    } catch (error) {
        console.error(`Error updating Google Task ${taskId}:`, error);
        throw error;
    }
};

export const deleteGoogleTask = async (client: OAuth2Client, taskListId: string, taskId: string): Promise<void> => {
    const service = google.tasks({ version: 'v1', auth: client });
    try {
        await service.tasks.delete({
            tasklist: taskListId,
            task: taskId,
        });
    } catch (error) {
        console.error(`Error deleting Google Task ${taskId}:`, error);
        throw error;
    }
};

/**
 * Fetch tasks from a specific list including completed ones (for sync)
 */
export const fetchGoogleTasksForSync = async (client: OAuth2Client, taskListId: string, updatedMin?: string): Promise<GoogleTask[]> => {
    const service = google.tasks({ version: 'v1', auth: client });
    try {
        const params: any = {
            tasklist: taskListId,
            showCompleted: true,
            showHidden: true,
            maxResults: 100,
        };
        if (updatedMin) {
            params.updatedMin = updatedMin;
        }

        const response = await service.tasks.list(params);

        return (response.data.items || []).map(item => ({
            id: item.id!,
            title: item.title!,
            notes: item.notes || undefined,
            status: item.status!,
            due: item.due || undefined,
            updated: item.updated!,
            parent: (item as any).parent || undefined,
        }));
    } catch (error: any) {
        // On quota exceeded (429), return empty array instead of crashing
        if (error?.code === 429 || error?.status === 429) {
            console.warn(`Google Tasks API quota exceeded for list ${taskListId}, skipping sync cycle`);
            return [];
        }
        console.error(`Error fetching Google Tasks for sync from list ${taskListId}:`, error);
        throw error;
    }
};

/**
 * Create a new task in a task list
 */
export const createGoogleTask = async (
    client: OAuth2Client,
    taskListId: string,
    taskData: { title: string; notes?: string; due?: string }
): Promise<GoogleTask> => {
    const service = google.tasks({ version: 'v1', auth: client });
    try {
        const requestBody: any = { title: taskData.title };
        if (taskData.notes) requestBody.notes = taskData.notes;
        if (taskData.due) requestBody.due = taskData.due;

        const response = await service.tasks.insert({
            tasklist: taskListId,
            requestBody,
        });
        const item = response.data;
        return {
            id: item.id!,
            title: item.title!,
            notes: item.notes || undefined,
            status: item.status!,
            due: item.due || undefined,
            updated: item.updated!,
            parent: (item as any).parent || undefined,
        };
    } catch (error) {
        console.error('Error creating Google Task:', error);
        throw error;
    }
};

export const updateGoogleTaskStatus = async (client: OAuth2Client, taskListId: string, taskId: string, status: 'needsAction' | 'completed'): Promise<GoogleTask> => {
    const service = google.tasks({ version: 'v1', auth: client });
    try {
        const response = await service.tasks.patch({
            tasklist: taskListId,
            task: taskId,
            requestBody: {
                status: status,
                completed: status === 'completed' ? new Date().toISOString() : null
            }
        });

        const item = response.data;
        return {
            id: item.id!,
            title: item.title!,
            notes: item.notes || undefined,
            status: item.status!,
            due: item.due || undefined,
            updated: item.updated!,
            parent: (item as any).parent || undefined,
        };
    } catch (error) {
        console.error(`Error updating Google Task ${taskId} in list ${taskListId}:`, error);
        throw error;
    }
};
