<?php

declare(strict_types=1);

namespace Drupal\flowdrop_runtime\Controller;

use Drupal\Component\Utility\Html;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\flowdrop_runtime\Entity\FlowDropWorkflowSnapshotInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Controller for viewing workflow snapshots.
 *
 * @internal This class is not part of the public API and may change without notice.
 */
final class SnapshotController extends ControllerBase {

  /**
   * The date formatter service.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected DateFormatterInterface $dateFormatter;

  /**
   * Constructs a new SnapshotController.
   *
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   */
  public function __construct(DateFormatterInterface $date_formatter) {
    $this->dateFormatter = $date_formatter;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): static {
    return new static(
      $container->get('date.formatter'),
    );
  }

  /**
   * Displays a workflow snapshot.
   *
   * @param \Drupal\flowdrop_runtime\Entity\FlowDropWorkflowSnapshotInterface $flowdrop_workflow_snapshot
   *   The workflow snapshot entity.
   *
   * @return array
   *   A render array.
   */
  public function view(FlowDropWorkflowSnapshotInterface $flowdrop_workflow_snapshot): array {
    $build = [];

    // Header information.
    $build['header'] = [
      '#type' => 'container',
      '#attributes' => ['class' => ['snapshot-header']],
    ];

    $build['header']['title'] = [
      '#type' => 'html_tag',
      '#tag' => 'h2',
      '#value' => $this->t('Snapshot: @id', ['@id' => $flowdrop_workflow_snapshot->id()]),
    ];

    // General information.
    $build['info'] = [
      '#type' => 'details',
      '#title' => $this->t('General Information'),
      '#open' => TRUE,
    ];

    $build['info']['table'] = [
      '#type' => 'table',
      '#rows' => [
        [$this->t('Entity ID'), $flowdrop_workflow_snapshot->id()],
        [$this->t('Execution ID'), $flowdrop_workflow_snapshot->getExecutionId() ?: '-'],
        [$this->t('Workflow ID'), $flowdrop_workflow_snapshot->getWorkflowId()],
        [$this->t('Workflow Version'), $flowdrop_workflow_snapshot->getWorkflowVersion()],
        [$this->t('Status'), $this->formatStatus($flowdrop_workflow_snapshot->getSnapshotStatus())],
        [$this->t('Thread ID'), $flowdrop_workflow_snapshot->getThreadId() ?: '-'],
        [$this->t('Current Node'), $flowdrop_workflow_snapshot->getCurrentNodeId() ?: '-'],
        [$this->t('Iteration Count'), $flowdrop_workflow_snapshot->getIterationCount()],
        [$this->t('Error'), $flowdrop_workflow_snapshot->getError() ?: '-'],
        [
          $this->t('Created'),
          $this->dateFormatter->format(
            (int) $flowdrop_workflow_snapshot->get('created')->value,
            'long'
          ),
        ],
        [$this->t('Updated'), $this->dateFormatter->format((int) $flowdrop_workflow_snapshot->getChangedTime(), 'long')],
      ],
    ];

    // Node states.
    $nodeStates = $flowdrop_workflow_snapshot->getNodeStates();
    $build['nodes'] = [
      '#type' => 'details',
      '#title' => $this->t('Node States (@count)', ['@count' => count($nodeStates)]),
      '#open' => TRUE,
    ];

    if (!empty($nodeStates)) {
      $nodeRows = [];
      foreach ($nodeStates as $nodeId => $nodeState) {
        $status = $nodeState['status'] ?? 'unknown';
        $nodeRows[] = [
          $nodeId,
          $this->formatStatus($status),
          ($nodeState['injected'] ?? FALSE) ? $this->t('Yes') : $this->t('No'),
          $nodeState['executionOrder'] ?? '-',
          $nodeState['error'] ?? '-',
        ];
      }

      $build['nodes']['table'] = [
        '#type' => 'table',
        '#header' => [
          $this->t('Node ID'),
          $this->t('Status'),
          $this->t('Injected'),
          $this->t('Execution Order'),
          $this->t('Error'),
        ],
        '#rows' => $nodeRows,
        '#empty' => $this->t('No node states recorded.'),
      ];
    }
    else {
      $build['nodes']['empty'] = [
        '#markup' => '<p>' . $this->t('No node states recorded.') . '</p>',
      ];
    }

    // Initial input.
    $initialInput = $flowdrop_workflow_snapshot->getInitialInput();
    $build['input'] = [
      '#type' => 'details',
      '#title' => $this->t('Initial Input'),
      '#open' => FALSE,
    ];

    $build['input']['data'] = [
      '#type' => 'html_tag',
      '#tag' => 'pre',
      '#value' => json_encode($initialInput, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES),
      '#attributes' => ['class' => ['snapshot-json']],
    ];

    // Metadata.
    $metadata = $flowdrop_workflow_snapshot->getSnapshotMetadata();
    $build['metadata'] = [
      '#type' => 'details',
      '#title' => $this->t('Metadata'),
      '#open' => FALSE,
    ];

    $build['metadata']['data'] = [
      '#type' => 'html_tag',
      '#tag' => 'pre',
      '#value' => json_encode($metadata, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES),
      '#attributes' => ['class' => ['snapshot-json']],
    ];

    // Messages (for StateGraph workflows).
    $messages = $flowdrop_workflow_snapshot->getMessages();
    if (!empty($messages)) {
      $build['messages'] = [
        '#type' => 'details',
        '#title' => $this->t('Messages (@count)', ['@count' => count($messages)]),
        '#open' => FALSE,
      ];

      $messageRows = [];
      foreach ($messages as $message) {
        $messageRows[] = [
          $message['role'] ?? 'unknown',
          substr($message['content'] ?? '', 0, 100) . (strlen($message['content'] ?? '') > 100 ? '...' : ''),
          isset($message['timestamp']) ? $this->dateFormatter->format($message['timestamp'], 'short') : '-',
        ];
      }

      $build['messages']['table'] = [
        '#type' => 'table',
        '#header' => [
          $this->t('Role'),
          $this->t('Content'),
          $this->t('Timestamp'),
        ],
        '#rows' => $messageRows,
      ];
    }

    // Data (for StateGraph workflows).
    $data = $flowdrop_workflow_snapshot->getData();
    if (!empty($data)) {
      $build['data'] = [
        '#type' => 'details',
        '#title' => $this->t('StateGraph Data'),
        '#open' => FALSE,
      ];

      $build['data']['content'] = [
        '#type' => 'html_tag',
        '#tag' => 'pre',
        '#value' => json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES),
        '#attributes' => ['class' => ['snapshot-json']],
      ];
    }

