// @ts-nocheck
/* eslint-disable @typescript-eslint/no-explicit-any */
// import { GoogleCalendarEvent as CalendarEvent } from './google-calendar';

export interface OutlookCalendar {
    id: string;
    name: string;
    isDefaultCalendar: boolean;
    canEdit: boolean;
    owner: {
        name: string;
        address: string;
    };
}

const GRAPH_ENDPOINT = 'https://graph.microsoft.com/v1.0';
const REDIRECT_URI = process.env.MICROSOFT_REDIRECT_URI || `${process.env.NEXTAUTH_URL}/api/calendar/outlook/callback`;

/**
 * Generate OAuth2 Authorization URL
 */
export const getAuthUrl = () => {
    const tenant = 'common';
    const clientId = process.env.MICROSOFT_CLIENT_ID;

    if (!clientId) throw new Error('MICROSOFT_CLIENT_ID is not defined');

    const scopes = [
        'offline_access',
        'user.read',
        'Calendars.ReadWrite',
        'Tasks.ReadWrite'
    ].join(' ');

    const params = new URLSearchParams({
        client_id: clientId,
        response_type: 'code',
        redirect_uri: REDIRECT_URI,
        response_mode: 'query',
        scope: scopes,
        state: 'outlook-auth' // Can be random for security
    });

    return `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/authorize?${params.toString()}`;
};

/**
 * Exchange Authorization Code for Tokens
 */
export const getTokens = async (code: string) => {
    const tenant = 'common';
    const clientId = process.env.MICROSOFT_CLIENT_ID;
    const clientSecret = process.env.MICROSOFT_CLIENT_SECRET;

    if (!clientId || !clientSecret) throw new Error('Microsoft credentials not defined');

    const params = new URLSearchParams({
        client_id: clientId,
        scope: 'offline_access user.read Calendars.ReadWrite Tasks.ReadWrite',
        code: code,
        redirect_uri: REDIRECT_URI,
        grant_type: 'authorization_code',
        client_secret: clientSecret
    });

    const response = await fetch(`https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: params.toString()
    });

    if (!response.ok) {
        const error = await response.text();
        console.error('Error getting Outlook tokens:', error);
        throw new Error(`Failed to get tokens: ${response.statusText}`);
    }

    return response.json();
};

/**
 * Refresh Access Token
 */
export const refreshAccessToken = async (refreshToken: string) => {
    const tenant = 'common';
    const clientId = process.env.MICROSOFT_CLIENT_ID;
    const clientSecret = process.env.MICROSOFT_CLIENT_SECRET;

    if (!clientId || !clientSecret) throw new Error('Microsoft credentials not defined');

    const params = new URLSearchParams({
        client_id: clientId,
        scope: 'offline_access user.read Calendars.ReadWrite Tasks.ReadWrite',
        refresh_token: refreshToken,
        redirect_uri: REDIRECT_URI,
        grant_type: 'refresh_token',
        client_secret: clientSecret
    });

    const response = await fetch(`https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: params.toString()
    });

    if (!response.ok) {
        const error = await response.text();
        console.error('Error refreshing Outlook token:', error);
        throw new Error(`Failed to refresh token: ${response.statusText}`);
    }

    return response.json();
};

/**
 * Get User's Calendars
 */
export const getUserCalendars = async (accessToken: string): Promise<OutlookCalendar[]> => {
    const response = await fetch(`${GRAPH_ENDPOINT}/me/calendars`, {
        headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Prefer': 'outlook.timezone="UTC"'
        }
    });

    if (!response.ok) {
        throw new Error(`Failed to fetch calendars: ${response.statusText}`);
    }

    const data = await response.json();
    return data.value;
};

/**
 * Get Upcoming Events
 */
export const getUpcomingEvents = async (
    accessToken: string,
    calendarId: string,
    startDateTime: string,
    endDateTime: string
) => {
    const params = new URLSearchParams({
        startDateTime: startDateTime,
        endDateTime: endDateTime,
        '$select': 'subject,bodyPreview,start,end,location,webLink,isAllDay,seriesMasterId,type,reminderMinutesBeforeStart,isReminderOn,showAs,sensitivity,attendees',
        '$orderby': 'start/dateTime',
        '$top': '50'
    });

    const response = await fetch(
        `${GRAPH_ENDPOINT}/me/calendars/${encodeURIComponent(calendarId)}/calendarView?${params.toString()}`,
        {
            headers: {
                'Authorization': `Bearer ${accessToken}`,
                'Prefer': 'outlook.timezone="UTC"'
            }
        }
    );

    if (!response.ok) {
        const errorText = await response.text();
        console.error(`[OUTLOOK] Failed to fetch events for calendar ${calendarId}:`, response.status, response.statusText, errorText);
        throw new Error(`Failed to fetch events: ${response.status} ${response.statusText}`);
    }

    const data = await response.json();
    return data.value.map((event: any) => {
        // Map Outlook showAs to our busyStatus
        const showAsMap: Record<string, string> = {
            'free': 'free', 'tentative': 'tentative', 'busy': 'busy',
            'oof': 'oof', 'workingElsewhere': 'workingElsewhere',
        };
        // Map Outlook sensitivity to our visibility
        const sensitivityMap: Record<string, string> = {
            'normal': 'default', 'personal': 'default', 'private': 'private', 'confidential': 'confidential',
        };

        return {
            id: event.seriesMasterId ? `${event.seriesMasterId}::${event.id}` : event.id,
            summary: event.subject,
            description: event.body?.content || event.bodyPreview,
            start: {
                dateTime: event.start.dateTime,
                timeZone: event.start.timeZone
            },
            end: {
                dateTime: event.end.dateTime,
                timeZone: event.end.timeZone
            },
            location: event.location?.displayName,
            htmlLink: event.webLink,
            allDay: event.isAllDay,
            reminders: event.isReminderOn && event.reminderMinutesBeforeStart != null
                ? [{ method: 'popup', minutes: event.reminderMinutesBeforeStart }]
                : undefined,
            busyStatus: showAsMap[event.showAs] || undefined,
            visibility: sensitivityMap[event.sensitivity] || undefined,
            attendees: event.attendees?.map((a: any) => ({
                email: a.emailAddress?.address,
                displayName: a.emailAddress?.name,
                responseStatus: a.status?.response === 'accepted' ? 'accepted'
                    : a.status?.response === 'declined' ? 'declined'
                    : a.status?.response === 'tentativelyAccepted' ? 'tentative'
                    : 'needsAction',
            })),
        };
    });
};

