/**
 * Email Deliverability Scoring Service
 * Evaluates email addresses and sender reputation for deliverability
 */

export interface DeliverabilityScore {
  email: string;
  score: number; // 0-100
  riskLevel: 'low' | 'medium' | 'high' | 'critical';
  issues: string[];
  warnings: string[];
  recommendations: string[];
}

export interface SenderReputation {
  domain: string;
  spfRecord: boolean;
  dkimRecord: boolean;
  dmarcRecord: boolean;
  reputationScore: number; // 0-100
  blacklistStatus: 'clean' | 'warning' | 'listed';
}

/**
 * Score email address for deliverability
 */
export function scoreEmailDeliverability(email: string): DeliverabilityScore {
  const issues: string[] = [];
  const warnings: string[] = [];
  const recommendations: string[] = [];
  let score = 100;

  // Check email format
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  if (!emailRegex.test(email)) {
    issues.push('Invalid email format');
    score -= 50;
  }

  // Check for disposable email domains
  if (isDisposableEmail(email)) {
    warnings.push('Disposable email address detected');
    score -= 20;
    recommendations.push('Consider filtering out disposable email addresses');
  }

  // Check for role-based addresses
  if (isRoleBasedEmail(email)) {
    warnings.push('Role-based email address (info@, support@, etc.)');
    score -= 10;
  }

  // Check for suspicious patterns
  if (hasSuspiciousPatterns(email)) {
    warnings.push('Email contains suspicious patterns');
    score -= 15;
    recommendations.push('Verify email address with double opt-in');
  }

  // Check domain reputation
  const domain = email.split('@')[1];
  if (isHighRiskDomain(domain)) {
    warnings.push('Email domain has reputation issues');
    score -= 25;
    recommendations.push('Monitor bounce rates for this domain');
  }

  // Check for common typos
  const typos = detectCommonTypos(email);
  if (typos.length > 0) {
    warnings.push(`Possible typo detected: ${typos.join(', ')}`);
    score -= 10;
    recommendations.push('Suggest correction to subscriber');
  }

  // Ensure score is between 0-100
  score = Math.max(0, Math.min(100, score));

  const riskLevel = getRiskLevel(score);

  return {
    email,
    score,
    riskLevel,
    issues,
    warnings,
    recommendations,
  };
}

/**
 * Score batch of emails
 */
export function scoreEmailBatch(emails: string[]): DeliverabilityScore[] {
  return emails.map((email) => scoreEmailDeliverability(email));
}

/**
 * Get average deliverability score
 */
export function getAverageDeliverabilityScore(scores: DeliverabilityScore[]): number {
  if (scores.length === 0) return 0;
  const sum = scores.reduce((acc, s) => acc + s.score, 0);
  return Math.round(sum / scores.length);
}

/**
 * Filter emails by risk level
 */
export function filterByRiskLevel(
  scores: DeliverabilityScore[],
  riskLevel: 'low' | 'medium' | 'high' | 'critical'
): DeliverabilityScore[] {
  return scores.filter((s) => s.riskLevel === riskLevel);
}

/**
 * Get sender reputation score
 */
export function calculateSenderReputation(
  domain: string,
  metrics: {
    bounceRate: number; // 0-100
    complaintRate: number; // 0-100
    unsubscribeRate: number; // 0-100
    spfConfigured: boolean;
    dkimConfigured: boolean;
    dmarcConfigured: boolean;
    isBlacklisted: boolean;
  }
): SenderReputation {
  let score = 100;

  // Deduct for bounce rate
  if (metrics.bounceRate > 5) {
    score -= Math.min(30, metrics.bounceRate * 2);
  }

  // Deduct for complaint rate
  if (metrics.complaintRate > 0.1) {
    score -= Math.min(25, metrics.complaintRate * 100);
  }

  // Deduct for high unsubscribe rate
  if (metrics.unsubscribeRate > 0.5) {
    score -= Math.min(15, metrics.unsubscribeRate * 20);
  }

  // Add points for SPF/DKIM/DMARC
  if (metrics.spfConfigured) score += 10;
  if (metrics.dkimConfigured) score += 10;
  if (metrics.dmarcConfigured) score += 10;

  // Penalize if blacklisted
  if (metrics.isBlacklisted) {
    score -= 50;
  }

  score = Math.max(0, Math.min(100, score));

  const blacklistStatus = metrics.isBlacklisted ? 'listed' : score < 50 ? 'warning' : 'clean';

  return {
    domain,
    spfRecord: metrics.spfConfigured,
    dkimRecord: metrics.dkimConfigured,
    dmarcRecord: metrics.dmarcConfigured,
    reputationScore: score,
    blacklistStatus,
  };
}

