import { createDAVClient } from 'tsdav';

export interface CalendarEvent {
  uid: string;
  summary: string;
  description?: string;
  location?: string;
  startDate: Date;
  endDate: Date;
  status?: string;
}

export class NextcloudCalendarService {
  private client: any;
  private initialized: boolean = false;
  private initPromise: Promise<void> | null = null;

  async initialize() {
    // Wenn bereits am Initialisieren, warte auf Abschluss
    if (this.initPromise) {
      return this.initPromise;
    }

    // Wenn bereits initialisiert, fertig
    if (this.initialized && this.client) {
      return Promise.resolve();
    }

    // Neue Initialisierung starten
    this.initPromise = this._doInitialize();
    
    try {
      await this.initPromise;
    } finally {
      this.initPromise = null;
    }
  }

  private async _doInitialize() {
    const serverUrl = process.env.NEXTCLOUD_URL;
    const username = process.env.NEXTCLOUD_USERNAME;
    const password = process.env.NEXTCLOUD_PASSWORD;

    console.log('🔍 Nextcloud credentials check:');
    console.log('   URL:', serverUrl);
    console.log('   Username:', username);
    console.log('   Password length:', password?.length, 'chars');

    if (!serverUrl || !username || !password) {
      throw new Error('Nextcloud credentials not configured');
    }

    try {
      console.log('⏳ Creating Nextcloud CalDAV client...');
      
      this.client = await createDAVClient({
        serverUrl: `${serverUrl}/remote.php/dav`,
        credentials: {
          username,
          password,
        },
        authMethod: 'Basic',
        defaultAccountType: 'caldav',
      });

      this.initialized = true;
      console.log('✅ Nextcloud CalDAV client initialized successfully');
    } catch (error: any) {
      console.error('❌ Failed to initialize Nextcloud CalDAV client:', error);
      this.initialized = false;
      this.client = null;
      throw new Error(`Nextcloud initialization failed: ${error.message}`);
    }
  }

  async getCalendars() {
    await this.initialize();
    try {
      const calendars = await this.client.fetchCalendars();
      return calendars;
    } catch (error) {
      console.error('Error fetching calendars:', error);
      throw error;
    }
  }

  async createEvent(calendarUrl: string, event: CalendarEvent) {
    await this.initialize();
    
    const icsContent = this.generateICS(event);

    try {
      const result = await this.client.createCalendarObject({
        calendar: { url: calendarUrl },
        filename: `${event.uid}.ics`,
        iCalString: icsContent,
      });
      
      console.log('✅ Event created in Nextcloud:', event.summary);
      return result;
    } catch (error) {
      console.error('Error creating event:', error);
      throw error;
    }
  }

  async updateEvent(calendarUrl: string, event: CalendarEvent) {
    await this.initialize();
    
    const icsContent = this.generateICS(event);

    try {
      const result = await this.client.updateCalendarObject({
        calendar: { url: calendarUrl },
        filename: `${event.uid}.ics`,
        iCalString: icsContent,
      });
      
      console.log('✅ Event updated in Nextcloud:', event.summary);
      return result;
    } catch (error) {
      console.error('Error updating event:', error);
      throw error;
    }
  }

  async deleteEvent(calendarUrl: string, eventUid: string) {
    await this.initialize();

    try {
      await this.client.deleteCalendarObject({
        calendar: { url: calendarUrl },
        filename: `${eventUid}.ics`,
      });
      
      console.log('✅ Event deleted from Nextcloud:', eventUid);
    } catch (error) {
      console.error('Error deleting event:', error);
      throw error;
    }
  }

  async syncBookingToCalendar(booking: any) {
    await this.initialize();

    const calendars = await this.getCalendars();
    
    if (calendars.length === 0) {
      throw new Error('No calendars found in Nextcloud');
    }

    // Suche nach "Buchungen" Kalender, sonst verwende ersten
    let calendar = calendars.find((cal: any) => 
      cal.displayName?.toLowerCase().includes('buchung')
    );
    
    if (!calendar) {
      console.warn('⚠️  Kein "Buchungen"-Kalender gefunden, verwende:', calendars[0].displayName);
      calendar = calendars[0];
    } else {
      console.log('✅ Verwende Kalender:', calendar.displayName);
    }

    const event: CalendarEvent = {
      uid: `savethemoment-booking-${booking.id}`,
      summary: `${booking.customerName} - ${booking.location?.name || 'Unbekannt'}`,
      description: `
Buchung #${booking.bookingNumber || booking.id}
Kunde: ${booking.customerName}
E-Mail: ${booking.customerEmail}
Telefon: ${booking.customerPhone || 'N/A'}
Event-Location: ${booking.eventLocation || booking.eventAddress}
Status: ${booking.status}
Fotobox: ${booking.photobox?.model || 'Keine Box'}
Standort: ${booking.location?.name || 'Unbekannt'}
Preis: ${booking.calculatedPrice || 0}€
      `.trim(),
      location: `${booking.eventAddress || ''}, ${booking.eventZip || ''} ${booking.eventCity || ''}`.trim(),
      startDate: new Date(booking.eventDate),
      endDate: new Date(new Date(booking.eventDate).getTime() + 4 * 60 * 60 * 1000),
      status: booking.status,
    };

    try {
      await this.createEvent(calendar.url, event);
      console.log('✅ Event in Nextcloud erstellt:', event.summary);
      return event;
    } catch (error: any) {
      if (error.message?.includes('already exists') || error.response?.status === 412) {
        await this.updateEvent(calendar.url, event);
        console.log('✅ Event in Nextcloud aktualisiert:', event.summary);
        return event;
      }
      throw error;
    }
  }

  async removeBookingFromCalendar(bookingId: string) {
    await this.initialize();

    const calendars = await this.getCalendars();
    
    if (calendars.length === 0) {
      throw new Error('No calendars found in Nextcloud');
    }

    // Suche nach "Buchungen" Kalender, sonst verwende ersten
    let calendar = calendars.find((cal: any) => 
      cal.displayName?.toLowerCase().includes('buchung')
    );
    
    if (!calendar) {
      calendar = calendars[0];
    }

    const eventUid = `savethemoment-booking-${bookingId}`;

    try {
      await this.deleteEvent(calendar.url, eventUid);
      console.log('✅ Event aus Nextcloud gelöscht:', eventUid);
    } catch (error) {
      console.error('Error removing booking from calendar:', error);
    }
  }

  private generateICS(event: CalendarEvent): string {
    const formatDate = (date: Date) => {
      return date.toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z';
    };

    const now = new Date();
    const dtstamp = formatDate(now);
    const dtstart = formatDate(event.startDate);
    const dtend = formatDate(event.endDate);

    return `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//SaveTheMoment Atlas//DE
BEGIN:VEVENT
UID:${event.uid}
DTSTAMP:${dtstamp}
DTSTART:${dtstart}
DTEND:${dtend}
SUMMARY:${event.summary}
DESCRIPTION:${event.description || ''}
LOCATION:${event.location || ''}
STATUS:${event.status === 'CONFIRMED' ? 'CONFIRMED' : 'TENTATIVE'}
END:VEVENT
END:VCALENDAR`;
  }
}

export const nextcloudCalendar = new NextcloudCalendarService();
