import { getServerSession } from "next-auth/next";
import { authOptions } from "@/app/api/auth/options";
import { redirect } from "next/navigation";
import { prisma } from "@/lib/prisma";
import { CalendarClient } from "@/components/calendar/calendar-client";
import { Metadata } from "next";
import { CalendarDays, Users, Bookmark, Clock } from "lucide-react";
import Image from "next/image";
import { Button } from "@/components/ui/button";
import { add } from 'date-fns';

export const metadata: Metadata = {
  title: "NEAH - Calendrier | Gestion d'événements professionnelle",
  description: "Plateforme avancée pour la gestion de vos rendez-vous, réunions et événements professionnels",
  keywords: "calendrier, rendez-vous, événements, gestion du temps, NEAH",
};

interface Event {
  id: string;
  title: string;
  description?: string | null;
  start: Date;
  end: Date;
  location?: string | null;
  isAllDay: boolean;
  type?: string;
  attendees?: { id: string; name: string }[];
}

interface Calendar {
  id: string;
  name: string;
  color: string;
  description?: string | null;
  events: Event[];
}

export default async function CalendarPage() {
  const session = await getServerSession(authOptions);

  if (!session?.user) {
    redirect("/api/auth/signin");
  }

  const userId = session.user.username || session.user.email || '';
  
  // Ensure user has a default private calendar (created automatically if missing)
  // This is the user's personal calendar, distinct from Microsoft synced calendars
  const defaultPrivateCalendarName = "Mon Calendrier";
  const existingDefaultCalendar = await prisma.calendar.findFirst({
    where: {
      userId: session?.user?.id || '',
      name: defaultPrivateCalendarName,
      missionId: null, // Not a mission calendar
      syncConfig: null, // Not a synced calendar
    }
  });

  if (!existingDefaultCalendar) {
    // Create default private calendar for the user
    await prisma.calendar.create({
      data: {
        name: defaultPrivateCalendarName,
        color: "#4f46e5", // Indigo color
        description: "Votre calendrier personnel",
        userId: session?.user?.id || '',
        missionId: null,
      }
    });
    console.log(`[AGENDA] Created default private calendar for user ${session?.user?.id}`);
  }
  
  // Get all calendars for the user with mission relation and sync configuration
  // This includes:
  // 1. Personal calendars (userId = session.user.id) - including the default private calendar
  // 2. Microsoft synced calendars (named "Privée" with syncConfig)
  // 3. Mission calendars where user is associated via MissionUser
  // 4. Group calendars where user is a member
  // Exclude "Privée" and "Default" calendars that are not synced (they should only exist if synced from courrier)
  
  // Get personal calendars
  // First, get all calendars, then filter in code for "Privée"/"Default" with sync
  let personalCalendars = await prisma.calendar.findMany({
    where: {
      userId: session?.user?.id || '',
      OR: [
        // Keep calendars that are not "Privée" or "Default"
        { name: { notIn: ["Privée", "Default"] } },
        // Or keep "Privée"/"Default" calendars that have sync config (we'll filter syncEnabled in code)
        {
          AND: [
            { name: { in: ["Privée", "Default"] } },
            { 
              syncConfig: { 
                isNot: null
              } 
            }
          ]
        }
      ]
    },
    include: {
      events: {
        orderBy: {
          start: 'asc'
        }
      },
      mission: {
        include: {
          missionUsers: true
        }
      },
      syncConfig: {
        include: {
          mailCredential: {
            select: {
              id: true,
              email: true,
              display_name: true,
            }
          }
        }
      }
    }
  });
  
  // Filter out "Privée"/"Default" calendars that don't have syncEnabled=true
  personalCalendars = personalCalendars.filter(cal => {
    // Keep all non-"Privée"/"Default" calendars
    if (cal.name !== "Privée" && cal.name !== "Default") {
      return true;
    }
    // For "Privée"/"Default", only keep if syncConfig exists and is enabled
    return cal.syncConfig && cal.syncConfig.syncEnabled === true;
  });
  
  // Get mission calendars where user is associated via MissionUser
  const missionUserRelations = await prisma.missionUser.findMany({
    where: {
      userId: session?.user?.id || '',
    },
    include: {
      mission: {
        include: {
          calendars: {
            where: {
              // Exclude calendars already owned by user (already in personalCalendars)
              userId: { not: session?.user?.id || '' }
            },
            include: {
              events: {
                orderBy: {
                  start: 'asc'
                }
              },
              mission: {
                include: {
                  missionUsers: true
                }
              },
              syncConfig: {
                include: {
                  mailCredential: {
                    select: {
                      id: true,
                      email: true,
                      display_name: true,
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  });
  
  // Extract mission calendars
  const missionCalendars = missionUserRelations.flatMap(mu => mu.mission.calendars);
  
  // Debug: Log calendar filtering
  console.log('[AGENDA] Calendar filtering:', {
    personalCalendarsCount: personalCalendars.length,
    personalCalendars: personalCalendars.map(cal => ({
      id: cal.id,
      name: cal.name,
      hasSyncConfig: !!cal.syncConfig,
      syncEnabled: cal.syncConfig?.syncEnabled,
      provider: cal.syncConfig?.provider,
    })),
    missionCalendarsCount: missionCalendars.length,
  });
  
  // Combine personal and mission calendars
  let calendars = [...personalCalendars, ...missionCalendars];

  // Auto-setup sync for email accounts from courrier (Microsoft only)
  // Get all Microsoft email accounts (OAuth)
  const microsoftAccounts = await prisma.mailCredentials.findMany({
    where: {
      userId: session?.user?.id || '',
      host: {
        contains: 'outlook.office365.com'
      },
      use_oauth: true,
      refresh_token: {
        not: null
      }
    },
    select: {
      id: true,
      email: true,
      display_name: true,
      refresh_token: true,
      use_oauth: true
    }
  });

  // Clean up orphaned syncs FIRST (before creating new ones)
  // This handles the case where a user deleted and re-added an email account
  const allMailCredentialIds = new Set([
    ...microsoftAccounts.map(acc => acc.id)
  ]);
  
  const orphanedSyncs = await prisma.calendarSync.findMany({
    where: {
      calendar: {
        userId: session?.user?.id || ''
      },
      mailCredentialId: {
        not: null
      }
    },
    include: {
      calendar: true,
      mailCredential: true
    }
  });
  
  // Delete syncs where mailCredential no longer exists
  for (const sync of orphanedSyncs) {
    if (sync.mailCredentialId && !allMailCredentialIds.has(sync.mailCredentialId)) {
      console.log(`[AGENDA] Deleting orphaned sync for non-existent mailCredentialId: ${sync.mailCredentialId}`);
      // Delete the calendar if it has no events
      const eventCount = await prisma.event.count({
        where: { calendarId: sync.calendarId }
      });
      if (eventCount === 0) {
        await prisma.calendar.delete({
          where: { id: sync.calendarId }
        });
      } else {
        // Just disable the sync, keep the calendar
        await prisma.calendarSync.update({
          where: { id: sync.id },
          data: { syncEnabled: false }
        });
      }
    }
  }

  // For each Microsoft account, ensure there's a synced calendar
  for (const account of microsoftAccounts) {
    // Check if a calendar sync already exists for this account (enabled or disabled)
    // This prevents creating duplicate calendars for the same account
    const existingSync = await prisma.calendarSync.findFirst({
      where: {
        mailCredentialId: account.id
      },
      include: {
        calendar: true
      }
    });

    // If sync exists but is disabled, re-enable it instead of creating a new calendar
    if (existingSync && !existingSync.syncEnabled) {
      await prisma.calendarSync.update({
        where: { id: existingSync.id },
        data: { syncEnabled: true }
      });
      continue; // Skip to next account
    }

    if (!existingSync) {
      // Try to discover calendars for this account
      try {
        const { discoverMicrosoftCalendars } = await import('@/lib/services/microsoft-calendar-sync');
        const externalCalendars = await discoverMicrosoftCalendars(
          session?.user?.id || '',
          account.email
        );

        if (externalCalendars.length > 0) {
          // Use the first calendar (usually the main calendar)
          const mainCalendar = externalCalendars[0];
          
          // Create a private calendar for this account
          const calendar = await prisma.calendar.create({
            data: {
              name: "Privée",
              color: "#0078D4", // Microsoft blue
              description: `Calendrier synchronisé avec ${account.display_name || account.email}`,
              userId: session?.user?.id || '',
            }
          });

          // Create sync configuration
          // Use 5 minutes for Microsoft (more reactive than 15 minutes)
          await prisma.calendarSync.create({
            data: {
              calendarId: calendar.id,
              mailCredentialId: account.id,
              provider: 'microsoft',
              externalCalendarId: mainCalendar.id,
              externalCalendarUrl: mainCalendar.webLink || mainCalendar.id,
              syncEnabled: true,
              syncFrequency: 5
            }
          });

          // Trigger initial sync
          try {
            const { syncMicrosoftCalendar } = await import('@/lib/services/microsoft-calendar-sync');
            const syncConfig = await prisma.calendarSync.findUnique({
              where: { calendarId: calendar.id },
              include: {
                calendar: true,
                mailCredential: true
              }
            });
            if (syncConfig) {
              await syncMicrosoftCalendar(syncConfig.id, true);
            }
          } catch (syncError) {
            console.error('Error during initial Microsoft sync:', syncError);
            // Don't fail if sync fails, calendar is still created
          }
        }
      } catch (error) {
        // Microsoft sync setup failed - likely because account doesn't have calendar scope yet
        // This is expected for accounts authenticated before calendar scope was added
        // User will need to re-authenticate their Microsoft account to get calendar access
        console.log(`Microsoft calendar sync not available for ${account.email} - account may need re-authentication with calendar permissions`);
        // Don't fail the page - continue with other accounts
      }
    }
  }

  // Clean up duplicate calendars for the same mailCredentialId
  // NOTE: This is mainly for cleaning up OLD duplicates created before we fixed the cascade deletion
  // New duplicates should not occur since we now delete calendars when mail accounts are deleted
  // This cleanup is conservative: only processes if there are multiple ENABLED syncs for the same account
  
  // Only run cleanup if there are actually multiple syncs to check (performance optimization)
  const syncCountCheck = await prisma.calendarSync.count({
    where: {
      calendar: {
        userId: session?.user?.id || ''
      },
      mailCredentialId: {
        in: Array.from(allMailCredentialIds)
      }
    }
  });

  console.log(`[AGENDA] Cleanup check: ${syncCountCheck} syncs found for ${allMailCredentialIds.size} mail accounts`);

  // Only run full cleanup if there are multiple syncs (likely duplicates)
  if (syncCountCheck > allMailCredentialIds.size) {
    console.log(`[AGENDA] Running cleanup: ${syncCountCheck} syncs > ${allMailCredentialIds.size} accounts (potential duplicates)`);
    const allSyncs = await prisma.calendarSync.findMany({
      where: {
        calendar: {
          userId: session?.user?.id || ''
        },
        mailCredentialId: {
          in: Array.from(allMailCredentialIds)
        }
      },
      include: {
        calendar: true,
        mailCredential: true
      },
      orderBy: {
        createdAt: 'desc'
      }
    });

    // Group by mailCredentialId and provider
    const syncsByAccount = new Map<string, typeof allSyncs>();
    for (const sync of allSyncs) {
      if (sync.mailCredentialId) {
        const key = `${sync.mailCredentialId}-${sync.provider}`;
        if (!syncsByAccount.has(key)) {
          syncsByAccount.set(key, []);
        }
        syncsByAccount.get(key)!.push(sync);
      }
    }

    // For each account, keep only the most recent enabled sync, disable or delete others
    // IMPORTANT: Only process if there are actually multiple ENABLED syncs to avoid disabling active syncs
    for (const [key, syncs] of syncsByAccount.entries()) {
      if (syncs.length > 1) {
        // Count how many are actually enabled
        const enabledSyncs = syncs.filter(s => s.syncEnabled === true);
        
        // Only clean up if there are multiple ENABLED syncs
        // If there's only one enabled sync, don't touch it even if there are disabled duplicates
        if (enabledSyncs.length > 1) {
          console.log(`[AGENDA] Found ${enabledSyncs.length} enabled syncs for ${key}, cleaning up duplicates`);
          
          // Sort by syncEnabled first (enabled first), then by lastSyncAt (most recently synced first), then by createdAt (newest first)
          syncs.sort((a, b) => {
            if (a.syncEnabled !== b.syncEnabled) {
              return a.syncEnabled ? -1 : 1;
            }
            // Among enabled syncs, prefer the one with most recent sync
            if (a.syncEnabled && b.syncEnabled) {
              if (a.lastSyncAt && b.lastSyncAt) {
                return new Date(b.lastSyncAt).getTime() - new Date(a.lastSyncAt).getTime();
              }
              if (a.lastSyncAt && !b.lastSyncAt) return -1;
              if (!a.lastSyncAt && b.lastSyncAt) return 1;
            }
            return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
          });

          const keepSync = syncs[0];
          const duplicates = syncs.slice(1);

          // Additional safety check: only disable duplicates if the sync to keep is actually valid
          // (has events or has been synced recently)
          const keepSyncEventCount = await prisma.event.count({
            where: { calendarId: keepSync.calendarId }
          });
          const keepSyncIsValid = keepSyncEventCount > 0 || keepSync.lastSyncAt;

          if (!keepSyncIsValid) {
            console.log(`[AGENDA] WARNING: Sync to keep ${keepSync.id} has no events and no sync history - skipping cleanup to avoid disabling valid syncs`);
            continue; // Skip this group to avoid disabling a potentially valid sync
          }

          console.log(`[AGENDA] Keeping sync ${keepSync.id} (calendar: ${keepSync.calendar.name}, events: ${keepSyncEventCount}), disabling ${duplicates.length} duplicates`);

          // Disable or delete duplicate syncs
          for (const duplicate of duplicates) {
            if (duplicate.syncEnabled) {
              // Disable the duplicate sync
              console.log(`[AGENDA] Disabling duplicate sync ${duplicate.id} (calendar: ${duplicate.calendar.name})`);
              await prisma.calendarSync.update({
                where: { id: duplicate.id },
                data: { syncEnabled: false }
              });
            }
            // Delete the calendar if it has no events
            const eventCount = await prisma.event.count({
              where: { calendarId: duplicate.calendarId }
            });
            if (eventCount === 0) {
              console.log(`[AGENDA] Deleting empty calendar ${duplicate.calendar.name} (${duplicate.calendarId})`);
              await prisma.calendar.delete({
                where: { id: duplicate.calendarId }
              });
            }
          }
        } else if (enabledSyncs.length === 1 && syncs.length > 1) {
          // There's only one enabled sync but multiple disabled ones - this is fine, don't touch anything
          console.log(`[AGENDA] Found 1 enabled sync and ${syncs.length - 1} disabled syncs for ${key} - no cleanup needed`);
        }
      }
    }
  }

  // Auto-sync Microsoft calendars if needed (background, don't block page load)
  const microsoftSyncConfigs = await prisma.calendarSync.findMany({
    where: {
      provider: 'microsoft',
      syncEnabled: true,
      calendar: {
        userId: session?.user?.id || ''
      }
    }
  });

  console.log(`[AGENDA] Found ${microsoftSyncConfigs.length} Microsoft sync configs`);

  // Trigger sync for Microsoft calendars that need it (async, don't wait)
  for (const syncConfig of microsoftSyncConfigs) {
    // For Microsoft, use a more frequent check (1 minute) for better reactivity
    // This allows new events to appear faster without overloading the API
    const microsoftMinSyncInterval = 1; // minutes (reduced from 2 to 1 for faster sync)
    const minutesSinceLastSync = syncConfig.lastSyncAt 
      ? (Date.now() - syncConfig.lastSyncAt.getTime()) / (1000 * 60)
      : Infinity;
    
    // Sync if never synced, or if enough time has passed (use minimum of 1 min or configured frequency)
    // Also sync if last sync had an error or if calendar has no events (might be a new setup)
    const calendar = await prisma.calendar.findUnique({
      where: { id: syncConfig.calendarId },
      include: {
        _count: {
          select: { events: true }
        }
      }
    });
    
    const hasEvents = (calendar?._count?.events || 0) > 0;
    const hasError = !!syncConfig.lastSyncError;
    
    const needsSync = !syncConfig.lastSyncAt || 
      minutesSinceLastSync >= Math.min(microsoftMinSyncInterval, syncConfig.syncFrequency) ||
      hasError || // Force sync if there was an error
      (!hasEvents && syncConfig.lastSyncAt); // Force sync if calendar has no events but was synced before
    
    console.log(`[AGENDA] Microsoft sync config ${syncConfig.id}: lastSyncAt=${syncConfig.lastSyncAt}, minutesSinceLastSync=${minutesSinceLastSync.toFixed(1)}, needsSync=${needsSync}, syncFrequency=${syncConfig.syncFrequency}, hasEvents=${hasEvents}, hasError=${hasError}`);
    
    if (needsSync) {
      console.log(`[AGENDA] Triggering background sync for Microsoft calendar ${syncConfig.id}`);
      // Trigger sync in background (don't await to avoid blocking page load)
      // The sync will update the database, and the next page load will show the events
      // Use forceSync=true because we've already checked that sync is needed
      import('@/lib/services/microsoft-calendar-sync').then(({ syncMicrosoftCalendar }) => {
        syncMicrosoftCalendar(syncConfig.id, true).then((result) => {
          console.log(`[AGENDA] Microsoft sync completed:`, {
            calendarSyncId: syncConfig.id,
            calendarId: syncConfig.calendarId,
            synced: result.synced,
            created: result.created,
            updated: result.updated,
            deleted: result.deleted,
          });
          
          // Verify events were created by checking the database
          prisma.event.count({
            where: { calendarId: syncConfig.calendarId }
          }).then((count) => {
            console.log(`[AGENDA] Total events in calendar ${syncConfig.calendarId} after sync: ${count}`);
          }).catch((err) => {
            console.error('[AGENDA] Error counting events:', err);
          });
        }).catch((error) => {
          console.error('[AGENDA] Background sync failed for Microsoft calendar', {
            calendarSyncId: syncConfig.id,
            calendarId: syncConfig.calendarId,
            error: error instanceof Error ? error.message : String(error),
            stack: error instanceof Error ? error.stack : undefined,
          });
        });
      });
    } else {
      console.log(`[AGENDA] Microsoft sync skipped - too soon since last sync (${minutesSinceLastSync.toFixed(1)} min < ${Math.min(microsoftMinSyncInterval, syncConfig.syncFrequency)} min)`);
    }
  }

  // Refresh calendars after auto-setup and cleanup
  // Exclude "Privée" and "Default" calendars that are not synced
  // IMPORTANT: Include all "Privée"/"Default" calendars that have ANY syncConfig (enabled or disabled)
  // We'll filter by syncEnabled later
  calendars = await prisma.calendar.findMany({
    where: {
      userId: session?.user?.id || '',
      OR: [
        // Keep calendars that are not "Privée" or "Default"
        { name: { notIn: ["Privée", "Default"] } },
        // Or keep "Privée"/"Default" calendars that have ANY sync config (we'll filter by enabled later)
        {
          AND: [
            { name: { in: ["Privée", "Default"] } },
            { 
              syncConfig: { 
                isNot: null
              } 
            }
          ]
        }
      ]
    },
    include: {
      events: {
        orderBy: {
          start: 'asc'
        }
      },
      mission: {
        include: {
          missionUsers: true
        }
      },
      syncConfig: {
        include: {
          mailCredential: {
            select: {
              id: true,
              email: true,
              display_name: true,
            }
          }
        }
      }
    }
  });

  // No default calendar creation - only synced calendars from courrier
  
  // Filter out "Privée" and "Default" calendars that don't have active sync
  calendars = calendars.filter(cal => {
    const isPrivateOrDefault = cal.name === "Privée" || cal.name === "Default";
    const hasActiveSync = cal.syncConfig?.syncEnabled === true && cal.syncConfig?.mailCredential;
    
    // Exclude "Privée"/"Default" calendars that are not actively synced
    if (isPrivateOrDefault && !hasActiveSync) {
      console.log(`[AGENDA] Filtering out calendar ${cal.name} (${cal.id}): syncEnabled=${cal.syncConfig?.syncEnabled}, hasMailCredential=${!!cal.syncConfig?.mailCredential}`);
      return false;
    }
    return true;
  });
  
  // Debug: Log all calendars with syncConfig to see what we have
  const calendarsWithSync = calendars.filter(cal => cal.syncConfig);
  console.log(`[AGENDA] Total calendars with syncConfig: ${calendarsWithSync.length}`);
  calendarsWithSync.forEach(cal => {
    const eventCount = cal.events?.length || 0;
    console.log(`[AGENDA] Calendar: ${cal.name}, provider: ${cal.syncConfig?.provider}, syncEnabled: ${cal.syncConfig?.syncEnabled}, hasMailCredential: ${!!cal.syncConfig?.mailCredential}, events: ${eventCount}`);
    if (cal.syncConfig?.provider === 'microsoft') {
      // Log all Microsoft events with details
      console.log(`[AGENDA] Microsoft calendar ${cal.id} events (${eventCount}):`, cal.events.map(e => ({
        id: e.id,
        title: e.title,
        start: e.start,
        end: e.end,
        isAllDay: e.isAllDay,
        description: e.description ? e.description.substring(0, 50) : null
      })));
      
      // Also check directly in DB to see if there are more events
      prisma.event.count({
        where: { calendarId: cal.id }
      }).then((dbCount) => {
        if (dbCount !== eventCount) {
          console.log(`[AGENDA] WARNING: Calendar ${cal.id} has ${eventCount} events in query but ${dbCount} in DB`);
        }
      }).catch((err) => {
        console.error('[AGENDA] Error counting events in DB:', err);
      });
    }
  });

  // Sort calendars: "Mon Calendrier" first, then synced, then groups, then missions
  calendars = calendars.sort((a, b) => {
    const aIsMonCalendrier = a.name === "Mon Calendrier";
    const bIsMonCalendrier = b.name === "Mon Calendrier";
    const aIsSynced = a.syncConfig?.syncEnabled && a.syncConfig?.mailCredential;
    const bIsSynced = b.syncConfig?.syncEnabled && b.syncConfig?.mailCredential;
    const aIsGroup = a.name?.startsWith("Groupe:");
    const bIsGroup = b.name?.startsWith("Groupe:");
    const aIsMission = a.name?.startsWith("Mission:");
    const bIsMission = b.name?.startsWith("Mission:");
    
    // "Mon Calendrier" always first
    if (aIsMonCalendrier && !bIsMonCalendrier) return -1;
    if (!aIsMonCalendrier && bIsMonCalendrier) return 1;
    
    // Synced calendars second
    if (aIsSynced && !bIsSynced) return -1;
    if (!aIsSynced && bIsSynced) return 1;
    
    // Groups third
    if (aIsGroup && !bIsGroup && !bIsSynced) return -1;
    if (!aIsGroup && bIsGroup && !aIsSynced) return 1;
    
    // Missions fourth
    if (aIsMission && !bIsMission && !bIsGroup && !bIsSynced) return -1;
    if (!aIsMission && bIsMission && !aIsGroup && !aIsSynced) return 1;
    
    // Same type, sort by name
    return (a.name || '').localeCompare(b.name || '');
  });

  const now = new Date();
  const nextWeek = add(now, { days: 7 });
  
  const upcomingEvents = calendars.flatMap(cal => 
    cal.events.filter(event => 
      new Date(event.start) >= now && 
      new Date(event.start) <= nextWeek
    )
  ).sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime());

  // Calculate statistics
  const totalEvents = calendars.flatMap(cal => cal.events).length;
  
  const totalMeetingHours = calendars
    .flatMap(cal => cal.events)
    .reduce((total, event) => {
      const start = new Date(event.start);
      const end = new Date(event.end);
      const hours = (end.getTime() - start.getTime()) / (1000 * 60 * 60);
      return total + (isNaN(hours) ? 0 : hours);
    }, 0);

  return (
    <main className="w-full bg-white" style={{ height: 'calc(100vh - 40px)' }}>
      <div className="w-full h-full px-4 pt-12 pb-4 flex">
        <CalendarClient 
          initialCalendars={calendars} 
          userId={session.user.id}
          userProfile={{
            name: session.user.name || '',
            email: session.user.email || '',
            avatar: session.user.image || undefined
          }}
        />
      </div>
    </main>
  );
}
