// ==================== CACHED EMAIL SERVICE ====================
// Service für E-Mail-Caching und Vertragszuordnung

import { CachedEmail, Prisma, EmailFolder } from '@prisma/client';
import prisma from '../lib/prisma.js';
import { decrypt } from '../utils/encryption.js';
import { fetchEmails, ImapCredentials, FetchedEmail, moveToTrash, restoreFromTrash, permanentDelete, humanizeImapError, findJunkFolderPath } from './imapService.js';
import { getImapSmtpSettings } from './emailProvider/emailProviderService.js';

// ==================== TYPES ====================

export interface CachedEmailWithRelations extends CachedEmail {
  stressfreiEmail?: {
    id: number;
    email: string;
    customerId: number;
  };
  contract?: {
    id: number;
    contractNumber: string;
  } | null;
}

// Parameter für gesendete E-Mail
export interface SentEmailParams {
  to: string[];
  cc?: string[];
  subject: string;
  text?: string;
  html?: string;
  messageId: string;
  contractId?: number; // Optional: Vertrag dem die E-Mail zugeordnet wird
  attachmentNames?: string[]; // Namen der Anhänge
  uid?: number; // UID im IMAP Sent-Ordner (für Attachment-Download)
}

export interface SyncResult {
  success: boolean;
  newEmails: number;
  totalEmails: number;
  error?: string;
}

export interface EmailListOptions {
  stressfreiEmailId?: number;
  customerId?: number;
  contractId?: number;
  folder?: string;
  limit?: number;
  offset?: number;
  includeBody?: boolean;
  // Suche / Filter (alle AND-verknüpft)
  search?: string;                // Volltextsuche über subject + from + body
  fromFilter?: string;            // Absender enthält
  toFilter?: string;              // Empfänger enthält
  subjectFilter?: string;         // Subject enthält
  bodyFilter?: string;            // Body enthält (text/html)
  attachmentNameFilter?: string;  // Anhang-Dateiname enthält
  hasAttachments?: boolean;       // Nur mit/ohne Anhang
  isRead?: boolean;               // Gelesen-Status
  isStarred?: boolean;            // Markiert-Status
  receivedFrom?: Date;            // Empfangen ab
  receivedTo?: Date;              // Empfangen bis
}

// ==================== SYNC FUNCTIONS ====================

// E-Mails für eine StressfreiEmail synchronisieren
export async function syncEmailsForAccount(
  stressfreiEmailId: number,
  options?: { folder?: string; fullSync?: boolean; dbFolder?: EmailFolder }
): Promise<SyncResult> {
  const folder = options?.folder || 'INBOX';
  const fullSync = options?.fullSync || false;

  try {
    // StressfreiEmail mit Mailbox-Daten laden
    const stressfreiEmail = await prisma.stressfreiEmail.findUnique({
      where: { id: stressfreiEmailId },
    });

    if (!stressfreiEmail) {
      return { success: false, newEmails: 0, totalEmails: 0, error: 'StressfreiEmail nicht gefunden' };
    }

    if (!stressfreiEmail.hasMailbox || !stressfreiEmail.emailPasswordEncrypted) {
      return { success: false, newEmails: 0, totalEmails: 0, error: 'Keine Mailbox für diese E-Mail-Adresse' };
    }

    // IMAP/SMTP-Einstellungen vom Provider holen
    const settings = await getImapSmtpSettings();
    if (!settings) {
      return { success: false, newEmails: 0, totalEmails: 0, error: 'Keine E-Mail-Provider-Einstellungen gefunden' };
    }

    // Passwort entschlüsseln
    let password: string;
    try {
      password = decrypt(stressfreiEmail.emailPasswordEncrypted);
    } catch {
      return { success: false, newEmails: 0, totalEmails: 0, error: 'Passwort konnte nicht entschlüsselt werden' };
    }

    // IMAP-Credentials zusammenstellen
    const credentials: ImapCredentials = {
      host: settings.imapServer,
      port: settings.imapPort,
      user: stressfreiEmail.email,
      password,
      encryption: settings.imapEncryption,
      allowSelfSignedCerts: settings.allowSelfSignedCerts,
    };

    // Folder-Mapping: IMAP-Ordner zu DB-Ordner. Explizites dbFolder (z.B.
    // SPAM für den Junk-Ordner, dessen IMAP-Name variiert) hat Vorrang.
    const dbFolder = options?.dbFolder
      ?? (folder.toUpperCase() === 'SENT' || folder.toLowerCase() === 'sent'
        ? EmailFolder.SENT
        : EmailFolder.INBOX);

    // Für inkrementellen Sync: Höchste UID des Ordners ermitteln
    let sinceUid: number | undefined;
    if (!fullSync) {
      const lastEmail = await prisma.cachedEmail.findFirst({
        where: { stressfreiEmailId, folder: dbFolder },
        orderBy: { uid: 'desc' },
        select: { uid: true },
      });
      if (lastEmail) {
        sinceUid = lastEmail.uid;
      }
    }

    // E-Mails vom IMAP-Server abrufen
    const fetchedEmails = await fetchEmails(credentials, {
      folder,
      sinceUid,
      limit: fullSync ? 500 : 100, // Mehr bei Full-Sync
    });

    // Neue E-Mails in DB speichern
    let newCount = 0;
    for (const email of fetchedEmails) {
      const created = await upsertCachedEmail(stressfreiEmailId, email, dbFolder);
      if (created) newCount++;
    }

    // Gesamtzahl ermitteln
    const totalEmails = await prisma.cachedEmail.count({
      where: { stressfreiEmailId },
    });

    return {
      success: true,
      newEmails: newCount,
      totalEmails,
    };
  } catch (error) {
    console.error('syncEmailsForAccount error:', error);
    // humanizeImapError zieht die eigentliche Server-Antwort aus dem
    // imapflow-Error und erkennt insbesondere Auth-Fehler ("Passwort
    // stimmt nicht mehr") mit klarer Handlungsanweisung – vorher sah
    // der User im Sync-Toast nur "Command failed".
    return {
      success: false,
      newEmails: 0,
      totalEmails: 0,
      error: humanizeImapError(error),
    };
  }
}

