import {
  collection,
  doc,
  getDoc,
  setDoc,
  updateDoc,
  deleteDoc,
  onSnapshot,
  query,
} from 'firebase/firestore';
import emailjs from '@emailjs/browser';
import { db } from '../lib/firebase';
import { getActiveEmailConfig, sendNewsletterSmartEmail } from './emailService';

export type SubscriberSource = 'footer' | 'checkout' | 'admin';
export type SubscriberStatus = 'active' | 'unsubscribed';

export interface NewsletterSubscriber {
  id: string; // Sanitized lowercased email as doc ID
  email: string;
  status: SubscriberStatus;
  source: SubscriberSource;
  subscribedAt: string; // ISO string
  updatedAt: string; // ISO string
  totalEmailsSent: number;
  lastEmailSent: string | null;
  notes?: string;
}

export interface NewsletterEmailHistory {
  id: string;
  subject: string;
  previewText?: string;
  html: string;
  totalRecipients: number;
  successCount: number;
  failedCount: number;
  startedAt: string;
  completedAt: string;
  createdBy: string;
}

const SUBSCRIBERS_STORAGE_KEY = 'tnl_newsletter_subscribers_v1';
const HISTORY_STORAGE_KEY = 'tnl_newsletter_history_v1';

const SUBSCRIBERS_COLLECTION = 'newsletterSubscribers';
const HISTORY_COLLECTION = 'newsletterEmailHistory';

// Default initial subscribers cache
export const INITIAL_SUBSCRIBERS: NewsletterSubscriber[] = [];

let inMemorySubscribers: NewsletterSubscriber[] = [];
let inMemoryHistory: NewsletterEmailHistory[] = [];

