<?php

declare(strict_types=1);

namespace Drupal\native_observability\Service;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Database\Connection;

/**
 * Cleans up retained request trace records.
 */
final class TraceCleanupHandler implements ObservabilityCleanupHandlerInterface {

  /**
   * Constructs the trace cleanup handler.
   */
  public function __construct(
    private readonly Connection $database,
    private readonly TimeInterface $time,
  ) {
  }

  /**
   * {@inheritdoc}
   */
  public function id(): string {
    return 'trace';
  }

  /**
   * {@inheritdoc}
   */
  public function isAvailable(): bool {
    return $this->database->schema()->tableExists('native_observability_trace');
  }

  /**
   * {@inheritdoc}
   */
  public function cleanup(array $settings): int {
    if (!$this->isAvailable()) {
      return 0;
    }

    $hours = max(1, (int) ($settings['trace_retention_hours'] ?? 24));
    $threshold = $this->time->getCurrentTime() - ($hours * 3600);
    $limit = max(1, (int) ($settings['cleanup_batch_limit'] ?? 5000));

    $ids = $this->database->select('native_observability_trace', 't')
      ->fields('t', ['id'])
      ->condition('started_at', $threshold, '<')
      ->range(0, $limit)
      ->execute()
      ->fetchCol();

    if (!$ids) {
      return 0;
    }

    return (int) $this->database->delete('native_observability_trace')
      ->condition('id', $ids, 'IN')
      ->execute();
  }

  /**
   * {@inheritdoc}
   */
  public function cleanupAll(): int {
    if (!$this->isAvailable()) {
      return 0;
    }

    $count = (int) $this->database->select('native_observability_trace', 't')
      ->countQuery()
      ->execute()
      ->fetchField();

    if ($count === 0) {
      return 0;
    }

    $this->database->truncate('native_observability_trace')->execute();

    return $count;
  }

}
