<?php

declare(strict_types=1);

namespace Drupal\flowdrop_session\EventSubscriber;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\flowdrop\Utility\Duration;
use Drupal\flowdrop_pipeline\Constants\PipelineStatus;
use Drupal\flowdrop_session\Constants\MessageAnnotation;
use Drupal\flowdrop_session\Entity\FlowDropSessionInterface;
use Drupal\flowdrop_session\Service\SessionServiceInterface;
use Drupal\flowdrop_runtime\Event\PipelineCompletedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Writes a system message when a pipeline run finishes.
 *
 * Emits a 'completed', 'failed', or 'paused' notice after all per-job messages.
 * System messages render as centered notices in the playground, visually
 * distinct from per-node job log rows.
 *
 * @internal This class is not part of the public API and may change without notice.
 */
class PipelineStatusSubscriber implements EventSubscriberInterface {

  public function __construct(
    private readonly EntityTypeManagerInterface $entityTypeManager,
    private readonly SessionServiceInterface $sessionService,
  ) {}

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    return [
      PipelineCompletedEvent::NAME => 'onPipelineCompleted',
    ];
  }

  /**
   * Writes a pipeline status log message to the session.
   */
  public function onPipelineCompleted(PipelineCompletedEvent $event): void {
    $playgroundContext = $event->getPlaygroundContext();
    if ($playgroundContext === NULL) {
      return;
    }

    /** @var \Drupal\flowdrop_session\Entity\FlowDropSessionInterface|null $session */
    $session = $this->entityTypeManager
      ->getStorage('flowdrop_session')
      ->load($playgroundContext->getSessionId());

    if (!$session instanceof FlowDropSessionInterface) {
      return;
    }

    $duration = Duration::formatMicroseconds($event->getExecutionTimeUs());
    $status = $event->getStatus();
    [$bareContent, $level, $outcomeLabel, $outcomeColor] = match ($status) {
      PipelineStatus::FAILED => ["failed after {$duration}", 'error', 'failed', MessageAnnotation::COLOR_ERROR],
      PipelineStatus::PAUSED => ["paused after {$duration}", 'warning', 'paused', MessageAnnotation::COLOR_WARNING],
      default => ["completed in {$duration}", 'info', 'completed', MessageAnnotation::COLOR_SUCCESS],
    };

    $hierarchy = $playgroundContext->getHierarchy();
    $isNested = count($hierarchy) >= 2;
    $hasHierarchy = $hierarchy !== [];
    $isSuccess = $status !== PipelineStatus::FAILED && $status !== PipelineStatus::PAUSED;

    // Card display is reserved for runs that need attention (failed or
    // paused) — those should grab the eye with the full hierarchy +
    // status tag layout. Successful runs render as a thin notice so the
    // stream doesn't terminate on a heavyweight row for every happy-
    // path execution; the per-node job logs above already show what
    // happened.
    $useCard = $hasHierarchy && !$isSuccess;

    $metadata = ['level' => $level];
    if ($hasHierarchy) {
      $metadata[MessageAnnotation::METADATA_KEY_HIERARCHY] = $hierarchy;
    }

    if ($useCard) {
      // Card body omits the leaf workflow label — the hierarchy chip
      // strip rendered above the body already shows it, and repeating
      // it produced "Calculator / Calculator completed in 230ms" rows.
      $metadata[MessageAnnotation::METADATA_KEY_DISPLAY] = MessageAnnotation::DISPLAY_CARD;

      $tags = [];
      if ($isNested) {
        $tags[] = [
          'id' => 'kind',
          'label' => 'sub-workflow',
          'color' => MessageAnnotation::COLOR_INFO,
          'variant' => MessageAnnotation::VARIANT_SUBTLE,
          'type' => 'kind',
        ];
      }
      $tags[] = [
        'id' => 'status',
        'label' => $outcomeLabel,
        'color' => $outcomeColor,
        'variant' => MessageAnnotation::VARIANT_SOLID,
        'type' => 'status',
      ];
      $tags[] = [
        'id' => 'duration',
        'label' => $duration,
        'color' => MessageAnnotation::COLOR_MUTED,
        'variant' => MessageAnnotation::VARIANT_SUBTLE,
        'type' => 'duration',
      ];
      $metadata[MessageAnnotation::METADATA_KEY_TAGS] = $tags;
      $content = $bareContent;
    }
    else {
      // Successful run, or no hierarchy data at all. Body is just the
      // outcome — the playground renders the hierarchy chip strip on
      // notice rows too, so prepending the leaf label produced
      // "Ask Confirmation / Ask Confirmation completed in 66.5ms" rows.
      // Explicit display preserves the layout independent of any future
      // role-default changes.
      $metadata[MessageAnnotation::METADATA_KEY_DISPLAY] = MessageAnnotation::DISPLAY_NOTICE;
      $content = $bareContent;
    }

    $this->sessionService->addSystemMessage(
      $session,
      $content,
      $metadata,
      $event->getExecutionId(),
    );
  }

}