/**
 * Baut die IMAP-Credentials für ein Postfach (für Operationen, die eine
 * eigene Verbindung brauchen – z.B. Junk-Ordner-Pfad ermitteln). Gibt null
 * zurück, wenn kein Postfach/Passwort/Provider-Settings vorhanden sind.
 */
async function getImapCredentialsForAccount(stressfreiEmailId: number): Promise<ImapCredentials | null> {
  const stressfreiEmail = await prisma.stressfreiEmail.findUnique({ where: { id: stressfreiEmailId } });
  if (!stressfreiEmail?.hasMailbox || !stressfreiEmail.emailPasswordEncrypted) return null;
  const settings = await getImapSmtpSettings();
  if (!settings) return null;
  let password: string;
  try {
    password = decrypt(stressfreiEmail.emailPasswordEncrypted);
  } catch {
    return null;
  }
  return {
    host: settings.imapServer,
    port: settings.imapPort,
    user: stressfreiEmail.email,
    password,
    encryption: settings.imapEncryption,
    allowSelfSignedCerts: settings.allowSelfSignedCerts,
  };
}

// Alle Ordner synchronisieren (INBOX + SENT + SPAM/Junk)
export async function syncAllFoldersForAccount(
  stressfreiEmailId: number,
  options?: { fullSync?: boolean }
): Promise<SyncResult> {
  const fullSync = options?.fullSync || false;

  // INBOX synchronisieren
  const inboxResult = await syncEmailsForAccount(stressfreiEmailId, { folder: 'INBOX', fullSync });

  // SENT synchronisieren (Plesk verwendet "Sent" als Ordnername)
  const sentResult = await syncEmailsForAccount(stressfreiEmailId, { folder: 'Sent', fullSync });

  // SPAM/Junk synchronisieren – Ordnername variiert je Server, daher erst
  // per IMAP ermitteln. Existiert kein Junk-Ordner, wird Spam übersprungen
  // (kein Fehler). Wird explizit als dbFolder=SPAM abgelegt.
  let spamNew = 0;
  const credentials = await getImapCredentialsForAccount(stressfreiEmailId);
  if (credentials) {
    const junkPath = await findJunkFolderPath(credentials);
    if (junkPath) {
      const spamResult = await syncEmailsForAccount(stressfreiEmailId, {
        folder: junkPath,
        dbFolder: EmailFolder.SPAM,
        fullSync,
      });
      if (spamResult.success) spamNew = spamResult.newEmails;
    }
  }

  // Ergebnisse kombinieren
  if (!inboxResult.success && !sentResult.success) {
    return {
      success: false,
      newEmails: 0,
      totalEmails: 0,
      error: inboxResult.error || sentResult.error || 'Synchronisation fehlgeschlagen',
    };
  }

  return {
    success: true,
    newEmails: inboxResult.newEmails + sentResult.newEmails + spamNew,
    totalEmails: inboxResult.totalEmails,
  };
}

