// lib/emailLoggingService.ts
import { createSbServiceRole } from "@/lib/supabaseServer";

export type EmailType = 
  | 'contract-created'
  | 'contract-updated' 
  | 'contract-cancelled'
  | 'employee-created'
  | 'invitation'
  | 'auto-declaration-invitation'
  | 'invoice'
  | 'signature-request'
  | 'signature-request-employer'
  | 'signature-request-employee'
  | 'signature-request-employee-amendment' // Signature avenant par salarié
  | 'signature-request-salarie' // Demande signature salarié (depuis Lambda DocuSeal)
  | 'bulk-signature-notification'
  | 'salary-transfer-notification'
  | 'salary-transfer-payment-confirmation' // Confirmation paiement salaires effectué
  | 'contribution-notification' // Notification de cotisations
  | 'notification'
  | 'support-reply' // Réponse support
  | 'support-ticket-created' // Nouveau ticket
  | 'support-ticket-reply' // Réponse utilisateur
  | 'contact-support' // Formulaire contact public
  | 'amendment-completed-employer' // Avenant signé (notification employeur)
  | 'amendment-completed-employee' // Avenant signé (notification salarié)
  | 'referral' // Email d'invitation au parrainage
  | 'account-activation'
  | 'access-updated'
  | 'access-revoked'
  | 'password-created'
  | 'password-changed'
  | 'twofa-enabled'
  | 'twofa-disabled'
  | 'bulk-email'
  | 'bulk_communication'
  | 'system-notification'
  | 'other';

export type EmailStatus = 
  | 'pending'
  | 'sending' 
  | 'sent'
  | 'delivered'
  | 'bounce'
  | 'complaint'
  | 'failed';

export interface EmailLogData {
  // Informations obligatoires
  senderEmail: string;
  recipientEmail: string;
  subject: string;
  emailType: EmailType;
  
  // Contenu
  htmlContent?: string;
  textContent?: string;
  templateName?: string;
  templateData?: Record<string, any>;
  
  // Destinataires additionnels
  ccEmails?: string[];
  bccEmails?: string[];
  
  // Informations utilisateur
  senderUserId?: string;
  senderName?: string;
  
  // SES
  sesMessageId?: string;
  sesRegion?: string;
  sesConfigurationSet?: string;
  sesSourceArn?: string;
  sesReturnPath?: string;
  
  // Contexte
  organizationId?: string;
  contractId?: string;
  ticketId?: string;
  userAgent?: string;
  ipAddress?: string;
  
  // Métadonnées
  tags?: Record<string, any>;
  context?: Record<string, any>;
  
  // Statut
  emailStatus?: EmailStatus;
}

export interface EmailLogUpdate {
  emailStatus?: EmailStatus;
  sesMessageId?: string;
  bounceReason?: string;
  complaintReason?: string;
  failureReason?: string;
  sentAt?: Date;
  deliveredAt?: Date;
}

class EmailLoggingService {
  private sb = createSbServiceRole();