// Helper to sanitize doc ID from email
export function getEmailDocId(email: string): string {
  return email.trim().toLowerCase().replace(/[\/\.#$\[\]]/g, '_');
}

export function getStoredSubscribers(): NewsletterSubscriber[] {
  if (inMemorySubscribers.length > 0) return inMemorySubscribers;
  if (typeof window === 'undefined') return [];
  try {
    const raw = localStorage.getItem(SUBSCRIBERS_STORAGE_KEY);
    if (!raw) {
      saveSubscribersLocal([]);
      return [];
    }
    const parsed = JSON.parse(raw) as NewsletterSubscriber[];
    if (!Array.isArray(parsed)) {
      saveSubscribersLocal([]);
      return [];
    }
    inMemorySubscribers = parsed;
    return parsed;
  } catch (err) {
    console.warn('Error reading subscribers from localStorage:', err);
    return [];
  }
}

export function saveSubscribersLocal(list: NewsletterSubscriber[]): void {
  inMemorySubscribers = list;
  if (typeof window === 'undefined') return;
  try {
    localStorage.setItem(SUBSCRIBERS_STORAGE_KEY, JSON.stringify(list));
  } catch (err) {
    console.warn('Error saving subscribers to localStorage:', err);
  }
}

export function getStoredEmailHistory(): NewsletterEmailHistory[] {
  if (inMemoryHistory.length > 0) return inMemoryHistory;
  if (typeof window === 'undefined') return [];
  try {
    const raw = localStorage.getItem(HISTORY_STORAGE_KEY);
    if (raw) {
      const parsed = JSON.parse(raw) as NewsletterEmailHistory[];
      inMemoryHistory = parsed;
      return parsed;
    }
  } catch (err) {
    console.warn('Error reading history from localStorage:', err);
  }
  return [];
}

export function saveEmailHistoryLocal(list: NewsletterEmailHistory[]): void {
  inMemoryHistory = list;
  if (typeof window === 'undefined') return;
  try {
    localStorage.setItem(HISTORY_STORAGE_KEY, JSON.stringify(list));
  } catch (err) {
    console.warn('Error saving history to localStorage:', err);
  }
}

// Real-time Firestore Subscriptions
export function subscribeToSubscribers(callback: (list: NewsletterSubscriber[]) => void): () => void {
  callback(getStoredSubscribers());
  try {
    const q = query(collection(db, SUBSCRIBERS_COLLECTION));
    const unsub = onSnapshot(
      q,
      (snapshot) => {
        const fireMap = new Map<string, NewsletterSubscriber>();
        snapshot.forEach((docSnap) => {
          const data = docSnap.data() as NewsletterSubscriber;
          const id = docSnap.id || getEmailDocId(data.email);
          if (data.email) {
            fireMap.set(id, {
              id,
              email: data.email.toLowerCase().trim(),
              status: data.status || 'active',
              source: data.source || 'footer',
              subscribedAt: data.subscribedAt || new Date().toISOString(),
              updatedAt: data.updatedAt || new Date().toISOString(),
              totalEmailsSent: Number(data.totalEmailsSent) || 0,
              lastEmailSent: data.lastEmailSent || null,
              notes: data.notes || '',
            });
          }
        });

        const localList = getStoredSubscribers();
        const mergedMap = new Map<string, NewsletterSubscriber>();
        localList.forEach((s) => mergedMap.set(s.id, s));
        fireMap.forEach((s, id) => mergedMap.set(id, s));

        const result = Array.from(mergedMap.values());
        result.sort((a, b) => new Date(b.subscribedAt).getTime() - new Date(a.subscribedAt).getTime());

        saveSubscribersLocal(result);
        callback(result);
      },
      (err) => {
        console.warn('Firestore subscriber subscription error:', err);
        callback(getStoredSubscribers());
      }
    );
    return unsub;
  } catch (err) {
    console.warn('Failed subscribing to newsletter subscribers:', err);
    return () => {};
  }
}

export function subscribeToEmailHistory(callback: (list: NewsletterEmailHistory[]) => void): () => void {
  callback(getStoredEmailHistory());
  try {
    const q = query(collection(db, HISTORY_COLLECTION));
    const unsub = onSnapshot(
      q,
      (snapshot) => {
        const list: NewsletterEmailHistory[] = [];
        snapshot.forEach((docSnap) => {
          list.push({ ...docSnap.data(), id: docSnap.id } as NewsletterEmailHistory);
        });
        list.sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
        saveEmailHistoryLocal(list);
        callback(list);
      },
      (err) => {
        console.warn('Firestore email history subscription error:', err);
        callback(getStoredEmailHistory());
      }
    );
    return unsub;
  } catch (err) {
    console.warn('Failed subscribing to email history:', err);
    return () => {};
  }
}

// Subscribe Newsletter Action with Duplicate Protection
export async function subscribeNewsletter(
  rawEmail: string,
  source: SubscriberSource = 'footer',
  notes: string = ''
): Promise<{ success: boolean; message: string; isNew: boolean }> {
  const email = rawEmail.trim().toLowerCase();
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  if (!email || !emailRegex.test(email)) {
    return { success: false, message: 'Please enter a valid email address.', isNew: false };
  }

  const docId = getEmailDocId(email);
  const currentLocal = getStoredSubscribers();
  const existingLocal = currentLocal.find((s) => s.email === email || s.id === docId);

  // Check Firestore directly for double guarantee
  try {
    const docRef = doc(db, SUBSCRIBERS_COLLECTION, docId);
    const docSnap = await getDoc(docRef);

    if (docSnap.exists() || existingLocal) {
      const existingData = docSnap.exists() ? (docSnap.data() as NewsletterSubscriber) : existingLocal!;
      if (existingData.status === 'unsubscribed') {
        // Re-activate if previously unsubscribed
        const updated: NewsletterSubscriber = {
          ...existingData,
          status: 'active',
          updatedAt: new Date().toISOString(),
          notes: notes || existingData.notes || '',
        };
        saveSubscribersLocal(currentLocal.map((s) => (s.id === docId ? updated : s)));
        await setDoc(docRef, updated, { merge: true });
        return { success: true, message: 'Welcome back! Your subscription has been re-activated.', isNew: false };
      }
      return { success: true, message: 'You are already subscribed to our newsletter!', isNew: false };
    }
  } catch (err) {
    console.warn('Firestore check error during subscription:', err);
    if (existingLocal) {
      return { success: true, message: 'You are already subscribed to our newsletter!', isNew: false };
    }
  }

  const now = new Date().toISOString();
  const newSubscriber: NewsletterSubscriber = {
    id: docId,
    email,
    status: 'active',
    source,
    subscribedAt: now,
    updatedAt: now,
    totalEmailsSent: 0,
    lastEmailSent: null,
    notes,
  };

  saveSubscribersLocal([newSubscriber, ...currentLocal]);

  try {
    const docRef = doc(db, SUBSCRIBERS_COLLECTION, docId);
    await setDoc(docRef, newSubscriber);
  } catch (err) {
    console.warn('Failed to save subscriber to Firestore:', err);
  }

  // Trigger automated email dispatch using separate newsletter credentials
  try {
    await fetch('/api/newsletter/subscribe', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email }),
    });
  } catch (err) {
    console.warn('Newsletter automation API call failed:', err);
  }

  return { success: true, message: 'Thank you for subscribing to Time N Life!', isNew: true };
}

