import Imap from 'imap';
import { simpleParser } from 'mailparser';
import { prisma } from './prisma';
import { emailParser } from './email-parser';
import { bookingAutomationService } from './booking-automation';

export interface ImapConfig {
  host: string;
  port: number;
  user: string;
  password: string;
  secure: boolean;
}

export class EmailSyncService {
  async syncLocationEmails(locationId: string): Promise<{
    success: boolean;
    newEmails: number;
    newBookings: number;
    errors: string[];
  }> {
    console.log('=== Starting email sync for location:', locationId);
    
    const location = await prisma.location.findUnique({
      where: { id: locationId },
    });

    console.log('Location found:', location?.name, 'emailSyncEnabled:', location?.emailSyncEnabled);

    if (!location || !location.emailSyncEnabled) {
      return { success: false, newEmails: 0, newBookings: 0, errors: ['Location not found or sync disabled'] };
    }

    if (!location.imapHost || !location.imapUser || !location.imapPassword) {
      console.log('IMAP config incomplete:', {
        host: !!location.imapHost,
        user: !!location.imapUser,
        password: !!location.imapPassword,
      });
      return { success: false, newEmails: 0, newBookings: 0, errors: ['IMAP configuration incomplete'] };
    }

    const config: ImapConfig = {
      host: location.imapHost,
      port: location.imapPort || 993,
      user: location.imapUser,
      password: location.imapPassword,
      secure: location.imapSecure ?? true,
    };

    console.log('IMAP config:', { host: config.host, port: config.port, user: config.user, secure: config.secure });

    return this.fetchNewEmails(config, location.slug, locationId);
  }

  private async fetchNewEmails(
    config: ImapConfig,
    locationSlug: string,
    locationId: string
  ): Promise<{
    success: boolean;
    newEmails: number;
    newBookings: number;
    errors: string[];
  }> {
    console.log('=== fetchNewEmails called for', locationSlug);
    
    return new Promise((resolve) => {
      const imap = new Imap({
        user: config.user,
        password: config.password,
        host: config.host,
        port: config.port,
        tls: config.secure,
        tlsOptions: { rejectUnauthorized: false },
      });

      console.log('IMAP instance created');

      let newEmails = 0;
      let newBookings = 0;
      const errors: string[] = [];

      imap.once('ready', () => {
        console.log('IMAP connection ready!');
        imap.openBox('INBOX', false, (err, box) => {
          if (err) {
            errors.push(`Failed to open inbox: ${err.message}`);
            imap.end();
            return;
          }

          // Fetch all emails from last 30 days (including seen/read ones for testing)
          const thirtyDaysAgo = new Date();
          thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

          imap.search([['SINCE', thirtyDaysAgo]], async (err, results) => {
            if (err) {
              console.error('IMAP search error:', err);
              errors.push(`Search failed: ${err.message}`);
              imap.end();
              return;
            }

            console.log('IMAP search results:', results?.length || 0, 'emails found');

            if (!results || results.length === 0) {
              console.log('No emails found in search');
              imap.end();
              resolve({ success: true, newEmails: 0, newBookings: 0, errors });
              return;
            }

            console.log('Fetching', results.length, 'emails...');
            const fetch = imap.fetch(results, { bodies: '' });

            fetch.on('message', (msg: any, seqno: number) => {
              console.log('Processing email', seqno);
              msg.on('body', (stream: any, info: any) => {
                simpleParser(stream, async (err: any, parsed: any) => {
                  if (err) {
                    console.error('Parse error for email', seqno, ':', err);
                    errors.push(`Failed to parse email ${seqno}: ${err.message}`);
                    return;
                  }

                  console.log('Parsed email:', {
                    subject: parsed.subject,
                    from: parsed.from?.text,
                    messageId: parsed.messageId,
                  });

                  try {
                    // Save email to database
                    const existingEmail = await prisma.email.findUnique({
                      where: { messageId: parsed.messageId },
                    });

                    if (existingEmail) {
                      console.log('Email already exists, skipping:', parsed.messageId);
                      return; // Already processed
                    }

                    console.log('Saving new email to database...');
                    const emailRecord = await prisma.email.create({
                      data: {
                        locationSlug,
                        from: parsed.from?.text || '',
                        to: parsed.to?.text || '',
                        subject: parsed.subject || '',
                        textBody: parsed.text || '',
                        htmlBody: parsed.html || '',
                        messageId: parsed.messageId || undefined,
                        direction: 'INBOUND',
                        receivedAt: parsed.date || new Date(),
                      },
                    });

                    console.log('✅ Email saved with ID:', emailRecord.id);
                    newEmails++;

                    // Try to parse as Ninjaforms booking
                    console.log('Attempting to parse as Ninjaforms email...');
                    console.log('Email subject:', parsed.subject);
                    console.log('Text body length:', parsed.text?.length || 0);
                    console.log('HTML body length:', parsed.html?.length || 0);
                    console.log('First 500 chars of content:', (parsed.html || parsed.text || '').substring(0, 500));
                    
                    const parsedData = emailParser.parseFromNinjaFormsEmail(
                      parsed.html || parsed.text || '',
                      parsed.subject || ''
                    );

                    console.log('Parse result:', parsedData ? '✅ Parsed successfully' : '❌ Not a Ninjaforms email');
                    if (parsedData) {
                      console.log('Parsed data:', JSON.stringify(parsedData, null, 2));
                    }

                    if (parsedData) {
                      console.log('Creating booking from parsed data:', parsedData);
                      // Create booking from parsed data
                      const booking = await this.createBookingFromParsedData(parsedData, locationSlug);
                      
                      if (booking) {
                        console.log('✅ Booking created:', booking.id);
                        newBookings++;
                        
                        // Update email with booking ID
                        await prisma.email.update({
                          where: { id: emailRecord.id },
                          data: {
                            parsed: true,
                            parsedData: parsedData as any,
                            bookingId: booking.id,
                          },
                        });

                        // Create notification
                        await prisma.notification.create({
                          data: {
                            type: 'NEW_BOOKING_EMAIL',
                            title: 'Neue Buchung per E-Mail',
                            message: `${parsedData.firstName || parsedData.companyName} - ${parsedData.eventDate}`,
                            metadata: {
                              bookingId: booking.id,
                              emailId: emailRecord.id,
                            },
                          },
                        });
                        console.log('✅ Notification created');
                      } else {
                        console.log('❌ Booking creation failed');
                      }
                    }
                  } catch (error: any) {
                    errors.push(`Failed to process email ${seqno}: ${error.message}`);
                  }
                });
              });
            });

            fetch.once('end', async () => {
              // Update last sync time
              await prisma.location.update({
                where: { id: locationId },
                data: { lastEmailSync: new Date() },
              });

              imap.end();
              resolve({ success: true, newEmails, newBookings, errors });
            });
          });
        });
      });

      imap.once('error', (err: any) => {
        errors.push(`IMAP connection error: ${err.message}`);
        resolve({ success: false, newEmails, newBookings, errors });
      });

      imap.connect();
    });
  }

