<?php

declare(strict_types=1);

namespace Drupal\native_observability_metrics\Drush\Commands;

use Drupal\native_observability_metrics\Service\RouteMetricsAggregator;
use Drush\Attributes as CLI;
use Drush\Commands\DrushCommands;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Drush commands for Native Observability metrics.
 */
final class NativeObservabilityMetricsCommands extends DrushCommands {

  /**
   * Constructs the metrics Drush commands service.
   *
   * @param \Drupal\native_observability_metrics\Service\RouteMetricsAggregator $routeMetricsAggregator
   *   The route metrics aggregation service.
   */
  public function __construct(
    private readonly RouteMetricsAggregator $routeMetricsAggregator,
  ) {
    parent::__construct();
  }

  /**
   * Creates the command instance from the Drupal container.
   *
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   *   The Drupal service container.
   *
   * @return static
   *   The command instance.
   */
  public static function create(ContainerInterface $container): self {
    return new self(
      $container->get('native_observability_metrics.route_metrics_aggregator'),
    );
  }

  /**
   * Aggregates route metrics and stores a new snapshot.
   *
   * By default, the command aggregates the latest completed metrics window.
   * Optionally, a rolling window can be aggregated by enabling --rolling.
   *
   * @param array $options
   *   Command options.
   *
   * @return int
   *   The command exit code.
   */
  #[CLI\Command(name: 'native-observability-metric:aggregate', aliases: ['nom:aggregate'])]
  #[CLI\Usage(name: 'drush native-observability-metric:aggregate', description: 'Aggregate the latest completed metrics window.')]
  #[CLI\Usage(name: 'drush native-observability-metric:aggregate --rolling=1 --seconds=300', description: 'Aggregate a rolling metrics window ending now.')]
  #[CLI\Option(name: 'rolling', description: 'Enable rolling window aggregation. Accepts 1 or 0.')]
  #[CLI\Option(name: 'seconds', description: 'Rolling window duration in seconds. Used only when --rolling=1.')]
  public function aggregate(
    array $options = [
      'rolling' => 0,
      'seconds' => 300,
    ],
  ): int {
    $rolling = (int) ($options['rolling'] ?? 0) === 1;
    $seconds = max(1, (int) ($options['seconds'] ?? 300));

    if ($rolling) {
      $metrics = $this->routeMetricsAggregator->aggregateRollingWindow($seconds);
      $this->logger()->notice(sprintf(
        'Running Native Observability metrics aggregation for a rolling window of %d seconds.',
        $seconds,
      ));
    }
    else {
      $metrics = $this->routeMetricsAggregator->aggregateLatestCompletedWindow();
      $this->logger()->notice('Running Native Observability metrics aggregation for the latest completed window.');
    }

    if (empty($metrics)) {
      $this->io()->warning('No aggregated metrics were generated. Ensure trace data exists and that the selected time window contains completed trace records.');
      return self::EXIT_SUCCESS;
    }

    $rows = [];
    foreach ($metrics as $metric) {
      $rows[] = [
        $metric['route_key'] ?? '',
        (string) ($metric['request_count'] ?? 0),
        (string) ($metric['throughput_per_minute'] ?? '0.00'),
        (string) ($metric['avg_duration_ms'] ?? 0),
        (string) ($metric['p95_duration_ms'] ?? 0),
        (string) ($metric['p99_duration_ms'] ?? 0),
      ];
    }

    $this->io()->title('Native Observability metrics aggregation');
    $this->io()->table(
      ['Route', 'Requests', 'Throughput / min', 'Avg duration (ms)', 'P95 (ms)', 'P99 (ms)'],
      $rows,
    );
    $this->io()->writeln('');
    $this->io()->success(sprintf(
      'Metrics aggregation completed successfully. Generated %d aggregated route snapshot rows.',
      count($metrics),
    ));

    return self::EXIT_SUCCESS;
  }

}