// Einzelne E-Mail in DB speichern/aktualisieren
async function upsertCachedEmail(
  stressfreiEmailId: number,
  email: FetchedEmail,
  folder: EmailFolder = EmailFolder.INBOX
): Promise<boolean> {
  try {
    // Prüfen ob bereits vorhanden (via messageId + folder)
    // WICHTIG: Gleiche messageId kann in INBOX und SENT existieren (z.B. E-Mail an sich selbst)
    const existing = await prisma.cachedEmail.findUnique({
      where: {
        stressfreiEmailId_messageId_folder: {
          stressfreiEmailId,
          messageId: email.messageId,
          folder,
        },
      },
    });

    if (existing) {
      // Bereits vorhanden
      return false;
    }

    // Neue E-Mail anlegen
    await prisma.cachedEmail.create({
      data: {
        stressfreiEmailId,
        folder,
        messageId: email.messageId,
        uid: email.uid,
        subject: email.subject,
        fromAddress: email.fromAddress,
        fromName: email.fromName,
        toAddresses: JSON.stringify(email.toAddresses),
        ccAddresses: email.ccAddresses.length > 0 ? JSON.stringify(email.ccAddresses) : null,
        receivedAt: email.date,
        textBody: email.textBody,
        htmlBody: email.htmlBody,
        hasAttachments: email.hasAttachments,
        attachmentNames: email.attachmentNames.length > 0
          ? JSON.stringify(email.attachmentNames)
          : null,
        isRead: folder === EmailFolder.SENT, // Gesendete E-Mails sind bereits gelesen
        isStarred: false,
      },
    });

    return true;
  } catch (error) {
    // Duplikat-Fehler ignorieren (Race Condition)
    if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === 'P2002') {
      return false;
    }
    throw error;
  }
}

// ==================== CRUD FUNCTIONS ====================

// E-Mails abrufen mit Optionen
export async function getCachedEmails(
  options: EmailListOptions
): Promise<CachedEmailWithRelations[]> {
  const where: Prisma.CachedEmailWhereInput = {
    isDeleted: false, // Gelöschte E-Mails ausschließen
  };

  if (options.stressfreiEmailId) {
    where.stressfreiEmailId = options.stressfreiEmailId;
  }

  if (options.customerId) {
    where.stressfreiEmail = {
      customerId: options.customerId,
    };
  }

  if (options.contractId) {
    where.contractId = options.contractId;
  }

  // Folder-Filter (INBOX, SENT oder SPAM). Unbekannte/fehlende Werte
  // defaulten bewusst auf INBOX – sonst bliebe where.folder ungesetzt und
  // die Abfrage mischte alle Ordner des Postfachs.
  if (options.folder === 'SENT') {
    where.folder = EmailFolder.SENT;
  } else if (options.folder === 'SPAM') {
    where.folder = EmailFolder.SPAM;
  } else {
    where.folder = EmailFolder.INBOX;
  }

  // ===== Such-/Filter-Parameter =====
  // Volltext-Quicksearch: durchsucht parallel Subject, From-Address/Name und
  // Body. MariaDB `contains` ist case-insensitive bei utf8mb4_unicode_ci.
  if (options.search && options.search.trim()) {
    const q = options.search.trim();
    where.OR = [
      { subject: { contains: q } },
      { fromAddress: { contains: q } },
      { fromName: { contains: q } },
      { textBody: { contains: q } },
    ];
  }

  // Feldspezifische Filter (alle AND-verknüpft mit dem Rest)
  if (options.fromFilter?.trim()) {
    const q = options.fromFilter.trim();
    // Treffer in fromAddress ODER fromName – für den Nutzer ist „Von" beides
    where.AND = [
      ...(Array.isArray(where.AND) ? where.AND : where.AND ? [where.AND] : []),
      { OR: [{ fromAddress: { contains: q } }, { fromName: { contains: q } }] },
    ];
  }
  if (options.toFilter?.trim()) {
    where.toAddresses = { contains: options.toFilter.trim() };
  }
  if (options.subjectFilter?.trim()) {
    where.subject = { contains: options.subjectFilter.trim() };
  }
  if (options.bodyFilter?.trim()) {
    const q = options.bodyFilter.trim();
    where.AND = [
      ...(Array.isArray(where.AND) ? where.AND : where.AND ? [where.AND] : []),
      { OR: [{ textBody: { contains: q } }, { htmlBody: { contains: q } }] },
    ];
  }
  if (options.attachmentNameFilter?.trim()) {
    where.attachmentNames = { contains: options.attachmentNameFilter.trim() };
  }
  if (typeof options.hasAttachments === 'boolean') {
    where.hasAttachments = options.hasAttachments;
  }
  if (typeof options.isRead === 'boolean') {
    where.isRead = options.isRead;
  }
  if (typeof options.isStarred === 'boolean') {
    where.isStarred = options.isStarred;
  }
  if (options.receivedFrom || options.receivedTo) {
    where.receivedAt = {};
    if (options.receivedFrom) (where.receivedAt as Prisma.DateTimeFilter).gte = options.receivedFrom;
    if (options.receivedTo) (where.receivedAt as Prisma.DateTimeFilter).lte = options.receivedTo;
  }

  // Body-Felder nur wenn explizit angefordert (spart Bandbreite)
  const select: Prisma.CachedEmailSelect = {
    id: true,
    stressfreiEmailId: true,
    folder: true,
    messageId: true,
    uid: true,
    subject: true,
    fromAddress: true,
    fromName: true,
    toAddresses: true,
    ccAddresses: true,
    receivedAt: true,
    hasAttachments: true,
    attachmentNames: true,
    contractId: true,
    assignedAt: true,
    assignedBy: true,
    isAutoAssigned: true,
    isRead: true,
    isStarred: true,
    createdAt: true,
    updatedAt: true,
    stressfreiEmail: {
      select: {
        id: true,
        email: true,
        customerId: true,
      },
    },
    contract: {
      select: {
        id: true,
        contractNumber: true,
      },
    },
  };

  if (options.includeBody) {
    select.textBody = true;
    select.htmlBody = true;
  }

  const emails = await prisma.cachedEmail.findMany({
    where,
    select,
    orderBy: { receivedAt: 'desc' },
    take: options.limit || 50,
    skip: options.offset || 0,
  });

  return emails as CachedEmailWithRelations[];
}

