<?php

declare(strict_types=1);

namespace Drupal\flowdrop_interrupt\Hook;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\flowdrop_interrupt\Service\InterruptManagerInterface;
use Drupal\flowdrop_interrupt\Service\ScheduledInterruptSweeper;
use Psr\Log\LoggerInterface;

/**
 * Cron hook implementations for the flowdrop_interrupt module.
 *
 * Resolves due scheduled interrupts (timers), expires overdue interrupts
 * and cleans up old resolved/cancelled entries.
 *
 * @internal This class is not part of the public API and may change without notice.
 */
final class CronHooks {

  /**
   * Constructs a new CronHooks object.
   *
   * @param \Drupal\flowdrop_interrupt\Service\InterruptManagerInterface $interruptManager
   *   The interrupt manager service.
   * @param \Drupal\flowdrop_interrupt\Service\ScheduledInterruptSweeper $scheduledSweeper
   *   The scheduled interrupt sweeper.
   * @param \Psr\Log\LoggerInterface $logger
   *   The logger channel.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
   *   The config factory.
   */
  public function __construct(
    protected readonly InterruptManagerInterface $interruptManager,
    protected readonly ScheduledInterruptSweeper $scheduledSweeper,
    protected readonly LoggerInterface $logger,
    protected readonly ConfigFactoryInterface $configFactory,
  ) {}

  /**
   * Implements hook_cron().
   *
   * Resolves due scheduled interrupts, expires overdue pending interrupts
   * and cleans up old entries.
   */
  #[Hook('cron')]
  public function cron(): void {
    $config = $this->configFactory->get('flowdrop_interrupt.settings');

    // Resolve due scheduled interrupts (timers) FIRST so a due timer is
    // resumed by the sweep, never caught by the expiry pass below.
    $resolved = $this->scheduledSweeper->sweep();
    if ($resolved > 0) {
      $this->logger->info('Cron: Resolved @count due scheduled interrupts', [
        '@count' => $resolved,
      ]);
    }

    // Expire pending interrupts that have passed their expiration time.
    $expired = $this->interruptManager->expireOverdueInterrupts();
    if ($expired > 0) {
      $this->logger->info('Cron: Expired @count overdue interrupts', [
        '@count' => $expired,
      ]);
    }

    // Clean up resolved/cancelled/expired interrupts based on config.
    if ($config->get('cleanup_enabled') !== FALSE) {
      $maxAge = (int) ($config->get('cleanup_max_age') ?: 604800);
      $cleaned = $this->interruptManager->cleanupOldInterrupts($maxAge);
      if ($cleaned > 0) {
        $this->logger->info('Cron: Cleaned up @count old interrupts', [
          '@count' => $cleaned,
        ]);
      }
    }
  }

}
