// ============================================================
// Scheduler: Activity Due Soon - alle 15 Minuten
// ============================================================

import { Injectable, Logger } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
import { CrmPrismaService } from '../prisma/crm-prisma.service';
import { RedisService } from '../redis/redis.service';
import { CrmEventPublisher } from './crm-event-publisher.service';

@Injectable()
export class ActivityDueSoonScheduler {
  private readonly logger = new Logger(ActivityDueSoonScheduler.name);
  private static readonly LOCK_KEY = 'lock:activity-due-soon';
  private static readonly LOCK_TTL = 600; // 10 Minuten

  constructor(
    private readonly prisma: CrmPrismaService,
    private readonly redis: RedisService,
    private readonly eventPublisher: CrmEventPublisher,
  ) {}

  @Cron('0 */15 * * * *')
  async checkDueSoon(): Promise<void> {
    // Distributed Lock um parallele Ausfuehrung zu verhindern
    const lockAcquired = await this.redis.setNx(
      ActivityDueSoonScheduler.LOCK_KEY,
      process.pid.toString(),
      ActivityDueSoonScheduler.LOCK_TTL,
    );

    if (!lockAcquired) {
      this.logger.debug('Activity Due Soon Check: Lock bereits vergeben, ueberspringe.');
      return;
    }

    try {
      const now = new Date();
      const in24h = new Date(now.getTime() + 24 * 60 * 60 * 1000);

      // Activities die in den naechsten 24h faellig sind und nicht completed
      const dueActivities = await this.prisma.activity.findMany({
        where: {
          scheduledAt: {
            gte: now,
            lte: in24h,
          },
          completedAt: null,
        },
        select: {
          id: true,
          tenantId: true,
          scheduledAt: true,
          contactId: true,
          companyId: true,
        },
        take: 100, // Batch-Limit
      });

      if (dueActivities.length === 0) {
        this.logger.debug('Keine faelligen Activities gefunden.');
        return;
      }

      this.logger.log(
        `${dueActivities.length} faellige Activities gefunden, publiziere Events...`,
      );

      for (const activity of dueActivities) {
        await this.eventPublisher.activityDueSoon(
          activity.tenantId,
          activity.id,
          {
            scheduledAt: activity.scheduledAt?.toISOString() ?? '',
            contactId: activity.contactId ?? undefined,
          },
        );
      }

      this.logger.log(`${dueActivities.length} activity.due_soon Events publiziert.`);
    } catch (err) {
      this.logger.error(`Fehler im Activity Due Soon Scheduler: ${String(err)}`);
    }
  }
}
