import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from "@/lib/auth";
import { prisma } from '@/lib/prisma';
import { createCalendarEvent, updateCalendarEvent, deleteCalendarEvent, CalendarConnection } from '@/lib/calendar-events';
import { upsertCachedEvent, deleteCachedEvent } from '@/lib/calendar-cache';

// Helper to find connection by calendarId (look up by email to avoid stale session IDs)
async function findConnectionForCalendar(email: string, calendarId: string) {
    const user = await prisma.user.findUnique({
        where: { email },
        include: { calendarConnections: true }
    });

    if (!user) return null;

    for (const conn of user.calendarConnections) {
        if (conn.calendars && Array.isArray(conn.calendars)) {
            const calendars = conn.calendars as any[];
            if (calendars.some(c => c.id === calendarId)) {
                return {
                    id: conn.id,
                    provider: conn.provider as 'google' | 'apple' | 'outlook',
                    accessToken: conn.accessToken,
                    refreshToken: conn.refreshToken || undefined,
                    expiresAt: conn.expiresAt || undefined,
                    calendars: conn.calendars
                } as CalendarConnection;
            }
        }
    }
    return null;
}

// POST - Create event
export async function POST(request: NextRequest) {
    try {
        const session = await getServerSession(authOptions);
        if (!session?.user?.email) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });

        const body = await request.json();
        const { calendarId, title, description, start, end, location, allDay, recurrence, recurrenceEndDate, recurrenceCount, recurrenceInterval, recurrenceDays, url,
                reminders, busyStatus, visibility, attendees, attachments, timezone } = body;

        console.log('[API] Creating event:', { calendarId, title, start, end });

        if (!calendarId || !title || !start || !end) {
            return NextResponse.json({ error: 'Missing required fields' }, { status: 400 });
        }

        const connection = await findConnectionForCalendar(session.user.email, calendarId);

        if (!connection) {
            return NextResponse.json({ error: 'Calendar connection not found' }, { status: 404 });
        }

        // Resolve real DB user ID for cache operations
        const dbUser = await prisma.user.findUnique({ where: { email: session.user.email }, select: { id: true } });
        const userId = dbUser?.id;
        if (!userId) return NextResponse.json({ error: 'User not found' }, { status: 404 });

        const event = await createCalendarEvent(connection, calendarId, {
            title,
            description,
            start,
            end,
            location,
            allDay: !!allDay,
            recurrence,
            recurrenceEndDate,
            recurrenceCount,
            recurrenceInterval,
            recurrenceDays,
            timezone,
            url,
            reminders,
            busyStatus,
            visibility,
            attendees,
            attachments,
        } as any);

        // Attach calendar color from connection metadata for cache + frontend
        if (!event.backgroundColor && connection.calendars) {
            const cal = (connection.calendars as any[]).find((c: any) => c.id === calendarId);
            if (cal?.backgroundColor || cal?.color) {
                event.backgroundColor = cal.backgroundColor || cal.color;
            }
        }

        // Update cache - await to ensure it's ready before client refreshes
        try {
            await upsertCachedEvent(userId, connection.id, connection.provider, event);
        } catch (e) {
            console.error('[CACHE] Failed to cache created event:', e);
        }

        return NextResponse.json({ event });
    } catch (error: any) {
        console.error('Error creating event:', error);
        return NextResponse.json({ error: error.message || 'Failed to create event' }, { status: 500 });
    }
}

// PATCH - Update event
export async function PATCH(request: NextRequest) {
    try {
        const session = await getServerSession(authOptions);
        if (!session?.user?.email) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });

        const body = await request.json();
        const { calendarId, eventId, title, description, start, end, location, allDay, recurrence, recurrenceEndDate, recurrenceCount, recurrenceInterval, recurrenceDays, url,
                reminders, busyStatus, visibility, attendees, attachments, editMode, recurringEventId } = body;

        console.log('[API] Updating event:', { calendarId, eventId, title, editMode });

        if (!calendarId || !eventId) {
            return NextResponse.json({ error: 'Missing required fields' }, { status: 400 });
        }

        const connection = await findConnectionForCalendar(session.user.email, calendarId);

        if (!connection) {
            return NextResponse.json({ error: 'Calendar connection not found' }, { status: 404 });
        }

        const dbUser2 = await prisma.user.findUnique({ where: { email: session.user.email }, select: { id: true } });
        const userId = dbUser2?.id;
        if (!userId) return NextResponse.json({ error: 'User not found' }, { status: 404 });

        // For "all events" edit mode on recurring events, use the series master ID
        let targetEventId = eventId;
        if (editMode === 'all' && recurringEventId) {
            // For Outlook composite IDs (seriesMasterId::instanceId), use just the seriesMasterId
            if (recurringEventId.includes('::')) {
                targetEventId = recurringEventId.split('::')[0];
            } else {
                targetEventId = recurringEventId;
            }
        }

        const event = await updateCalendarEvent(connection, calendarId, targetEventId, {
            title,
            description,
            start,
            end,
            location,
            allDay: allDay !== undefined ? !!allDay : undefined,
            recurrence,
            recurrenceEndDate,
            recurrenceCount,
            recurrenceInterval,
            recurrenceDays,
            url,
            reminders,
            busyStatus,
            visibility,
            attendees,
            attachments,
        } as any);

        // Attach calendar color from connection metadata for cache + frontend
        if (!event.backgroundColor && connection.calendars) {
            const cal = (connection.calendars as any[]).find((c: any) => c.id === calendarId);
            if (cal?.backgroundColor || cal?.color) {
                event.backgroundColor = cal.backgroundColor || cal.color;
            }
        }

        // Update cache - await to ensure it's ready before client refreshes
        try {
            await upsertCachedEvent(userId, connection.id, connection.provider, event);
        } catch (e) {
            console.error('[CACHE] Failed to cache updated event:', e);
        }

        return NextResponse.json({ event });
    } catch (error: any) {
        console.error('Error updating event:', error);
        return NextResponse.json({ error: error.message || 'Failed to update event' }, { status: 500 });
    }
}

// DELETE - Delete event
export async function DELETE(request: NextRequest) {
    try {
        const session = await getServerSession(authOptions);
        if (!session?.user?.email) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });

        const { searchParams } = new URL(request.url);
        const calendarId = searchParams.get('calendarId');
        const eventId = searchParams.get('eventId');
        const deleteMode = searchParams.get('deleteMode') || 'all';

        console.log('[API] Deleting event:', { calendarId, eventId, deleteMode });

        if (!calendarId || !eventId) {
            return NextResponse.json({ error: 'Missing required fields' }, { status: 400 });
        }

        const connection = await findConnectionForCalendar(session.user.email, calendarId);

        if (!connection) {
            return NextResponse.json({ error: 'Calendar connection not found' }, { status: 404 });
        }

        const dbUser3 = await prisma.user.findUnique({ where: { email: session.user.email }, select: { id: true } });
        const userId = dbUser3?.id;
        if (!userId) return NextResponse.json({ error: 'User not found' }, { status: 404 });

        await deleteCalendarEvent(connection, calendarId, eventId, deleteMode);

        // Remove from cache - await to ensure consistency
        try {
            if (deleteMode === 'all') {
                await deleteCachedEvent(userId, eventId, connection.provider);
            }
            // For 'this' and 'future', force a full cache refresh
        } catch (e) {
            console.error('[CACHE] Failed to delete cached event:', e);
        }

        return NextResponse.json({ success: true });
    } catch (error: any) {
        console.error('Error deleting event:', error);
        return NextResponse.json({ error: error.message || 'Failed to delete event' }, { status: 500 });
    }
}