// Einzelne E-Mail abrufen (mit Body)
export async function getCachedEmailById(
  id: number
): Promise<CachedEmailWithRelations | null> {
  const email = await prisma.cachedEmail.findUnique({
    where: { id },
    include: {
      stressfreiEmail: {
        select: {
          id: true,
          email: true,
          customerId: true,
        },
      },
      contract: {
        select: {
          id: true,
          contractNumber: true,
        },
      },
    },
  });

  return email as CachedEmailWithRelations | null;
}

// E-Mail als gelesen markieren
export async function markEmailAsRead(id: number): Promise<void> {
  await prisma.cachedEmail.update({
    where: { id },
    data: { isRead: true },
  });
}

// E-Mail als ungelesen markieren
export async function markEmailAsUnread(id: number): Promise<void> {
  await prisma.cachedEmail.update({
    where: { id },
    data: { isRead: false },
  });
}

// E-Mail Stern setzen/entfernen
export async function toggleEmailStar(id: number): Promise<boolean> {
  const email = await prisma.cachedEmail.findUnique({
    where: { id },
    select: { isStarred: true },
  });

  if (!email) {
    throw new Error('E-Mail nicht gefunden');
  }

  const newValue = !email.isStarred;
  await prisma.cachedEmail.update({
    where: { id },
    data: { isStarred: newValue },
  });

  return newValue;
}

// ==================== CONTRACT ASSIGNMENT ====================

// E-Mail einem Vertrag zuordnen
export async function assignEmailToContract(
  emailId: number,
  contractId: number,
  userId?: number
): Promise<CachedEmailWithRelations> {
  // Prüfen ob E-Mail existiert
  const email = await prisma.cachedEmail.findUnique({
    where: { id: emailId },
  });

  if (!email) {
    throw new Error('E-Mail nicht gefunden');
  }

  // Prüfen ob Vertrag existiert
  const contract = await prisma.contract.findUnique({
    where: { id: contractId },
  });

  if (!contract) {
    throw new Error('Vertrag nicht gefunden');
  }

  // Zuordnung setzen (manuell)
  const updated = await prisma.cachedEmail.update({
    where: { id: emailId },
    data: {
      contractId,
      assignedAt: new Date(),
      assignedBy: userId || null,
      isAutoAssigned: false, // Manuell zugeordnet
    },
    include: {
      stressfreiEmail: {
        select: {
          id: true,
          email: true,
          customerId: true,
        },
      },
      contract: {
        select: {
          id: true,
          contractNumber: true,
        },
      },
    },
  });

  return updated as CachedEmailWithRelations;
}

// Vertragszuordnung aufheben
export async function unassignEmailFromContract(
  emailId: number
): Promise<CachedEmailWithRelations> {
  const updated = await prisma.cachedEmail.update({
    where: { id: emailId },
    data: {
      contractId: null,
      assignedAt: null,
      assignedBy: null,
    },
    include: {
      stressfreiEmail: {
        select: {
          id: true,
          email: true,
          customerId: true,
        },
      },
      contract: {
        select: {
          id: true,
          contractNumber: true,
        },
      },
    },
  });

  return updated as CachedEmailWithRelations;
}

