import { usePrisma } from "../utils/prisma";

export async function getMailConnections(userId: string) {
  const db = usePrisma();
  // isActive=true UND nicht pausiert (pausedAt=null) — pausierte werden vom Cron ausgelassen
  return db.mailConnection.findMany({
    where: { userId, isActive: true, pausedAt: null },
    orderBy: { createdAt: "asc" },
  });
}

/** Alle Verbindungen eines Users inkl. pausierten — für Status-Anzeige im Frontend. */
export async function getAllMailConnections(userId: string) {
  const db = usePrisma();
  return db.mailConnection.findMany({
    where: { userId },
    orderBy: { createdAt: "asc" },
    select: {
      id: true,
      email: true,
      provider: true,
      providerName: true,
      isActive: true,
      pausedAt: true,
      pausedReason: true,
      scanInterval: true,
      lastScannedAt: true,
      nextScanAt: true,
      emailsBlocked: true,
      emailsScanned: true,
      lastConnectError: true,
      createdAt: true,
    },
  });
}

export async function getAllActiveMailUserIds() {
  const db = usePrisma();
  const rows = await db.mailConnection.findMany({
    where: { isActive: true, nextScanAt: { lte: new Date() } },
    select: { userId: true },
    distinct: ["userId"],
  });
  return rows.map((r) => r.userId);
}

export async function countMailConnections(userId: string) {
  const db = usePrisma();
  // Nur aktive + nicht-pausierte Verbindungen zählen gegen das Limit
  return db.mailConnection.count({ where: { userId, isActive: true, pausedAt: null } });
}

export async function upsertMailConnection(data: {
  userId: string;
  email: string;
  provider: string;
  providerName: string;
  imapHost: string;
  imapPort: number;
  passwordEncrypted: string;
  rejectUnauthorized?: boolean;
  useStarttls?: boolean;
}) {
  const db = usePrisma();
  return db.mailConnection.upsert({
    where: { userId_email: { userId: data.userId, email: data.email } },
    create: {
      ...data,
      isActive: true,
      rejectUnauthorized: data.rejectUnauthorized ?? true,
      useStarttls: data.useStarttls ?? false,
    },
    update: {
      providerName: data.providerName,
      imapHost: data.imapHost,
      imapPort: data.imapPort,
      passwordEncrypted: data.passwordEncrypted,
      rejectUnauthorized: data.rejectUnauthorized ?? true,
      useStarttls: data.useStarttls ?? false,
      isActive: true,
      // Bei Re-Connect (z.B. neues App-Passwort): alte Error-Spuren clearen,
      // damit UI sofort wieder "Live" zeigt — IDLE-daemon übernimmt.
      lastConnectError: null,
      lastConnectErrorAt: null,
    },
  });
}

export async function deleteMailConnection(
  userId: string,
  connectionId: string,
) {
  const db = usePrisma();
  return db.mailConnection.deleteMany({
    where: { id: connectionId, userId },
  });
}

export async function deleteAllMailConnections(userId: string) {
  const db = usePrisma();
  return db.mailConnection.deleteMany({ where: { userId } });
}

export async function updateMailConnectionInterval(
  userId: string,
  connectionId: string,
  interval: number,
) {
  const db = usePrisma();
  return db.mailConnection.updateMany({
    where: { id: connectionId, userId },
    data: { scanInterval: interval },
  });
}

export async function updateMailConnectionScanStats(
  connectionId: string,
  scanned: number,
  blocked: number,
  currentBlocked: number,
  currentScanned: number,
  scanIntervalHours: number,
) {
  const db = usePrisma();
  return db.mailConnection.update({
    where: { id: connectionId },
    data: {
      lastScannedAt: new Date(),
      emailsBlocked: currentBlocked + blocked,
      emailsScanned: currentScanned + scanned,
      nextScanAt: new Date(Date.now() + scanIntervalHours * 3_600_000),
    },
  });
}

export async function getMailBlockedStats(userId: string) {
  const db = usePrisma();
  const since7d = new Date(Date.now() - 7 * 86_400_000);
  return db.mailBlocked.findMany({
    where: { userId, createdAt: { gte: since7d } },
    select: { createdAt: true },
  });
}

export async function isMailAlreadyBlocked(
  gmailMessageId: string,
  userId: string,
) {
  const db = usePrisma();
  const existing = await db.mailBlocked.findFirst({
    where: { gmailMessageId, userId },
    select: { id: true },
  });
  return !!existing;
}

export async function getAlreadyBlockedUidSet(
  uids: string[],
  userId: string,
): Promise<Set<string>> {
  if (uids.length === 0) return new Set();
  const db = usePrisma();
  const existing = await db.mailBlocked.findMany({
    where: { gmailMessageId: { in: uids }, userId },
    select: { gmailMessageId: true },
  });
  return new Set(existing.map((e) => e.gmailMessageId));
}

export async function insertMailBlocked(
  entries: {
    userId: string;
    connectionId: string;
    gmailMessageId: string;
    senderEmail: string;
    senderName: string | null;
    subject: string;
    receivedAt: Date;
    action: string;
  }[],
) {
  if (entries.length === 0) return;
  const db = usePrisma();
  await db.mailBlocked.createMany({ data: entries, skipDuplicates: true });
}

export async function getImapProxyAccounts(userId: string) {
  const db = usePrisma();
  return db.imapProxyAccount.findMany({ where: { userId } });
}

export async function upsertImapProxyAccount(data: {
  userId: string;
  proxyUsername: string;
  proxyPassword: string;
  connectionId: string;
}) {
  const db = usePrisma();
  return db.imapProxyAccount.upsert({
    where: { connectionId: data.connectionId },
    create: data,
    update: { proxyPassword: data.proxyPassword },
  });
}

export async function deleteOldMailBlocked(userId: string) {
  const db = usePrisma();
  const cutoff = new Date(Date.now() - 24 * 3_600_000);
  return db.mailBlocked.deleteMany({
    where: { userId, createdAt: { lt: cutoff } },
  });
}

export async function getMailBlockedPaginated(
  userId: string,
  page: number,
  limit = 20,
) {
  const db = usePrisma();
  const offset = (page - 1) * limit;
  const [results, total] = await Promise.all([
    db.mailBlocked.findMany({
      where: { userId },
      orderBy: { createdAt: "desc" },
      skip: offset,
      take: limit,
    }),
    db.mailBlocked.count({ where: { userId } }),
  ]);
  return { results, total, page, pages: Math.ceil(total / limit) };
}
