import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from "@/lib/auth";
import { PrismaClient } from '@prisma/client';
import { getUserDatabases } from '@/lib/notion-calendar';

export const dynamic = 'force-dynamic';

const prisma = new PrismaClient();

export async function GET(request: NextRequest) {
    try {
        const session = await getServerSession(authOptions);
        const { searchParams } = new URL(request.url);
        const code = searchParams.get('code');
        const state = searchParams.get('state');

        const appBaseUrl = process.env.NEXTAUTH_URL || request.url;

        if (!code) {
            return NextResponse.redirect(new URL('/tasks?error=oauth_code_missing', appBaseUrl));
        }

        const userId = (session?.user as any)?.id || state;
        if (!userId) {
            return NextResponse.redirect(new URL('/auth/login?error=session_expired', appBaseUrl));
        }

        const user = await prisma.user.findUnique({ where: { id: userId } });
        if (!user) {
            return NextResponse.redirect(new URL('/auth/login?error=user_not_found', appBaseUrl));
        }

        // Exchange code for tokens
        const clientId = process.env.NOTION_CLIENT_ID || '';
        const clientSecret = process.env.NOTION_CLIENT_SECRET || '';
        const redirectUri = process.env.NOTION_REDIRECT_URI
            || `${process.env.NEXTAUTH_URL}/api/calendar/notion/callback`;

        const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');

        const tokenResponse = await fetch('https://api.notion.com/v1/oauth/token', {
            method: 'POST',
            headers: {
                'Authorization': `Basic ${credentials}`,
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                grant_type: 'authorization_code',
                code,
                redirect_uri: redirectUri,
            }),
        });

        if (!tokenResponse.ok) {
            const errorText = await tokenResponse.text();
            console.error('Notion token exchange failed:', errorText);
            return NextResponse.redirect(new URL('/tasks?error=oauth_failed', appBaseUrl));
        }

        const tokens = await tokenResponse.json();
        const accessToken = tokens.access_token;
        const refreshToken = tokens.refresh_token || null;

        // Fetch databases shared with the integration
        const databases = await getUserDatabases(accessToken);

        // Map to calendar-style format for consistency
        const calendars = databases.map(db => ({
            id: db.id,
            title: db.title,
            selected: true,
            dateProperty: db.dateProperty,
            backgroundColor: '#000000',
        }));

        // Check for existing connection
        const existingConnection = await prisma.calendarConnection.findFirst({
            where: { userId: user.id, provider: 'notion' },
        });

        if (existingConnection) {
            // Merge selection state
            let finalCalendars = calendars;
            if (existingConnection.calendars && Array.isArray(existingConnection.calendars)) {
                const existingList = existingConnection.calendars as any[];
                finalCalendars = calendars.map(remote => {
                    const match = existingList.find((e: any) => e.id === remote.id);
                    return {
                        ...remote,
                        selected: match ? match.selected : true,
                        dateProperty: remote.dateProperty || match?.dateProperty,
                    };
                });
            }

            await prisma.calendarConnection.update({
                where: { id: existingConnection.id },
                data: {
                    accessToken,
                    refreshToken: refreshToken || existingConnection.refreshToken,
                    calendars: finalCalendars,
                    updatedAt: new Date(),
                },
            });
        } else {
            await prisma.calendarConnection.create({
                data: {
                    userId: user.id,
                    provider: 'notion',
                    accessToken,
                    refreshToken,
                    calendars,
                },
            });
        }

        return NextResponse.redirect(new URL('/tasks?calendar=connected&openSettings=calendars', appBaseUrl));
    } catch (error) {
        console.error('Notion OAuth error:', error);
        const appBaseUrl = process.env.NEXTAUTH_URL || request.url;
        return NextResponse.redirect(new URL('/tasks?error=oauth_failed', appBaseUrl));
    }
}