// ==================== HELPER FUNCTIONS ====================

// Anzahl ungelesener E-Mails für Kunde
export async function getUnreadCountForCustomer(customerId: number): Promise<number> {
  return prisma.cachedEmail.count({
    where: {
      stressfreiEmail: {
        customerId,
      },
      isRead: false,
    },
  });
}

// Anzahl ungelesener E-Mails für Vertrag
export async function getUnreadCountForContract(contractId: number): Promise<number> {
  return prisma.cachedEmail.count({
    where: {
      contractId,
      isRead: false,
    },
  });
}

// E-Mail-Anzahl pro Ordner für ein Konto (total und ungelesen)
export async function getFolderCountsForAccount(stressfreiEmailId: number): Promise<{
  inbox: number;
  inboxUnread: number;
  sent: number;
  sentUnread: number;
  spam: number;
  spamUnread: number;
  trash: number;
  trashUnread: number;
}> {
  const [inbox, inboxUnread, sent, sentUnread, spam, spamUnread, trash, trashUnread] = await Promise.all([
    // INBOX total
    prisma.cachedEmail.count({
      where: { stressfreiEmailId, folder: EmailFolder.INBOX, isDeleted: false },
    }),
    // INBOX unread
    prisma.cachedEmail.count({
      where: { stressfreiEmailId, folder: EmailFolder.INBOX, isDeleted: false, isRead: false },
    }),
    // SENT total
    prisma.cachedEmail.count({
      where: { stressfreiEmailId, folder: EmailFolder.SENT, isDeleted: false },
    }),
    // SENT unread
    prisma.cachedEmail.count({
      where: { stressfreiEmailId, folder: EmailFolder.SENT, isDeleted: false, isRead: false },
    }),
    // SPAM total
    prisma.cachedEmail.count({
      where: { stressfreiEmailId, folder: EmailFolder.SPAM, isDeleted: false },
    }),
    // SPAM unread
    prisma.cachedEmail.count({
      where: { stressfreiEmailId, folder: EmailFolder.SPAM, isDeleted: false, isRead: false },
    }),
    // TRASH total (isDeleted = true)
    prisma.cachedEmail.count({
      where: { stressfreiEmailId, isDeleted: true },
    }),
    // TRASH unread
    prisma.cachedEmail.count({
      where: { stressfreiEmailId, isDeleted: true, isRead: false },
    }),
  ]);

  return { inbox, inboxUnread, sent, sentUnread, spam, spamUnread, trash, trashUnread };
}

// E-Mail-Anzahl pro Ordner für einen Vertrag (zugeordnete E-Mails).
// Optional auf ein bestimmtes Postfach einschränken. Bug 2026-06-21:
// vorher zählten die Badges Mails aus ALLEN Postfächern, während die
// Liste (nach Fix) nur die des ausgewählten Postfachs zeigt – Badge
// und Liste liefen auseinander. Trash mit reingenommen, weil der
// Contract-Trash-Badge sonst wieder auf account-globalen Zähler
// zurückfallen müsste.
export async function getFolderCountsForContract(
  contractId: number,
  stressfreiEmailId?: number,
): Promise<{
  inbox: number;
  inboxUnread: number;
  sent: number;
  sentUnread: number;
  trash: number;
  trashUnread: number;
}> {
  const baseWhere: Prisma.CachedEmailWhereInput = { contractId };
  if (stressfreiEmailId) baseWhere.stressfreiEmailId = stressfreiEmailId;
  const [inbox, inboxUnread, sent, sentUnread, trash, trashUnread] = await Promise.all([
    prisma.cachedEmail.count({ where: { ...baseWhere, folder: EmailFolder.INBOX, isDeleted: false } }),
    prisma.cachedEmail.count({ where: { ...baseWhere, folder: EmailFolder.INBOX, isDeleted: false, isRead: false } }),
    prisma.cachedEmail.count({ where: { ...baseWhere, folder: EmailFolder.SENT, isDeleted: false } }),
    prisma.cachedEmail.count({ where: { ...baseWhere, folder: EmailFolder.SENT, isDeleted: false, isRead: false } }),
    prisma.cachedEmail.count({ where: { ...baseWhere, isDeleted: true } }),
    prisma.cachedEmail.count({ where: { ...baseWhere, isDeleted: true, isRead: false } }),
  ]);
  return { inbox, inboxUnread, sent, sentUnread, trash, trashUnread };
}