  private parseDateString(dateString: string): Date | null {
    if (!dateString) return null;

    // Try German format: DD.MM.YYYY or D.M.YYYY
    const germanMatch = dateString.match(/(\d{1,2})\.(\d{1,2})\.(\d{4})/);
    if (germanMatch) {
      const [, day, month, year] = germanMatch;
      return new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
    }

    // Try ISO format or other standard formats
    const date = new Date(dateString);
    return isNaN(date.getTime()) ? null : date;
  }

  private async createBookingFromParsedData(data: any, locationSlug: string) {
    try {
      const location = await prisma.location.findUnique({
        where: { slug: locationSlug },
      });

      if (!location) return null;

      // Parse German date format
      const eventDate = this.parseDateString(data.eventDate);
      if (!eventDate) {
        console.error('Invalid event date:', data.eventDate);
        return null;
      }

      const startOfDay = new Date(eventDate);
      startOfDay.setHours(0, 0, 0, 0);
      const endOfDay = new Date(eventDate);
      endOfDay.setHours(23, 59, 59, 999);

      const availablePhotobox = await prisma.photobox.findFirst({
        where: {
          locationId: location.id,
          model: data.model,
          active: true,
          NOT: {
            bookings: {
              some: {
                eventDate: {
                  gte: startOfDay,
                  lte: endOfDay,
                },
                status: {
                  in: ['RESERVED', 'CONFIRMED'],
                },
              },
            },
          },
        },
      });

      if (!availablePhotobox) {
        console.warn('No photobox available for parsed booking');
        return null;
      }

      const bookingNumber = this.generateBookingNumber();

      const booking = await prisma.booking.create({
        data: {
          bookingNumber,
          locationId: location.id,
          photoboxId: availablePhotobox.id,
          status: 'RESERVED',
          
          customerName: data.companyName || `${data.firstName || ''} ${data.lastName || ''}`.trim(),
          customerEmail: data.email,
          customerPhone: data.phone,
          customerAddress: data.street,
          customerCity: data.city,
          customerZip: data.zip,
          
          invoiceType: data.companyName ? 'BUSINESS' : 'PRIVATE',
          companyName: data.companyName,
          
          eventDate: eventDate,
          eventAddress: data.eventLocation || '',
          eventCity: data.city || '',
          eventZip: data.zip || '',
          eventLocation: data.eventLocation,
          
          setupTimeStart: eventDate,
          setupTimeLatest: eventDate,
          
          calculatedPrice: data.calculatedPrice || 0,
          notes: data.message,
        },
      });

      // 🤖 Automatische Post-Booking Aktionen
      console.log('📢 Starte automatische Aktionen...');
      bookingAutomationService.runPostBookingActions(booking.id).catch(err => {
        console.error('⚠️  Automatische Aktionen fehlgeschlagen:', err);
      });

      return booking;
    } catch (error) {
      console.error('Failed to create booking from parsed data:', error);
      return null;
    }
  }

  private generateBookingNumber(): string {
    const date = new Date();
    const year = date.getFullYear().toString().slice(-2);
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const random = Math.floor(Math.random() * 10000).toString().padStart(4, '0');
    return `STM-${year}${month}-${random}`;
  }
}

export const emailSyncService = new EmailSyncService();