/**
 * Check if email is from disposable email service
 */
function isDisposableEmail(email: string): boolean {
  const disposableDomains = [
    'tempmail.com',
    'throwaway.email',
    '10minutemail.com',
    'guerrillamail.com',
    'mailinator.com',
    'maildrop.cc',
    'temp-mail.org',
    'yopmail.com',
    'trashmail.com',
    'fakeinbox.com',
  ];

  const domain = email.split('@')[1]?.toLowerCase();
  return disposableDomains.includes(domain);
}

/**
 * Check if email is role-based
 */
function isRoleBasedEmail(email: string): boolean {
  const roleBasedPrefixes = [
    'info',
    'support',
    'contact',
    'admin',
    'noreply',
    'no-reply',
    'help',
    'sales',
    'marketing',
    'webmaster',
    'postmaster',
  ];

  const prefix = email.split('@')[0]?.toLowerCase();
  return roleBasedPrefixes.includes(prefix);
}

/**
 * Check for suspicious patterns
 */
function hasSuspiciousPatterns(email: string): boolean {
  const suspiciousPatterns = [
    /\d{10,}/, // Too many consecutive digits
    /(.)\1{4,}/, // Too many repeated characters
    /[^a-zA-Z0-9@._-]/, // Invalid characters
  ];

  return suspiciousPatterns.some((pattern) => pattern.test(email));
}

/**
 * Check if domain has reputation issues
 */
function isHighRiskDomain(domain: string): boolean {
  const highRiskDomains = [
    'example.com',
    'test.com',
    'localhost',
    'invalid.com',
    'spam.com',
  ];

  return highRiskDomains.includes(domain?.toLowerCase());
}

/**
 * Detect common email typos
 */
function detectCommonTypos(email: string): string[] {
  const commonTypos: Record<string, string[]> = {
    'gmial.com': ['gmail.com'],
    'gmai.com': ['gmail.com'],
    'yahooo.com': ['yahoo.com'],
    'hotmial.com': ['hotmail.com'],
    'outlok.com': ['outlook.com'],
  };

  const domain = email.split('@')[1]?.toLowerCase();
  return commonTypos[domain] || [];
}

/**
 * Get risk level based on score
 */
function getRiskLevel(score: number): 'low' | 'medium' | 'high' | 'critical' {
  if (score >= 80) return 'low';
  if (score >= 60) return 'medium';
  if (score >= 40) return 'high';
  return 'critical';
}

/**
 * Generate deliverability report
 */
export function generateDeliverabilityReport(scores: DeliverabilityScore[]): {
  totalEmails: number;
  averageScore: number;
  riskBreakdown: Record<string, number>;
  recommendations: string[];
  criticalIssues: string[];
} {
  const riskBreakdown = {
    low: 0,
    medium: 0,
    high: 0,
    critical: 0,
  };

  const allRecommendations = new Set<string>();
  const criticalIssues = new Set<string>();

  for (const score of scores) {
    riskBreakdown[score.riskLevel]++;
    score.recommendations.forEach((r) => allRecommendations.add(r));
    score.issues.forEach((i) => criticalIssues.add(i));
  }

  return {
    totalEmails: scores.length,
    averageScore: getAverageDeliverabilityScore(scores),
    riskBreakdown,
    recommendations: Array.from(allRecommendations),
    criticalIssues: Array.from(criticalIssues),
  };
}
