import { Injectable, Logger, OnModuleDestroy, OnModuleInit } from "@nestjs/common";
import { PrismaService } from "./prisma/prisma.service";

export async function purgeExpiredServiceAds(prisma: PrismaService) {
  const expired = await prisma.serviceAd.findMany({
    where: { deletedAt: { not: null }, purgeAt: { lte: new Date() } },
    select: { id: true },
    take: 100,
  });
  if (!expired.length) return 0;
  const ids = expired.map(item => item.id);
  await prisma.$transaction([
    prisma.favorite.deleteMany({ where: { adId: { in: ids } } }),
    prisma.conversation.updateMany({ where: { adId: { in: ids } }, data: { adId: null } }),
    prisma.serviceAd.deleteMany({ where: { id: { in: ids } } }),
  ]);
  return ids.length;
}

export function serviceAdPurgeDate(from = new Date()) {
  const date = new Date(from);
  date.setUTCMonth(date.getUTCMonth() + 3);
  return date;
}

@Injectable()
export class ServiceAdRetentionService implements OnModuleInit, OnModuleDestroy {
  private readonly logger = new Logger(ServiceAdRetentionService.name);
  private timer?: NodeJS.Timeout;

  constructor(private readonly prisma: PrismaService) {}

  onModuleInit() {
    void this.runCleanup();
    this.timer = setInterval(() => void this.runCleanup(), 24 * 60 * 60 * 1000);
    this.timer.unref?.();
  }

  onModuleDestroy() {
    if (this.timer) clearInterval(this.timer);
  }

  private async runCleanup() {
    try {
      let removed = 0;
      do {
        removed = await purgeExpiredServiceAds(this.prisma);
      } while (removed === 100);
    } catch (error) {
      this.logger.error(
        "Failed to purge expired service ads.",
        error instanceof Error ? error.stack : undefined,
      );
    }
  }
}
