<?php

declare(strict_types=1);

namespace Drupal\native_observability\Form;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\native_observability\Service\ObservabilityCleanupManager;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Configuration form for observability cleanup and retention settings.
 */
final class ObservabilityCleanupSettingsForm extends ConfigFormBase {

  /**
   * Constructs the cleanup settings form.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   Config factory.
   * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager
   *   Typed config manager.
   * @param \Drupal\native_observability\Service\ObservabilityCleanupManager $cleanup_manager
   *   Cleanup manager.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   Module handler.
   */
  public function __construct(
    ConfigFactoryInterface $config_factory,
    TypedConfigManagerInterface $typed_config_manager,
    private readonly ObservabilityCleanupManager $cleanup_manager,
    private readonly ModuleHandlerInterface $module_handler,
  ) {
    parent::__construct($config_factory, $typed_config_manager);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): self {
    return new self(
      $container->get('config.factory'),
      $container->get('config.typed'),
      $container->get('native_observability.cleanup_manager'),
      $container->get('module_handler'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return 'native_observability_cleanup_settings_form';
  }

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames(): array {
    return ['native_observability.settings'];
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $config = $this->config('native_observability.settings');

    $spans_enabled = $this->module_handler->moduleExists('native_observability_spans');
    $metrics_enabled = $this->module_handler->moduleExists('native_observability_metrics');

    $form['description'] = [
      '#type' => 'item',
      '#markup' => $this->t('Configure centralized retention, scheduled cleanup, and manual cleanup actions for the Native Observability ecosystem. Submodule-specific settings remain visible even when the related module is not enabled.'),
    ];

    $form['cleanup_enabled'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable automatic cleanup'),
      '#default_value' => $config->get('cleanup_enabled'),
      '#description' => $this->t('When enabled, Native Observability will execute scheduled cleanup during cron using the configured retention values.'),
    ];

    $form['cleanup_batch_limit'] = [
      '#type' => 'number',
      '#title' => $this->t('Cleanup batch limit'),
      '#default_value' => $config->get('cleanup_batch_limit') ?? 5000,
      '#min' => 1,
      '#step' => 1,
      '#required' => TRUE,
      '#description' => $this->t('Maximum number of records deleted per cleanup run and per handler.'),
    ];

    $form['trace_settings'] = [
      '#type' => 'details',
      '#title' => $this->t('Trace cleanup'),
      '#open' => TRUE,
    ];

    $form['trace_settings']['trace_retention_hours'] = [
      '#type' => 'number',
      '#title' => $this->t('Trace retention (hours)'),
      '#default_value' => $config->get('trace_retention_hours') ?? 24,
      '#min' => 1,
      '#step' => 1,
      '#required' => TRUE,
      '#description' => $this->t('Retention period for raw request traces stored by the base module.'),
    ];

    $form['spans_settings'] = [
      '#type' => 'details',
      '#title' => $this->t('Spans cleanup'),
      '#open' => TRUE,
      '#description' => !$spans_enabled
        ? $this->t('This section is currently unavailable because the Native Observability Spans submodule is not enabled.')
        : $this->t('Retention settings for execution span data.'),
    ];

    $form['spans_settings']['spans_retention_hours'] = [
      '#type' => 'number',
      '#title' => $this->t('Spans retention (hours)'),
      '#default_value' => $config->get('spans_retention_hours') ?? 24,
      '#min' => 1,
      '#step' => 1,
      '#required' => TRUE,
      '#disabled' => !$spans_enabled,
      '#description' => $this->t('Retention period for execution span records.'),
    ];

    $form['metrics_settings'] = [
      '#type' => 'details',
      '#title' => $this->t('Metrics cleanup'),
      '#open' => TRUE,
      '#description' => !$metrics_enabled
        ? $this->t('This section is currently unavailable because the Native Observability Metrics submodule is not enabled.')
        : $this->t('Retention settings for persisted aggregated metrics.'),
    ];

    $form['metrics_settings']['metrics_retention_days'] = [
      '#type' => 'number',
      '#title' => $this->t('Metrics retention (days)'),
      '#default_value' => $config->get('metrics_retention_days') ?? 7,
      '#min' => 1,
      '#step' => 1,
      '#required' => TRUE,
      '#disabled' => !$metrics_enabled,
      '#description' => $this->t('Retention period for persisted aggregated metrics.'),
    ];

    $form['manual_actions'] = [
      '#type' => 'details',
      '#title' => $this->t('Manual cleanup actions'),
      '#open' => TRUE,
      '#description' => $this->t('Manual cleanup actions are available even when automatic cleanup is disabled.'),
    ];

    $form['manual_actions']['run_cleanup_now'] = [
      '#type' => 'submit',
      '#value' => $this->t('Run cleanup now'),
      '#submit' => ['::runCleanupNowSubmit'],
      '#limit_validation_errors' => [],
      '#button_type' => 'secondary',
    ];

    $form['manual_actions']['force_cleanup_all'] = [
      '#type' => 'submit',
      '#value' => $this->t('Force clean all observability data'),
      '#submit' => ['::forceCleanupAllSubmit'],
      '#limit_validation_errors' => [],
      '#button_type' => 'danger',
      '#attributes' => [
        'onclick' => 'return confirm("This action will delete all retained observability data across all available observability datasets. Continue?");',
      ],
    ];

    return parent::buildForm($form, $form_state);
  }

  /**
   * Saves configuration values.
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    $this->configFactory->getEditable('native_observability.settings')
      ->set('cleanup_enabled', (bool) $form_state->getValue('cleanup_enabled'))
      ->set('cleanup_batch_limit', (int) $form_state->getValue('cleanup_batch_limit'))
      ->set('trace_retention_hours', (int) $form_state->getValue('trace_retention_hours'))
      ->set('spans_retention_hours', (int) ($form_state->getValue('spans_retention_hours') ?? 24))
      ->set('metrics_retention_days', (int) ($form_state->getValue('metrics_retention_days') ?? 7))
      ->save();

    parent::submitForm($form, $form_state);
  }

  /**
   * Runs cleanup immediately using current stored settings.
   */
  public function runCleanupNowSubmit(array &$form, FormStateInterface $form_state): void {
    $results = $this->cleanup_manager->runManualCleanup();

    $this->messenger()->addStatus($this->t('Cleanup completed. Results: @results', [
      '@results' => json_encode($results),
    ]));
  }

  /**
   * Runs a forced full cleanup immediately.
   */
  public function forceCleanupAllSubmit(array &$form, FormStateInterface $form_state): void {
    $results = $this->cleanup_manager->runForcedCleanupAll();

    $this->messenger()->addWarning($this->t('Forced cleanup completed. Results: @results', [
      '@results' => json_encode($results),
    ]));
  }

}
