import { Injectable } from '@nestjs/common';
import { CommandBus } from '@nestjs/cqrs';
import { OnEvent } from '@nestjs/event-emitter';
import { LoggerService, PrismaService } from '@modules/shared';
import { ListingExpiringEvent } from '@modules/listings';
import { SendNotificationCommand } from '../commands/send-notification/send-notification.command';

/**
 * Handles `listing.expiring` events published by the daily expiry-warning cron.
 *
 * Sends both an email and a Zalo OA notification to the seller so they can
 * renew or extend their listing before it expires.
 */
@Injectable()
export class ListingExpiringListener {
  constructor(
    private readonly commandBus: CommandBus,
    private readonly prisma: PrismaService,
    private readonly logger: LoggerService,
  ) {}

  @OnEvent('listing.expiring', { async: true })
  async handle(event: ListingExpiringEvent): Promise<void> {
    this.logger.log(
      `Handling listing.expiring for listing ${event.aggregateId}`,
      'ListingExpiringListener',
    );

    const listing = await this.prisma.listing.findUnique({
      where: { id: event.aggregateId },
      include: {
        property: { select: { title: true } },
        seller: { select: { id: true, email: true, phone: true } },
      },
    });

    if (!listing) return;

    const templateData = {
      listingTitle: listing.property.title,
      expiresAt: event.expiresAt.toISOString(),
      daysRemaining: Math.ceil(
        (event.expiresAt.getTime() - Date.now()) / (1000 * 60 * 60 * 24),
      ),
    };

    const notifications: Promise<unknown>[] = [];

    // Email notification
    if (listing.seller.email) {
      notifications.push(
        this.commandBus.execute(
          new SendNotificationCommand(
            listing.seller.id,
            'EMAIL',
            'listing.expiring',
            templateData,
            listing.seller.email,
          ),
        ),
      );
    }

    // Zalo OA notification (phone as recipient address)
    if (listing.seller.phone) {
      notifications.push(
        this.commandBus.execute(
          new SendNotificationCommand(
            listing.seller.id,
            'ZALO_OA',
            'listing.expiring',
            templateData,
            listing.seller.phone,
          ),
        ),
      );
    }

    await Promise.allSettled(notifications);
  }
}
