/**
 * Automated Email List Cleaning Service
 * Removes invalid, bounced, and disposable emails from lists
 */

import {
  scoreEmailDeliverability,
  filterByRiskLevel,
  type DeliverabilityScore,
} from './deliverabilityScoring.ts';
import {
  filterActiveSubscribers,
  deduplicateEmailList,
  type EmailSubscriber,
} from './emailListManagement.ts';

export interface ListCleaningConfig {
  removeInvalidEmails: boolean;
  removeDisposableEmails: boolean;
  removeRoleBasedEmails: boolean;
  removeBouncedEmails: boolean;
  removeComplainedEmails: boolean;
  removeHighRiskEmails: boolean;
  minDeliverabilityScore: number; // 0-100
}

export interface ListCleaningResult {
  originalCount: number;
  finalCount: number;
  removed: number;
  removedBreakdown: {
    invalid: number;
    disposable: number;
    roleBased: number;
    bounced: number;
    complained: number;
    highRisk: number;
    duplicates: number;
  };
  removedEmails: string[];
  keptEmails: EmailSubscriber[];
}

/**
 * Clean email list based on configuration
 */
export function cleanEmailList(
  subscribers: EmailSubscriber[],
  config: ListCleaningConfig
): ListCleaningResult {
  const originalCount = subscribers.length;
  const removedEmails = new Set<string>();
  const removedBreakdown = {
    invalid: 0,
    disposable: 0,
    roleBased: 0,
    bounced: 0,
    complained: 0,
    highRisk: 0,
    duplicates: 0,
  };

  let workingList = [...subscribers];

  // Remove duplicates
  if (config.removeInvalidEmails) {
    const { unique, duplicates } = deduplicateEmailList(workingList);
    duplicates.forEach((email) => removedEmails.add(email));
    removedBreakdown.duplicates = duplicates.length;
    workingList = unique;
  }

  // Remove bounced emails
  if (config.removeBouncedEmails) {
    const beforeCount = workingList.length;
    workingList = workingList.filter((sub) => {
      if (sub.bounced) {
        removedEmails.add(sub.email);
        return false;
      }
      return true;
    });
    removedBreakdown.bounced = beforeCount - workingList.length;
  }

  // Remove complained emails
  if (config.removeComplainedEmails) {
    const beforeCount = workingList.length;
    workingList = workingList.filter((sub) => {
      if (sub.complained) {
        removedEmails.add(sub.email);
        return false;
      }
      return true;
    });
    removedBreakdown.complained = beforeCount - workingList.length;
  }

  // Score remaining emails for deliverability
  const scores = workingList.map((sub) => ({
    subscriber: sub,
    score: scoreEmailDeliverability(sub.email),
  }));

  // Remove invalid emails
  if (config.removeInvalidEmails) {
    const beforeCount = workingList.length;
    workingList = scores
      .filter((item) => {
        if (item.score.issues.length > 0) {
          removedEmails.add(item.subscriber.email);
          return false;
        }
        return true;
      })
      .map((item) => item.subscriber);
    removedBreakdown.invalid = beforeCount - workingList.length;
  }

  // Remove disposable emails
  if (config.removeDisposableEmails) {
    const beforeCount = workingList.length;
    workingList = workingList.filter((sub) => {
      const score = scoreEmailDeliverability(sub.email);
      if (score.warnings.some((w) => w.includes('Disposable'))) {
        removedEmails.add(sub.email);
        return false;
      }
      return true;
    });
    removedBreakdown.disposable = beforeCount - workingList.length;
  }

  // Remove role-based emails
  if (config.removeRoleBasedEmails) {
    const beforeCount = workingList.length;
    workingList = workingList.filter((sub) => {
      const score = scoreEmailDeliverability(sub.email);
      if (score.warnings.some((w) => w.includes('Role-based'))) {
        removedEmails.add(sub.email);
        return false;
      }
      return true;
    });
    removedBreakdown.roleBased = beforeCount - workingList.length;
  }

  // Remove high-risk emails
  if (config.removeHighRiskEmails) {
    const beforeCount = workingList.length;
    workingList = workingList.filter((sub) => {
      const score = scoreEmailDeliverability(sub.email);
      if (score.score < config.minDeliverabilityScore) {
        removedEmails.add(sub.email);
        return false;
      }
      return true;
    });
    removedBreakdown.highRisk = beforeCount - workingList.length;
  }

  return {
    originalCount,
    finalCount: workingList.length,
    removed: originalCount - workingList.length,
    removedBreakdown,
    removedEmails: Array.from(removedEmails),
    keptEmails: workingList,
  };
}

/**
 * Get recommended cleaning configuration
 */
export function getRecommendedCleaningConfig(): ListCleaningConfig {
  return {
    removeInvalidEmails: true,
    removeDisposableEmails: true,
    removeRoleBasedEmails: false,
    removeBouncedEmails: true,
    removeComplainedEmails: true,
    removeHighRiskEmails: true,
    minDeliverabilityScore: 60,
  };
}

/**
 * Get aggressive cleaning configuration
 */
export function getAggressiveCleaningConfig(): ListCleaningConfig {
  return {
    removeInvalidEmails: true,
    removeDisposableEmails: true,
    removeRoleBasedEmails: true,
    removeBouncedEmails: true,
    removeComplainedEmails: true,
    removeHighRiskEmails: true,
    minDeliverabilityScore: 80,
  };
}

/**
 * Get conservative cleaning configuration
 */
export function getConservativeCleaningConfig(): ListCleaningConfig {
  return {
    removeInvalidEmails: true,
    removeDisposableEmails: false,
    removeRoleBasedEmails: false,
    removeBouncedEmails: true,
    removeComplainedEmails: true,
    removeHighRiskEmails: false,
    minDeliverabilityScore: 0,
  };
}

/**
 * Generate cleaning report
 */
export function generateCleaningReport(result: ListCleaningResult): string {
  const removalRate = ((result.removed / result.originalCount) * 100).toFixed(1);

  return `
Email List Cleaning Report
==========================

Original Count: ${result.originalCount}
Final Count: ${result.finalCount}
Removed: ${result.removed} (${removalRate}%)

Removed Breakdown:
- Invalid Emails: ${result.removedBreakdown.invalid}
- Disposable Emails: ${result.removedBreakdown.disposable}
- Role-Based Emails: ${result.removedBreakdown.roleBased}
- Bounced Emails: ${result.removedBreakdown.bounced}
- Complained Emails: ${result.removedBreakdown.complained}
- High-Risk Emails: ${result.removedBreakdown.highRisk}
- Duplicates: ${result.removedBreakdown.duplicates}

Quality Metrics:
- List Quality: ${((result.finalCount / result.originalCount) * 100).toFixed(1)}%
- Improvement: ${removalRate}% reduction in problematic addresses
  `.trim();
}

/**
 * Estimate cleaning impact
 */
export function estimateCleaningImpact(
  subscribers: EmailSubscriber[],
  config: ListCleaningConfig
): {
  estimatedRemoval: number;
  estimatedRemovalRate: number;
  estimatedFinalCount: number;
} {
  const result = cleanEmailList(subscribers, config);

  return {
    estimatedRemoval: result.removed,
    estimatedRemovalRate: (result.removed / result.originalCount) * 100,
    estimatedFinalCount: result.finalCount,
  };
}
