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

export const dynamic = 'force-dynamic';

const prisma = new PrismaClient();

// Google Calendar OAuth callback endpoint
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'); // User CUID passed from start route

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

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

    // Get user by session ID or state parameter (which now contains CUID, not email)
    const userId = (session?.user as any)?.id || state;

    if (!userId) {
      return NextResponse.redirect(new URL('/auth/login?error=session_expired', appBaseUrl));
    }

    // Find user in database by ID (works regardless of signup email)
    const user = await prisma.user.findUnique({
      where: { id: userId }
    });

    if (!user) {
      return NextResponse.redirect(new URL('/auth/login?error=user_not_found', appBaseUrl));
    }

    // Initialize Google OAuth client
    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);

    // Exchange authorization code for access token
    const { tokens } = await oauth2Client.getToken(code);
    oauth2Client.setCredentials(tokens);

    // Fetch user calendars to store in connection settings
    // Dynamic import to avoid circular dep issues in some envs, or just standard import?
    // Standard import is better but we are inside function scope to check diff.
    // I'll assume the import is added at top level or I force it here if possible. 
    // I will add import at top level in separate chunk if needed? 
    // Replace whole file content is unsafe. I'll use multi-replace.

    // We need getUserCalendars. I'll use require or assume import added.
    // Actually, I'll allow ReplaceFileContent to manage imports? No.
    // I'll use multi_replace to add import AND update logic.

    // WAIT, better approach: Just implement the fetch logic here locally to avoid import issues or dependency on lib if it changes.
    // But duplicate code is bad.
    // I'll add the import at the top.

    // Logic:
    const calendar = google.calendar({ version: 'v3', auth: oauth2Client });
    const response = await calendar.calendarList.list();
    const remoteCalendars = response.data.items?.map((item: any) => ({
      id: item.id,
      title: item.summary,
      isPrimary: item.primary,
      backgroundColor: item.backgroundColor, // Store calendar color for event fallback
      selected: true // Default newly found to true
    })) || [];

    // Check if connection already exists
    const existingConnection = await prisma.calendarConnection.findFirst({
      where: {
        userId: user.id,
        provider: 'google'
      }
    });

    let finalCalendars = remoteCalendars;

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

      // Update existing connection
      await prisma.calendarConnection.update({
        where: { id: existingConnection.id },
        data: {
          accessToken: tokens.access_token || '',
          refreshToken: tokens.refresh_token || existingConnection.refreshToken,
          expiresAt: tokens.expiry_date ? new Date(tokens.expiry_date) : null,
          calendars: finalCalendars, // Store calendars
          updatedAt: new Date()
        }
      });
    } else {
      // Create new connection
      await prisma.calendarConnection.create({
        data: {
          userId: user.id,
          provider: 'google',
          accessToken: tokens.access_token || '',
          refreshToken: tokens.refresh_token || null,
          expiresAt: tokens.expiry_date ? new Date(tokens.expiry_date) : null,
          calendars: finalCalendars, // Store calendars
        }
      });
    }

    // Store Google account record for Tasks API access
    // Use 'google-calendar' provider to avoid collision with NextAuth's 'google' provider
    const existingAccount = await prisma.account.findFirst({
      where: { userId: user.id, provider: { in: ['google-calendar', 'google'] } }
    });

    if (existingAccount) {
      await prisma.account.update({
        where: { id: existingAccount.id },
        data: {
          provider: 'google-calendar',
          access_token: tokens.access_token || '',
          refresh_token: tokens.refresh_token || existingAccount.refresh_token,
          expires_at: tokens.expiry_date ? Math.floor(tokens.expiry_date / 1000) : null,
          scope: tokens.scope || existingAccount.scope,
          token_type: tokens.token_type || 'Bearer',
        }
      });
    } else {
      await prisma.account.create({
        data: {
          userId: user.id,
          type: 'oauth',
          provider: 'google-calendar',
          providerAccountId: `calendar-${user.id}`,
          access_token: tokens.access_token || '',
          refresh_token: tokens.refresh_token || null,
          expires_at: tokens.expiry_date ? Math.floor(tokens.expiry_date / 1000) : null,
          scope: tokens.scope || '',
          token_type: tokens.token_type || 'Bearer',
        }
      });
    }

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