<?php
/**
 * BookiFlex Notification Extension
 *
 * @package    BookiFlex
 * @subpackage Notification
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */

declare(strict_types=1);

namespace BookiFlex\Extensions\Notification\Service\Jobs;

use BookiFlex\Core\Contract\Queue\QueueJobInterface;
use BookiFlex\Core\Model\Reservation\ReservationStatus;
use BookiFlex\Extensions\Notification\Repository\NotificationRepository;
use Cycle\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;

defined('ABSPATH') || exit;

/**
 * Daily job that purges notifications linked to completed reservations
 * where the send time is older than RETENTION_WEEKS weeks.
 *
 * Runs in batches of BATCH_SIZE to avoid memory pressure.
 */
class PurgeOldNotificationsJob implements QueueJobInterface
{
    public const HOOK = 'bookiflex_purge_old_notifications';

    private const RETENTION_WEEKS = 2;
    private const BATCH_SIZE      = 200;

    public function __construct(
        private readonly NotificationRepository $notificationRepository,
        private readonly EntityManagerInterface $entityManager,
        private readonly ?LoggerInterface $logger = null,
    ) {
    }

    public function handle(array $args): void
    {
        $cutoff = new \DateTimeImmutable(
            '-' . self::RETENTION_WEEKS . ' weeks',
            new \DateTimeZone('UTC')
        );

        $notifications = $this->notificationRepository->findOlderThan($cutoff, self::BATCH_SIZE);

        if (empty($notifications)) {
            $this->logger?->debug('PurgeOldNotificationsJob: nothing to purge');
            return;
        }

        $deleted = 0;

        foreach ($notifications as $notification) {
            $reservation = $notification->getReservation();
            if ($reservation === null) {
                continue;
            }

            if ($reservation->getStatus()->isEquals(ReservationStatus::STATUS_COMPLETED)) {
                $this->entityManager->delete($notification);
                $deleted++;
            }
        }

        if ($deleted > 0) {
            $this->entityManager->run();
        }

        $this->logger?->info('PurgeOldNotificationsJob: completed', [
            'checked' => count($notifications),
            'deleted' => $deleted,
        ]);
    }

    public function getHook(): string
    {
        return self::HOOK;
    }

    public function getMaxAttempts(): int
    {
        return 1;
    }
}