// Alle StressfreiEmails eines Kunden mit Mailbox
export async function getMailboxAccountsForCustomer(customerId: number) {
  return prisma.stressfreiEmail.findMany({
    where: {
      customerId,
      hasMailbox: true,
    },
    select: {
      id: true,
      email: true,
      notes: true,
      _count: {
        select: {
          cachedEmails: true,
        },
      },
    },
    orderBy: { email: 'asc' },
  });
}

// E-Mail-Thread finden (basierend auf References/In-Reply-To)
export async function getEmailThread(emailId: number): Promise<CachedEmailWithRelations[]> {
  const email = await prisma.cachedEmail.findUnique({
    where: { id: emailId },
  });

  if (!email) {
    return [];
  }

  // Suche nach E-Mails mit dem gleichen Betreff (vereinfachte Thread-Logik)
  // In einer vollständigen Implementierung würde man References/In-Reply-To parsen
  const baseSubject = email.subject?.replace(/^(Re|Fwd|Aw|Wg):\s*/gi, '') || '';

  if (!baseSubject) {
    return [email as CachedEmailWithRelations];
  }

  const thread = await prisma.cachedEmail.findMany({
    where: {
      stressfreiEmailId: email.stressfreiEmailId,
      OR: [
        { subject: baseSubject },
        { subject: { startsWith: `Re: ${baseSubject}` } },
        { subject: { startsWith: `Aw: ${baseSubject}` } },
        { subject: { startsWith: `Fwd: ${baseSubject}` } },
        { subject: { startsWith: `Wg: ${baseSubject}` } },
      ],
    },
    include: {
      stressfreiEmail: {
        select: {
          id: true,
          email: true,
          customerId: true,
        },
      },
      contract: {
        select: {
          id: true,
          contractNumber: true,
        },
      },
    },
    orderBy: { receivedAt: 'asc' },
  });

  return thread as CachedEmailWithRelations[];
}

// ==================== TRASH OPERATIONS ====================

export interface TrashOperationResult {
  success: boolean;
  error?: string;
}

// E-Mail in Papierkorb verschieben (markiert als gelöscht + IMAP-Move)
export async function moveEmailToTrash(id: number): Promise<TrashOperationResult> {
  // E-Mail mit StressfreiEmail laden
  const email = await prisma.cachedEmail.findUnique({
    where: { id },
    include: {
      stressfreiEmail: true,
    },
  });

  if (!email) {
    return { success: false, error: 'E-Mail nicht gefunden' };
  }

  if (email.isDeleted) {
    return { success: false, error: 'E-Mail ist bereits im Papierkorb' };
  }

  // IMAP-Einstellungen und Credentials laden
  const settings = await getImapSmtpSettings();
  if (!settings) {
    return { success: false, error: 'Keine E-Mail-Provider-Einstellungen' };
  }

  if (!email.stressfreiEmail.emailPasswordEncrypted) {
    return { success: false, error: 'Keine Mailbox-Zugangsdaten' };
  }

  let password: string;
  try {
    password = decrypt(email.stressfreiEmail.emailPasswordEncrypted);
  } catch {
    return { success: false, error: 'Passwort konnte nicht entschlüsselt werden' };
  }

  const credentials: ImapCredentials = {
    host: settings.imapServer,
    port: settings.imapPort,
    user: email.stressfreiEmail.email,
    password,
    encryption: settings.imapEncryption,
    allowSelfSignedCerts: settings.allowSelfSignedCerts,
  };

  // IMAP-Quellordner bestimmen. Bei SPAM den tatsächlichen Junk-Pfad
  // ermitteln (Name variiert je Server) – sonst würde moveToTrash im
  // falschen Ordner nach der UID suchen.
  let sourceFolder: string;
  if (email.folder === 'SENT') {
    sourceFolder = 'Sent';
  } else if (email.folder === 'SPAM') {
    const junkPath = await findJunkFolderPath(credentials);
    if (!junkPath) {
      return { success: false, error: 'Spam-/Junk-Ordner nicht gefunden – kann nicht in den Papierkorb verschieben' };
    }
    sourceFolder = junkPath;
  } else {
    sourceFolder = 'INBOX';
  }

  // Auf IMAP-Server in Trash verschieben
  const imapResult = await moveToTrash(credentials, email.uid, sourceFolder);

  if (!imapResult.success) {
    return { success: false, error: imapResult.error || 'IMAP-Fehler beim Verschieben' };
  }

  // In DB als gelöscht markieren (mit neuer UID im Trash)
  await prisma.cachedEmail.update({
    where: { id },
    data: {
      isDeleted: true,
      deletedAt: new Date(),
      uid: imapResult.newUid || email.uid, // Neue UID im Trash speichern
    },
  });

  return { success: true };
}

