<?php

declare(strict_types=1);

namespace Drupal\native_observability_status_block\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a status block for Native Observability capture configuration.
 *
 * @Block(
 *   id = "native_observability_status_block",
 *   admin_label = @Translation("Native Observability: Status summary"),
 *   category = @Translation("Native Observability")
 * )
 */
final class NativeObservabilityStatusBlock extends BlockBase implements ContainerFactoryPluginInterface {

  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    private readonly ConfigFactoryInterface $configFactory,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * Creates the block plugin instance.
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
    return new self(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('config.factory'),
    );
  }

  /**
   * Gets the default block configuration.
   */
  public function defaultConfiguration(): array {
    return [
      'variant' => 'compact',
      'show_warnings' => TRUE,
      'show_capture' => TRUE,
      'show_retention' => TRUE,
      'show_meta' => FALSE,
    ] + parent::defaultConfiguration();
  }

  /**
   * Builds the block configuration form.
   */
  public function blockForm($form, FormStateInterface $form_state): array {
    $form['variant'] = [
      '#type' => 'select',
      '#title' => $this->t('Variant'),
      '#default_value' => (string) ($this->configuration['variant'] ?? 'compact'),
      '#options' => [
        'compact' => $this->t('Compact'),
        'detailed' => $this->t('Detailed'),
      ],
      '#description' => $this->t('Controls the template suggestion used for rendering.'),
    ];

    $form['show_capture'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Show capture settings summary'),
      '#default_value' => (bool) ($this->configuration['show_capture'] ?? TRUE),
    ];

    $form['show_retention'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Show retention summary'),
      '#default_value' => (bool) ($this->configuration['show_retention'] ?? TRUE),
    ];

    $form['show_warnings'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Show warnings'),
      '#default_value' => (bool) ($this->configuration['show_warnings'] ?? TRUE),
      '#description' => $this->t('Shows warnings when riskier capture modes are enabled (e.g. full IP, full User-Agent, full query/body).'),
    ];

    $form['show_meta'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Show meta info'),
      '#default_value' => (bool) ($this->configuration['show_meta'] ?? FALSE),
      '#description' => $this->t('Includes extra technical info intended for administrators.'),
    ];

    return $form;
  }

  /**
   * Submits the block configuration form.
   */
  public function blockSubmit($form, FormStateInterface $form_state): void {
    $this->configuration['variant'] = (string) $form_state->getValue('variant');
    $this->configuration['show_warnings'] = (bool) $form_state->getValue('show_warnings');
    $this->configuration['show_capture'] = (bool) $form_state->getValue('show_capture');
    $this->configuration['show_retention'] = (bool) $form_state->getValue('show_retention');
    $this->configuration['show_meta'] = (bool) $form_state->getValue('show_meta');
  }

  /**
   * Builds the status block output.
   */
  public function build(): array {
    $settings = $this->configFactory->get('native_observability.settings');
    $capture = (array) ($settings->get('capture') ?? []);
    $retention = (array) ($settings->get('retention') ?? []);

    $enabled = (bool) ($capture['enabled'] ?? TRUE);

    $summary = $this->buildCaptureSummary($capture);
    $warnings = $this->buildWarnings($capture);

    $build = [
      '#theme' => 'native_observability_status_block',
      '#title' => $this->t('Native Observability'),
      '#variant' => (string) ($this->configuration['variant'] ?? 'compact'),
      '#capture' => [
        'enabled' => $enabled,
        'summary' => $summary,
        'raw' => $capture,
      ],
      '#retention' => [
        'days' => (int) ($retention['days'] ?? 14),
        'max_rows' => (int) ($retention['max_rows'] ?? 0),
      ],
      '#warnings' => $warnings,
      '#meta' => [
        'module' => 'native_observability_status_block',
      ],
      '#attached' => [
        'library' => [
          'native_observability_status_block/status_block',
        ],
      ],
      '#cache' => [
        'contexts' => ['user.permissions'],
        'tags' => ['config:native_observability.settings'],
      ],
    ];

    // Allow block-level toggles.
    if (empty($this->configuration['show_capture'])) {
      $build['#capture']['summary'] = [];
    }
    if (empty($this->configuration['show_retention'])) {
      $build['#retention'] = [];
    }
    if (empty($this->configuration['show_warnings'])) {
      $build['#warnings'] = [];
    }
    if (empty($this->configuration['show_meta'])) {
      $build['#meta'] = [];
    }

    return $build;
  }

  /**
   * Builds the capture summary lines.
   *
   * @param array<string, mixed> $capture
   *   The capture configuration snapshot.
   *
   * @return array<int, \Drupal\Core\StringTranslation\TranslatableMarkup|string>
   *   A list of human-readable summary items.
   */
  private function buildCaptureSummary(array $capture): array {
    $enabled = (bool) ($capture['enabled'] ?? TRUE);
    $ip_mode = (string) ($capture['client_ip_mode'] ?? 'anonymized');
    $ua_mode = (string) ($capture['user_agent_mode'] ?? 'family');
    $headers_mode = (string) ($capture['headers_mode'] ?? 'off');
    $query_mode = (string) ($capture['query_mode'] ?? 'off');
    $body_mode = (string) ($capture['body_mode'] ?? 'off');
    $store_uid = (bool) ($capture['store_uid'] ?? TRUE);

    $items = [];
    $items[] = $enabled ? $this->t('Capture: enabled') : $this->t('Capture: disabled');
    $items[] = $this->t('User ID: @v', ['@v' => $store_uid ? 'on' : 'off']);
    $items[] = $this->t('Client IP: @v', ['@v' => $ip_mode]);
    $items[] = $this->t('User-Agent: @v', ['@v' => $ua_mode]);
    $items[] = $this->t('Headers: @v', ['@v' => $headers_mode]);
    $items[] = $this->t('Query: @v', ['@v' => $query_mode]);
    $items[] = $this->t('Body: @v', ['@v' => $body_mode]);

    return $items;
  }

  /**
   * Builds warning messages for risky capture settings.
   *
   * @param array<string, mixed> $capture
   *   The capture configuration snapshot.
   *
   * @return array<int, \Drupal\Core\StringTranslation\TranslatableMarkup|string>
   *   A list of warning messages.
   */
  private function buildWarnings(array $capture): array {
    $warnings = [];

    $enabled = (bool) ($capture['enabled'] ?? TRUE);
    if (!$enabled) {
      return $warnings;
    }

    $ip_mode = (string) ($capture['client_ip_mode'] ?? 'anonymized');
    $ua_mode = (string) ($capture['user_agent_mode'] ?? 'family');
    $query_mode = (string) ($capture['query_mode'] ?? 'off');
    $body_mode = (string) ($capture['body_mode'] ?? 'off');

    // Simple heuristics for “riskier” modes.
    if ($ip_mode === 'full') {
      $warnings[] = $this->t('Full client IP capture is enabled. This increases personal data exposure.');
    }
    if ($ua_mode === 'full') {
      $warnings[] = $this->t('Full User-Agent capture is enabled. This may increase fingerprinting risk.');
    }
    if ($query_mode === 'full') {
      $warnings[] = $this->t('Full query string capture is enabled. Ensure you do not collect personal/sensitive data via URL parameters.');
    }
    if ($body_mode === 'full') {
      $warnings[] = $this->t('Full request body capture is enabled. This can collect sensitive data. Use only for short-term debugging.');
    }

    // Combined warning.
    if ($ip_mode === 'full' && $ua_mode === 'full') {
      $warnings[] = $this->t('Both full IP and full User-Agent capture are enabled. This significantly increases correlation/fingerprinting risk.');
    }

    return $warnings;
  }

}
