/**
 * Email List Management Service
 * Handles importing, exporting, and managing email subscriber lists
 */

import { parse } from 'csv-parse/sync';
import { stringify } from 'csv-stringify/sync';

export interface EmailSubscriber {
  email: string;
  firstName?: string;
  lastName?: string;
  segment: 'all' | 'vip' | 'new' | 'inactive' | 'high-value';
  subscribed: boolean;
  bounced: boolean;
  complained: boolean;
  tags?: string[];
  metadata?: Record<string, string>;
  subscribedAt: Date;
  unsubscribedAt?: Date;
}

export interface EmailListImportResult {
  success: boolean;
  imported: number;
  skipped: number;
  errors: Array<{ row: number; email: string; error: string }>;
}

/**
 * Validate email address
 */
export function validateEmail(email: string): boolean {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
}

/**
 * Parse CSV file and extract email list
 */
export function parseCSVEmailList(
  csvContent: string
): { subscribers: Partial<EmailSubscriber>[]; errors: string[] } {
  const errors: string[] = [];
  const subscribers: Partial<EmailSubscriber>[] = [];

  try {
    const records = parse(csvContent, {
      columns: true,
      skip_empty_lines: true,
      trim: true,
    });

    records.forEach((record: Record<string, string>, index: number) => {
      try {
        const email = record.email?.toLowerCase().trim();

        if (!email) {
          errors.push(`Row ${index + 1}: Missing email address`);
          return;
        }

        if (!validateEmail(email)) {
          errors.push(`Row ${index + 1}: Invalid email format: ${email}`);
          return;
        }

        subscribers.push({
          email,
          firstName: record.firstName?.trim(),
          lastName: record.lastName?.trim(),
          segment: (record.segment?.toLowerCase() as any) || 'all',
          subscribed: record.subscribed?.toLowerCase() !== 'false',
          bounced: record.bounced?.toLowerCase() === 'true',
          complained: record.complained?.toLowerCase() === 'true',
          tags: record.tags ? record.tags.split(',').map((t) => t.trim()) : [],
          metadata: record.metadata ? JSON.parse(record.metadata) : {},
          subscribedAt: record.subscribedAt ? new Date(record.subscribedAt) : new Date(),
        });
      } catch (error) {
        errors.push(`Row ${index + 1}: ${error instanceof Error ? error.message : 'Unknown error'}`);
      }
    });
  } catch (error) {
    errors.push(`CSV parsing error: ${error instanceof Error ? error.message : 'Unknown error'}`);
  }

  return { subscribers, errors };
}

/**
 * Generate CSV from email list
 */
export function generateCSVEmailList(subscribers: EmailSubscriber[]): string {
  const headers = [
    'email',
    'firstName',
    'lastName',
    'segment',
    'subscribed',
    'bounced',
    'complained',
    'tags',
    'subscribedAt',
    'unsubscribedAt',
  ];

  const rows = subscribers.map((sub) => [
    sub.email,
    sub.firstName || '',
    sub.lastName || '',
    sub.segment,
    sub.subscribed ? 'true' : 'false',
    sub.bounced ? 'true' : 'false',
    sub.complained ? 'true' : 'false',
    sub.tags?.join(',') || '',
    sub.subscribedAt.toISOString(),
    sub.unsubscribedAt?.toISOString() || '',
  ]);

  return stringify([headers, ...rows]);
}

/**
 * Filter subscribers by segment
 */
export function filterBySegment(
  subscribers: EmailSubscriber[],
  segment: 'all' | 'vip' | 'new' | 'inactive' | 'high-value'
): EmailSubscriber[] {
  if (segment === 'all') {
    return subscribers;
  }

  return subscribers.filter((sub) => sub.segment === segment);
}

/**
 * Filter active subscribers
 */
export function filterActiveSubscribers(subscribers: EmailSubscriber[]): EmailSubscriber[] {
  return subscribers.filter(
    (sub) => sub.subscribed && !sub.bounced && !sub.complained
  );
}

/**
 * Deduplicate email list
 */
export function deduplicateEmailList(
  subscribers: EmailSubscriber[]
): { unique: EmailSubscriber[]; duplicates: string[] } {
  const seen = new Set<string>();
  const unique: EmailSubscriber[] = [];
  const duplicates: string[] = [];

  for (const sub of subscribers) {
    if (seen.has(sub.email)) {
      duplicates.push(sub.email);
    } else {
      seen.add(sub.email);
      unique.push(sub);
    }
  }

  return { unique, duplicates };
}

/**
 * Merge email lists
 */
export function mergeEmailLists(
  list1: EmailSubscriber[],
  list2: EmailSubscriber[]
): EmailSubscriber[] {
  const merged = [...list1];
  const emails = new Set(list1.map((s) => s.email));

  for (const sub of list2) {
    if (!emails.has(sub.email)) {
      merged.push(sub);
      emails.add(sub.email);
    }
  }

  return merged;
}

/**
 * Get list statistics
 */
export function getListStatistics(subscribers: EmailSubscriber[]): {
  total: number;
  subscribed: number;
  unsubscribed: number;
  bounced: number;
  complained: number;
  active: number;
  bySegment: Record<string, number>;
} {
  const stats = {
    total: subscribers.length,
    subscribed: subscribers.filter((s) => s.subscribed).length,
    unsubscribed: subscribers.filter((s) => !s.subscribed).length,
    bounced: subscribers.filter((s) => s.bounced).length,
    complained: subscribers.filter((s) => s.complained).length,
    active: subscribers.filter((s) => s.subscribed && !s.bounced && !s.complained).length,
    bySegment: {
      all: subscribers.filter((s) => s.segment === 'all').length,
      vip: subscribers.filter((s) => s.segment === 'vip').length,
      new: subscribers.filter((s) => s.segment === 'new').length,
      inactive: subscribers.filter((s) => s.segment === 'inactive').length,
      'high-value': subscribers.filter((s) => s.segment === 'high-value').length,
    },
  };

  return stats;
}

/**
 * Add tags to subscribers
 */
export function addTagsToSubscribers(
  subscribers: EmailSubscriber[],
  tags: string[]
): EmailSubscriber[] {
  return subscribers.map((sub) => ({
    ...sub,
    tags: [...new Set([...(sub.tags || []), ...tags])],
  }));
}

/**
 * Remove tags from subscribers
 */
export function removeTagsFromSubscribers(
  subscribers: EmailSubscriber[],
  tags: string[]
): EmailSubscriber[] {
  return subscribers.map((sub) => ({
    ...sub,
    tags: (sub.tags || []).filter((t) => !tags.includes(t)),
  }));
}

/**
 * Update subscriber segment
 */
export function updateSubscriberSegment(
  subscribers: EmailSubscriber[],
  emails: string[],
  newSegment: EmailSubscriber['segment']
): EmailSubscriber[] {
  const emailSet = new Set(emails.map((e) => e.toLowerCase()));

  return subscribers.map((sub) =>
    emailSet.has(sub.email.toLowerCase()) ? { ...sub, segment: newSegment } : sub
  );
}

/**
 * Unsubscribe subscribers
 */
export function unsubscribeSubscribers(
  subscribers: EmailSubscriber[],
  emails: string[]
): EmailSubscriber[] {
  const emailSet = new Set(emails.map((e) => e.toLowerCase()));

  return subscribers.map((sub) =>
    emailSet.has(sub.email.toLowerCase())
      ? { ...sub, subscribed: false, unsubscribedAt: new Date() }
      : sub
  );
}