// E-Mail aus Papierkorb wiederherstellen
export async function restoreEmailFromTrash(id: number): Promise<TrashOperationResult> {
  // E-Mail laden
  const email = await prisma.cachedEmail.findUnique({
    where: { id },
    include: {
      stressfreiEmail: true,
    },
  });

  if (!email) {
    return { success: false, error: 'E-Mail nicht gefunden' };
  }

  if (!email.isDeleted) {
    return { success: false, error: 'E-Mail ist nicht im Papierkorb' };
  }

  // IMAP-Einstellungen und Credentials
  const settings = await getImapSmtpSettings();
  if (!settings) {
    return { success: false, error: 'Keine E-Mail-Provider-Einstellungen' };
  }

  if (!email.stressfreiEmail.emailPasswordEncrypted) {
    return { success: false, error: 'Keine Mailbox-Zugangsdaten' };
  }

  let password: string;
  try {
    password = decrypt(email.stressfreiEmail.emailPasswordEncrypted);
  } catch {
    return { success: false, error: 'Passwort konnte nicht entschlüsselt werden' };
  }

  const credentials: ImapCredentials = {
    host: settings.imapServer,
    port: settings.imapPort,
    user: email.stressfreiEmail.email,
    password,
    encryption: settings.imapEncryption,
    allowSelfSignedCerts: settings.allowSelfSignedCerts,
  };

  // Ziel-Ordner bestimmen (basierend auf originalem Ordner). SPAM zurück
  // in den tatsächlichen Junk-Ordner (Name variiert je Server).
  let targetFolder: string;
  if (email.folder === 'SENT') {
    targetFolder = 'Sent';
  } else if (email.folder === 'SPAM') {
    const junkPath = await findJunkFolderPath(credentials);
    if (!junkPath) {
      return { success: false, error: 'Spam-/Junk-Ordner nicht gefunden – kann nicht wiederherstellen' };
    }
    targetFolder = junkPath;
  } else {
    targetFolder = 'INBOX';
  }

  // Auf IMAP-Server aus Trash wiederherstellen
  const imapResult = await restoreFromTrash(credentials, email.uid, targetFolder);

  if (!imapResult.success) {
    return { success: false, error: imapResult.error || 'IMAP-Fehler beim Wiederherstellen' };
  }

  // In DB als wiederhergestellt markieren
  await prisma.cachedEmail.update({
    where: { id },
    data: {
      isDeleted: false,
      deletedAt: null,
      uid: imapResult.newUid || email.uid, // Neue UID im wiederhergestellten Ordner
    },
  });

  return { success: true };
}

// E-Mail endgültig löschen (aus Papierkorb)
export async function permanentDeleteEmail(id: number): Promise<TrashOperationResult> {
  // E-Mail laden
  const email = await prisma.cachedEmail.findUnique({
    where: { id },
    include: {
      stressfreiEmail: true,
    },
  });

  if (!email) {
    return { success: false, error: 'E-Mail nicht gefunden' };
  }

  if (!email.isDeleted) {
    return { success: false, error: 'E-Mail muss erst in den Papierkorb verschoben werden' };
  }

  // IMAP-Einstellungen und Credentials
  const settings = await getImapSmtpSettings();
  if (!settings) {
    return { success: false, error: 'Keine E-Mail-Provider-Einstellungen' };
  }

  if (!email.stressfreiEmail.emailPasswordEncrypted) {
    return { success: false, error: 'Keine Mailbox-Zugangsdaten' };
  }

  let password: string;
  try {
    password = decrypt(email.stressfreiEmail.emailPasswordEncrypted);
  } catch {
    return { success: false, error: 'Passwort konnte nicht entschlüsselt werden' };
  }

  const credentials: ImapCredentials = {
    host: settings.imapServer,
    port: settings.imapPort,
    user: email.stressfreiEmail.email,
    password,
    encryption: settings.imapEncryption,
    allowSelfSignedCerts: settings.allowSelfSignedCerts,
  };

  // Auf IMAP-Server endgültig löschen (aus Trash)
  const imapResult = await permanentDelete(credentials, email.uid);

  if (!imapResult.success) {
    return { success: false, error: imapResult.error || 'IMAP-Fehler beim endgültigen Löschen' };
  }

  // Aus DB löschen
  await prisma.cachedEmail.delete({
    where: { id },
  });

  return { success: true };
}