    // Raw JSON export.
    $build['raw'] = [
      '#type' => 'details',
      '#title' => $this->t('Raw JSON'),
      '#open' => FALSE,
    ];

    $snapshot = $flowdrop_workflow_snapshot->toWorkflowSnapshot();
    $build['raw']['data'] = [
      '#type' => 'html_tag',
      '#tag' => 'pre',
      '#value' => json_encode($snapshot->toArray(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES),
      '#attributes' => ['class' => ['snapshot-json', 'snapshot-raw']],
    ];

    // Add some basic styling.
    $build['#attached']['html_head'][] = [
      [
        '#type' => 'html_tag',
        '#tag' => 'style',
        '#value' => '
          .snapshot-json {
            background: #f5f5f5;
            padding: 15px;
            border-radius: 4px;
            overflow-x: auto;
            font-size: 12px;
            max-height: 400px;
            overflow-y: auto;
          }
          .snapshot-header h2 {
            margin-bottom: 20px;
          }
          .color-success { color: #28a745; }
          .color-error { color: #dc3545; }
          .color-warning { color: #ffc107; }
        ',
      ],
      'flowdrop_snapshot_styles',
    ];

    return $build;
  }

  /**
   * Formats a status value for display.
   *
   * @param string $status
   *   The status string.
   *
   * @return array
   *   A render array with styled status.
   */
  protected function formatStatus(string $status): array {
    $class = match ($status) {
      'completed' => 'color-success',
      'failed' => 'color-error',
      'running', 'paused', 'approval_required' => 'color-warning',
      default => '',
    };

    return [
      '#markup' => '<span class="' . $class . '">' . Html::escape(ucfirst($status)) . '</span>',
    ];
  }

}
