<?php

declare(strict_types=1);

namespace Drupal\flowdrop_runtime\Hook;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Psr\Log\LoggerInterface;

/**
 * Hook implementations for the flowdrop_runtime module.
 *
 * @internal This class is not part of the public API and may change without notice.
 */
final class RuntimeHooks {

  use StringTranslationTrait;

  /**
   * Constructs a new RuntimeHooks object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manager.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
   *   The configuration factory.
   * @param \Psr\Log\LoggerInterface $logger
   *   The logger channel.
   */
  public function __construct(
    protected readonly EntityTypeManagerInterface $entityTypeManager,
    protected readonly ConfigFactoryInterface $configFactory,
    protected readonly LoggerInterface $logger,
  ) {}

  /**
   * Implements hook_help().
   */
  #[Hook('help')]
  public function help(string $route_name, RouteMatchInterface $route_match): string {
    switch ($route_name) {
      case 'help.page.flowdrop_runtime':
        return '<p>' . $this->t('The FlowDrop Runtime module provides workflow execution orchestration, including synchronous, asynchronous, and stateful graph-based execution modes.') . '</p>';

      case 'entity.flowdrop_workflow_snapshot.collection':
        return '<p>' . $this->t('Workflow snapshots capture the complete state of a workflow execution at a point in time. They can be used for workflow resume, orchestrator handover, and debugging.') . '</p>';

      default:
        return '';
    }
  }

  /**
   * Implements hook_cron().
   *
   * Performs periodic cleanup of old workflow snapshots based on configuration.
   */
  #[Hook('cron')]
  public function cron(): void {
    $config = $this->configFactory->get('flowdrop_runtime.settings');
    $enabled = $config->get('snapshot_cleanup.enabled') ?? TRUE;

    if (!$enabled) {
      return;
    }

    // Get cleanup parameters.
    // 7 days default.
    $maxAge = $config->get('snapshot_cleanup.max_age') ?? 604800;
    $statuses = $config->get('snapshot_cleanup.statuses') ?? ['completed', 'failed'];
    $batchSize = $config->get('snapshot_cleanup.batch_size') ?? 100;

    // Calculate cutoff timestamp.
    $olderThan = time() - $maxAge;

    try {
      $snapshotStorage = $this->entityTypeManager->getStorage('flowdrop_workflow_snapshot');
      $query = $snapshotStorage->getQuery()
        ->condition('created', $olderThan, '<')
        // Access bypassed: system cron cleanup runs without user context.
        ->accessCheck(FALSE)
        ->range(0, $batchSize);

      if (!empty($statuses)) {
        $query->condition('snapshot_status', $statuses, 'IN');
      }

      $ids = $query->execute();
      if (!empty($ids)) {
        $entities = $snapshotStorage->loadMultiple($ids);

        foreach ($entities as $entity) {
          $entity->delete();
        }

        $this->logger->info('Cron: Cleaned up @count workflow snapshots older than @days days.', [
          '@count' => count($ids),
          '@days' => round($maxAge / 86400, 1),
        ]);
      }
    }
    catch (\Exception $e) {
      $this->logger->error('Cron: Failed to cleanup workflow snapshots: @error', [
        '@error' => $e->getMessage(),
      ]);
    }
  }

}