const ensureTimeZone = (dateTimeObj: any) => {
    if (!dateTimeObj) return dateTimeObj;
    return {
        dateTime: dateTimeObj.dateTime,
        timeZone: dateTimeObj.timeZone || 'UTC'
    };
};

/**
 * Create Outlook Event
 */
export const createEvent = async (
    accessToken: string,
    calendarId: string,
    event: any
) => {
    const response = await fetch(`${GRAPH_ENDPOINT}/me/calendars/${encodeURIComponent(calendarId)}/events`, {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            subject: event.summary,
            body: {
                contentType: 'HTML',
                content: event.description || ''
            },
            start: ensureTimeZone(event.start),
            end: ensureTimeZone(event.end),
            isAllDay: !!event.allDay,
            location: {
                displayName: event.location || ''
            },
            ...(event.recurrence ? { recurrence: event.recurrence } : {}),
            ...(event.reminders?.length ? {
                isReminderOn: true,
                reminderMinutesBeforeStart: event.reminders[0].minutes,
            } : {}),
            ...(event.busyStatus ? { showAs: event.busyStatus === 'oof' ? 'oof' : event.busyStatus } : {}),
            ...(event.visibility ? {
                sensitivity: event.visibility === 'private' ? 'private'
                    : event.visibility === 'confidential' ? 'confidential'
                    : 'normal'
            } : {}),
            ...(event.attendees?.length ? {
                attendees: event.attendees.map((a: any) => ({
                    emailAddress: { address: a.email, name: a.displayName || a.email },
                    type: 'required',
                })),
            } : {}),
        })
    });

    if (!response.ok) {
        const err = await response.text();
        throw new Error(`Failed to create Outlook event: ${err}`);
    }

    const created = await response.json();
    return {
        id: created.id,
        summary: created.subject,
        description: created.bodyPreview,
        start: created.start,
        end: created.end,
        location: created.location?.displayName,
        allDay: created.isAllDay
    };
};

/**
 * Update Outlook Event
 */
export const updateEvent = async (
    accessToken: string,
    calendarId: string, // Not strictly needed for Graph ID-based update but kept for interface consistency
    eventId: string,
    event: any
) => {
    const response = await fetch(`${GRAPH_ENDPOINT}/me/events/${encodeURIComponent(eventId)}`, {
        method: 'PATCH',
        headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            subject: event.summary,
            body: {
                contentType: 'HTML',
                content: event.description || ''
            },
            start: ensureTimeZone(event.start),
            end: ensureTimeZone(event.end),
            isAllDay: event.allDay !== undefined ? !!event.allDay : undefined,
            location: {
                displayName: event.location || ''
            },
            ...(event.recurrence ? { recurrence: event.recurrence } : {}),
            ...(event.reminders?.length ? {
                isReminderOn: true,
                reminderMinutesBeforeStart: event.reminders[0].minutes,
            } : {}),
            ...(event.busyStatus ? { showAs: event.busyStatus === 'oof' ? 'oof' : event.busyStatus } : {}),
            ...(event.visibility ? {
                sensitivity: event.visibility === 'private' ? 'private'
                    : event.visibility === 'confidential' ? 'confidential'
                    : 'normal'
            } : {}),
            ...(event.attendees?.length ? {
                attendees: event.attendees.map((a: any) => ({
                    emailAddress: { address: a.email, name: a.displayName || a.email },
                    type: 'required',
                })),
            } : {}),
        })
    });

    if (!response.ok) {
        const err = await response.text();
        throw new Error(`Failed to update Outlook event: ${err}`);
    }

    const updated = await response.json();
    return {
        id: updated.id,
        summary: updated.subject,
        description: updated.bodyPreview,
        start: updated.start,
        end: updated.end,
        location: updated.location?.displayName,
        allDay: updated.isAllDay
    };
};

/**
 * Delete Outlook Event
 */
export const deleteEvent = async (
    accessToken: string,
    calendarId: string,
    eventId: string
) => {
    const response = await fetch(`${GRAPH_ENDPOINT}/me/events/${encodeURIComponent(eventId)}`, {
        method: 'DELETE',
        headers: {
            'Authorization': `Bearer ${accessToken}`
        }
    });

    if (!response.ok) {
        const err = await response.text();
        throw new Error(`Failed to delete Outlook event: ${err}`);
    }
};