// Auto Subscribe from Checkout
export async function subscribeFromCheckout(rawEmail: string): Promise<void> {
  if (!rawEmail) return;
  try {
    await subscribeNewsletter(rawEmail, 'checkout', 'Subscribed during checkout');
  } catch (err) {
    console.warn('Silent failure subscribing from checkout:', err);
  }
}

// Update status
export async function updateSubscriberStatus(docId: string, status: SubscriberStatus): Promise<void> {
  const list = getStoredSubscribers();
  const updated = list.map((s) => (s.id === docId ? { ...s, status, updatedAt: new Date().toISOString() } : s));
  saveSubscribersLocal(updated);

  try {
    const docRef = doc(db, SUBSCRIBERS_COLLECTION, docId);
    await setDoc(docRef, { status, updatedAt: new Date().toISOString() }, { merge: true });
  } catch (err) {
    console.warn('Error updating subscriber status:', err);
  }
}

// Update notes
export async function updateSubscriberNotes(docId: string, notes: string): Promise<void> {
  const list = getStoredSubscribers();
  const updated = list.map((s) => (s.id === docId ? { ...s, notes, updatedAt: new Date().toISOString() } : s));
  saveSubscribersLocal(updated);

  try {
    const docRef = doc(db, SUBSCRIBERS_COLLECTION, docId);
    await setDoc(docRef, { notes, updatedAt: new Date().toISOString() }, { merge: true });
  } catch (err) {
    console.warn('Error updating subscriber notes:', err);
  }
}

// Delete subscriber
export async function deleteSubscriber(docId: string): Promise<void> {
  const list = getStoredSubscribers().filter((s) => s.id !== docId);
  saveSubscribersLocal(list);

  try {
    const docRef = doc(db, SUBSCRIBERS_COLLECTION, docId);
    await deleteDoc(docRef);
  } catch (err) {
    console.warn('Error deleting subscriber from Firestore:', err);
  }
}

// Record Email History
export async function recordEmailHistory(history: Omit<NewsletterEmailHistory, 'id'>): Promise<NewsletterEmailHistory> {
  const id = `HIST-${Date.now()}-${Math.floor(Math.random() * 1000)}`;
  const record: NewsletterEmailHistory = { ...history, id };
  const current = getStoredEmailHistory();
  saveEmailHistoryLocal([record, ...current]);

  try {
    const docRef = doc(db, HISTORY_COLLECTION, id);
    await setDoc(docRef, record);
  } catch (err) {
    console.warn('Error saving email history to Firestore:', err);
  }

  return record;
}

// Bulk Email Sender Function using existing EmailJS Config
export async function sendBulkNewsletter(
  recipients: NewsletterSubscriber[],
  subject: string,
  htmlContent: string,
  onProgress?: (sentCount: number, total: number, failedCount: number) => void
): Promise<{ successCount: number; failedCount: number }> {
  const config = await getActiveEmailConfig();
  if (config.publicKey) {
    emailjs.init(config.publicKey);
  }

  let successCount = 0;
  let failedCount = 0;
  const total = recipients.length;
  const startedAt = new Date().toISOString();

  for (let i = 0; i < total; i++) {
    const sub = recipients[i];

    // Skip invalid or unsubscribed
    if (!sub.email || !sub.email.includes('@') || sub.status !== 'active') {
      failedCount++;
      if (onProgress) onProgress(successCount, total, failedCount);
      continue;
    }

    try {
      const templateParams = {
        to_email: sub.email,
        to_name: sub.email.split('@')[0] || 'Valued Subscriber',
        subject: subject,
        message: htmlContent,
        message_html: htmlContent,
      };

      const sentSuccess = await sendNewsletterSmartEmail(templateParams, config);
      if (sentSuccess) {
        successCount++;
        // Update subscriber stats in Firestore
        const now = new Date().toISOString();
        const updatedTotal = (sub.totalEmailsSent || 0) + 1;
        const docRef = doc(db, SUBSCRIBERS_COLLECTION, sub.id);
        updateDoc(docRef, { totalEmailsSent: updatedTotal, lastEmailSent: now }).catch(() => {});
      } else {
        failedCount++;
      }
    } catch (err) {
      console.warn(`Failed sending newsletter to ${sub.email}:`, err);
      failedCount++;
    }

    if (onProgress) {
      onProgress(successCount, total, failedCount);
    }

    // Small delay between sends to prevent rate limits
    if (i < total - 1) {
      await new Promise((res) => setTimeout(res, 200));
    }
  }

  const completedAt = new Date().toISOString();

  // Store history
  await recordEmailHistory({
    subject,
    html: htmlContent,
    totalRecipients: total,
    successCount,
    failedCount,
    startedAt,
    completedAt,
    createdBy: 'Time N Life Admin',
  });

  return { successCount, failedCount };
}