// Papierkorb-E-Mails für einen Kunden abrufen
// Optional: nach Postfach (stressfreiEmailId) und/oder Vertrag (contractId)
// einschränken. Vorher zeigte der Papierkorb immer ALLE gelöschten E-Mails
// des Kunden, unabhängig von welchem Postfach man gerade angemeldet ist –
// User-Bug 2026-06-21.
export async function getTrashEmails(
  customerId: number,
  options?: { stressfreiEmailId?: number; contractId?: number },
): Promise<CachedEmailWithRelations[]> {
  const where: Prisma.CachedEmailWhereInput = {
    isDeleted: true,
    stressfreiEmail: { customerId },
  };
  if (options?.stressfreiEmailId) {
    where.stressfreiEmailId = options.stressfreiEmailId;
  }
  if (options?.contractId) {
    where.contractId = options.contractId;
  }
  return prisma.cachedEmail.findMany({
    where,
    include: {
      stressfreiEmail: {
        select: {
          id: true,
          email: true,
          customerId: true,
        },
      },
      contract: {
        select: {
          id: true,
          contractNumber: true,
        },
      },
    },
    orderBy: { deletedAt: 'desc' },
  }) as Promise<CachedEmailWithRelations[]>;
}

// Papierkorb-E-Mails zählen (gleiche Filter wie getTrashEmails)
export async function getTrashCount(
  customerId: number,
  options?: { stressfreiEmailId?: number; contractId?: number },
): Promise<number> {
  const where: Prisma.CachedEmailWhereInput = {
    isDeleted: true,
    stressfreiEmail: { customerId },
  };
  if (options?.stressfreiEmailId) {
    where.stressfreiEmailId = options.stressfreiEmailId;
  }
  if (options?.contractId) {
    where.contractId = options.contractId;
  }
  return prisma.cachedEmail.count({ where });
}

// Legacy: E-Mail löschen (jetzt deprecated, nutze moveEmailToTrash)
export async function deleteCachedEmail(id: number): Promise<void> {
  // Zur Abwärtskompatibilität: In Papierkorb verschieben statt löschen
  const result = await moveEmailToTrash(id);
  if (!result.success) {
    throw new Error(result.error || 'Fehler beim Löschen');
  }
}

// Alle gecachten E-Mails für eine StressfreiEmail löschen (nur Cache, kein IMAP)
export async function clearCacheForAccount(stressfreiEmailId: number): Promise<number> {
  const result = await prisma.cachedEmail.deleteMany({
    where: { stressfreiEmailId },
  });
  return result.count;
}

// ==================== SENT EMAILS ====================

// Gesendete E-Mail speichern
export async function createSentEmail(
  stressfreiEmailId: number,
  params: SentEmailParams
): Promise<CachedEmail> {
  // StressfreiEmail laden um Absender-Info zu bekommen
  const stressfreiEmail = await prisma.stressfreiEmail.findUnique({
    where: { id: stressfreiEmailId },
    select: { email: true },
  });

  if (!stressfreiEmail) {
    throw new Error('StressfreiEmail nicht gefunden');
  }

  const hasAttachments = params.attachmentNames && params.attachmentNames.length > 0;

  const email = await prisma.cachedEmail.create({
    data: {
      stressfreiEmailId,
      folder: EmailFolder.SENT,
      messageId: params.messageId,
      uid: params.uid || 0, // UID vom IMAP Sent-Ordner (für Attachment-Download)
      subject: params.subject || null,
      fromAddress: stressfreiEmail.email,
      fromName: null,
      toAddresses: JSON.stringify(params.to),
      ccAddresses: params.cc && params.cc.length > 0 ? JSON.stringify(params.cc) : null,
      receivedAt: new Date(), // Sendezeitpunkt
      textBody: params.text || null,
      htmlBody: params.html || null,
      hasAttachments: hasAttachments || false,
      attachmentNames: hasAttachments ? JSON.stringify(params.attachmentNames) : null,
      isRead: true, // Gesendete sind immer "gelesen"
      isStarred: false,
      // Vertragszuordnung falls angegeben (automatisch = aus Vertrag gesendet)
      contractId: params.contractId || null,
      assignedAt: params.contractId ? new Date() : null,
      isAutoAssigned: params.contractId ? true : false, // Automatisch wenn aus Vertrag gesendet
    },
  });

  return email;
}

// Anzahl E-Mails für Konto nach Ordner
export async function getEmailCountByFolder(
  stressfreiEmailId: number,
  folder: 'INBOX' | 'SENT'
): Promise<number> {
  return prisma.cachedEmail.count({
    where: {
      stressfreiEmailId,
      folder: folder === 'SENT' ? EmailFolder.SENT : EmailFolder.INBOX,
    },
  });
}