  /**
   * Extraire l'adresse email pure d'une chaîne qui peut contenir un nom d'affichage
   * Ex: "Odentas <paie@odentas.fr>" -> "paie@odentas.fr"
   */
  private extractPureEmail(emailString: string): string {
    // Rechercher un email entre < >
    const match = emailString.match(/<([^>]+)>/);
    if (match) {
      return match[1].trim();
    }
    
    // Si pas de < >, retourner la chaîne nettoyée
    return emailString.trim().replace(/['"]/g, '');
  }

  /**
   * Créer un nouveau log d'email
   */
  async logEmail(data: EmailLogData): Promise<string | null> {
    try {
      const cleanedSenderEmail = this.extractPureEmail(data.senderEmail);
      const cleanedRecipientEmail = this.extractPureEmail(data.recipientEmail);
      
      const logEntry = {
        sender_email: cleanedSenderEmail,
        recipient_email: cleanedRecipientEmail,
        cc_emails: data.ccEmails?.map(email => this.extractPureEmail(email)) || null,
        bcc_emails: data.bccEmails || null,
        subject: data.subject,
        html_content: data.htmlContent || null,
        text_content: data.textContent || null,
        template_name: data.templateName || null,
        template_data: data.templateData || null,
        email_type: data.emailType,
        email_status: data.emailStatus || 'pending',
        
        // Informations utilisateur
        sender_user_id: data.senderUserId || null,
        sender_name: data.senderName || null,
        
        // SES
        ses_message_id: data.sesMessageId || null,
        ses_region: data.sesRegion || process.env.AWS_REGION || 'eu-west-3',
        ses_configuration_set: data.sesConfigurationSet || null,
        ses_source_arn: data.sesSourceArn || null,
        ses_return_path: data.sesReturnPath || null,
        
        // Contexte
        organization_id: data.organizationId || null,
        contract_id: data.contractId || null,
        ticket_id: data.ticketId || null,
        user_agent: data.userAgent || null,
        ip_address: data.ipAddress || null,
        
        // Métadonnées
        tags: data.tags || {},
        context: data.context || {},
        
        created_at: new Date().toISOString()
      };

      const { data: result, error } = await this.sb
        .from('email_logs')
        .insert(logEntry)
        .select('id')
        .single();

      if (error) {
        console.error('Erreur lors de la création du log email:', error);
        return null;
      }

      return result?.id || null;
    } catch (error) {
      console.error('Exception lors de la création du log email:', error);
      return null;
    }
  }

  /**
   * Mettre à jour un log d'email existant
   */
  async updateEmailLog(logId: string, updates: EmailLogUpdate): Promise<boolean> {
    try {
      const updateData: any = {};

      if (updates.emailStatus) {
        updateData.email_status = updates.emailStatus;
      }
      
      if (updates.sesMessageId) {
        updateData.ses_message_id = updates.sesMessageId;
      }
      
      if (updates.bounceReason) {
        updateData.bounce_reason = updates.bounceReason;
      }
      
      if (updates.complaintReason) {
        updateData.complaint_reason = updates.complaintReason;
      }
      
      if (updates.failureReason) {
        updateData.failure_reason = updates.failureReason;
      }
      
      if (updates.sentAt) {
        updateData.sent_at = updates.sentAt.toISOString();
      }
      
      if (updates.deliveredAt) {
        updateData.delivered_at = updates.deliveredAt.toISOString();
      }

      const { error } = await this.sb
        .from('email_logs')
        .update(updateData)
        .eq('id', logId);

      if (error) {
        console.error('Erreur lors de la mise à jour du log email:', error);
        return false;
      }

      return true;
    } catch (error) {
      console.error('Exception lors de la mise à jour du log email:', error);
      return false;
    }
  }

  /**
   * Mettre à jour un log par SES Message ID
   */
  async updateEmailLogBySesId(sesMessageId: string, updates: EmailLogUpdate): Promise<boolean> {
    try {
      const updateData: any = {};

      if (updates.emailStatus) {
        updateData.email_status = updates.emailStatus;
      }
      
      if (updates.bounceReason) {
        updateData.bounce_reason = updates.bounceReason;
      }
      
      if (updates.complaintReason) {
        updateData.complaint_reason = updates.complaintReason;
      }
      
      if (updates.failureReason) {
        updateData.failure_reason = updates.failureReason;
      }
      
      if (updates.sentAt) {
        updateData.sent_at = updates.sentAt.toISOString();
      }
      
      if (updates.deliveredAt) {
        updateData.delivered_at = updates.deliveredAt.toISOString();
      }

      const { error } = await this.sb
        .from('email_logs')
        .update(updateData)
        .eq('ses_message_id', sesMessageId);

      if (error) {
        console.error('Erreur lors de la mise à jour du log email par SES ID:', error);
        return false;
      }

      return true;
    } catch (error) {
      console.error('Exception lors de la mise à jour du log email par SES ID:', error);
      return false;
    }
  }

  /**
   * Récupérer les logs d'email avec filtres
   */
  async getEmailLogs(options: {
    limit?: number;
    offset?: number;
    emailType?: EmailType;
    emailStatus?: EmailStatus;
    senderEmail?: string;
    recipientEmail?: string;
    organizationId?: string;
    dateFrom?: Date;
    dateTo?: Date;
    searchTerm?: string;
  } = {}) {
    try {
      let query = this.sb
        .from('email_logs')
        .select(`
          id,
          created_at,
          sent_at,
          delivered_at,
          sender_email,
          sender_name,
          recipient_email,
          cc_emails,
          bcc_emails,
          subject,
          email_type,
          email_status,
          ses_message_id,
          organization_id,
          contract_id,
          ticket_id,
          bounce_reason,
          complaint_reason,
          failure_reason,
          tags,
          context
        `);

      // Filtres
      if (options.emailType) {
        query = query.eq('email_type', options.emailType);
      }
      
      if (options.emailStatus) {
        query = query.eq('email_status', options.emailStatus);
      }
      
      if (options.senderEmail) {
        query = query.eq('sender_email', options.senderEmail);
      }
      
      if (options.recipientEmail) {
        query = query.eq('recipient_email', options.recipientEmail);
      }
      
      if (options.organizationId) {
        query = query.eq('organization_id', options.organizationId);
      }
      
      if (options.dateFrom) {
        query = query.gte('created_at', options.dateFrom.toISOString());
      }
      
      if (options.dateTo) {
        query = query.lte('created_at', options.dateTo.toISOString());
      }
      
      if (options.searchTerm) {
        query = query.or(`subject.ilike.%${options.searchTerm}%,recipient_email.ilike.%${options.searchTerm}%,sender_email.ilike.%${options.searchTerm}%`);
      }

      // Pagination et tri
      query = query
        .order('created_at', { ascending: false })
        .range(options.offset || 0, (options.offset || 0) + (options.limit || 50) - 1);

      const { data, error } = await query;

      if (error) {
        console.error('Erreur lors de la récupération des logs email:', error);
        return { data: [], error };
      }

      return { data: data || [], error: null };
    } catch (error) {
      console.error('Exception lors de la récupération des logs email:', error);
      return { data: [], error };
    }
  }

  /**
   * Récupérer les statistiques d'email
   */
  async getEmailStats(options: {
    dateFrom?: Date;
    dateTo?: Date;
    organizationId?: string;
  } = {}) {
    try {
      let query = this.sb
        .from('email_stats_summary')
        .select('*');

      if (options.dateFrom) {
        query = query.gte('date', options.dateFrom.toISOString().split('T')[0]);
      }
      
      if (options.dateTo) {
        query = query.lte('date', options.dateTo.toISOString().split('T')[0]);
      }

      const { data, error } = await query;

      if (error) {
        console.error('Erreur lors de la récupération des stats email:', error);
        return { data: [], error };
      }

      return { data: data || [], error: null };
    } catch (error) {
      console.error('Exception lors de la récupération des stats email:', error);
      return { data: [], error };
    }
  }

  /**
   * Nettoyer les anciens logs (à exécuter périodiquement)
   */
  async cleanupOldLogs(daysToKeep: number = 90): Promise<number> {
    try {
      const cutoffDate = new Date();
      cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);

      const { data, error } = await this.sb
        .from('email_logs')
        .delete()
        .lt('created_at', cutoffDate.toISOString())
        .select('id');

      if (error) {
        console.error('Erreur lors du nettoyage des logs email:', error);
        return 0;
      }

      return data?.length || 0;
    } catch (error) {
      console.error('Exception lors du nettoyage des logs email:', error);
      return 0;
    }
  }
}

// Instance singleton
export const emailLogger = new EmailLoggingService();

// Helpers pour extraction de données SES
export function extractSesDataFromResponse(sesResponse: any) {
  return {
    sesMessageId: sesResponse.MessageId,
    sesRegion: process.env.AWS_REGION || 'eu-west-3',
  };
}

export function extractUserContextFromRequest(request: any) {
  return {
    userAgent: request.headers.get('user-agent') || undefined,
    ipAddress: request.headers.get('x-forwarded-for') || 
               request.headers.get('x-real-ip') || 
               undefined,
  };
}