
import { NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
import { prisma } from '@/lib/db';
import { 
  fetchExternalEvents, 
  syncToGoogleCalendar, 
  syncToMicrosoftCalendar,
  detectConflicts,
  refreshGoogleToken,
  refreshMicrosoftToken 
} from '@/lib/calendar-sync';

export async function POST(request: Request) {
  try {
    const session = await getServerSession(authOptions);

    if (!session) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    // Get user's calendar sync configuration
    const syncConfig = await prisma.calendarSync.findUnique({
      where: { userId: session.user.id },
    });

    if (!syncConfig || !syncConfig.isEnabled) {
      return NextResponse.json(
        { error: 'Calendar sync is not configured' },
        { status: 400 }
      );
    }

    // Check if token needs refresh
    let accessToken = syncConfig.accessToken;
    const now = new Date();
    
    if (syncConfig.tokenExpiry && syncConfig.tokenExpiry <= now) {
      // Token expired, refresh it
      if (syncConfig.provider === 'GOOGLE' && syncConfig.refreshToken) {
        accessToken = await refreshGoogleToken(syncConfig.refreshToken, session.user.id);
      } else if (syncConfig.provider === 'MICROSOFT' && syncConfig.refreshToken) {
        accessToken = await refreshMicrosoftToken(syncConfig.refreshToken, session.user.id);
      } else {
        return NextResponse.json(
          { error: 'Token expired and no refresh token available. Please reconnect your calendar.' },
          { status: 401 }
        );
      }
    }

    if (!accessToken) {
      return NextResponse.json(
        { error: 'Invalid access token' },
        { status: 401 }
      );
    }

    // Fetch CRM events
    const crmEvents = await prisma.calendarEvent.findMany({
      where: {
        userId: session.user.id,
        isDeleted: false,
        startTime: {
          gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), // Last 30 days
        },
      },
    });

    let syncedCount = 0;
    let conflictsDetected = 0;

    if (syncConfig.syncDirection === 'ONE_WAY') {
      // Push CRM events to external calendar
      for (const event of crmEvents) {
        if (!event.eventId) {
          // Event not yet synced, create in external calendar
          try {
            let externalEventId;
            
            if (syncConfig.provider === 'GOOGLE') {
              externalEventId = await syncToGoogleCalendar(accessToken, event);
            } else if (syncConfig.provider === 'MICROSOFT') {
              externalEventId = await syncToMicrosoftCalendar(accessToken, event);
            }

            // Update event with external ID
            await prisma.calendarEvent.update({
              where: { id: event.id },
              data: {
                eventId: externalEventId,
                syncStatus: 'SYNCED',
                syncProvider: syncConfig.provider,
                lastSyncedAt: new Date(),
              },
            });

            syncedCount++;
          } catch (error) {
            console.error(`Failed to sync event ${event.id}:`, error);
            await prisma.calendarEvent.update({
              where: { id: event.id },
              data: {
                syncStatus: 'FAILED',
              },
            });
          }
        }
      }
    } else if (syncConfig.syncDirection === 'TWO_WAY') {
      // Fetch external events
      const startDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
      const endDate = new Date(Date.now() + 90 * 24 * 60 * 60 * 1000);

      const externalEvents = await fetchExternalEvents(
        syncConfig.provider as 'GOOGLE' | 'MICROSOFT',
        accessToken,
        startDate,
        endDate
      );

      // Detect conflicts
      const conflicts = await detectConflicts(session.user.id, externalEvents, crmEvents);
      conflictsDetected = conflicts.length;

      // Sync CRM events to external calendar (CRM is source of truth)
      for (const event of crmEvents) {
        try {
          let externalEventId = event.eventId;

          if (!externalEventId) {
            // Create new event in external calendar
            if (syncConfig.provider === 'GOOGLE') {
              externalEventId = await syncToGoogleCalendar(accessToken, event);
            } else if (syncConfig.provider === 'MICROSOFT') {
              externalEventId = await syncToMicrosoftCalendar(accessToken, event);
            }
          }

          // Update event status
          await prisma.calendarEvent.update({
            where: { id: event.id },
            data: {
              eventId: externalEventId || undefined,
              syncStatus: 'SYNCED',
              syncProvider: syncConfig.provider,
              lastSyncedAt: new Date(),
            },
          });

          syncedCount++;
        } catch (error) {
          console.error(`Failed to sync event ${event.id}:`, error);
          await prisma.calendarEvent.update({
            where: { id: event.id },
            data: {
              syncStatus: 'FAILED',
            },
          });
        }
      }

      // Log conflicts for review
      if (conflicts.length > 0) {
        console.log(`Detected ${conflicts.length} calendar conflicts for user ${session.user.id}`);
        // TODO: Notify user about conflicts
      }
    }

    // Update last synced timestamp
    await prisma.calendarSync.update({
      where: { userId: session.user.id },
      data: {
        lastSyncedAt: new Date(),
      },
    });

    return NextResponse.json({
      success: true,
      syncedCount,
      conflictsDetected,
      message: `Successfully synced ${syncedCount} events`,
    });
  } catch (error) {
    console.error('Error during calendar sync:', error);
    return NextResponse.json(
      { error: 'Failed to sync calendar', details: error instanceof Error ? error.message : 'Unknown error' },
      { status: 500 }
    );
  }
}
