<?php

declare(strict_types=1);

namespace Drupal\flowdrop\Utility;

/**
 * Reads a stored node's node-type anchor (`data.metadata.node_type_id`).
 *
 * The node-type id is the single anchor persisted on a workflow node; every
 * other metadata field is derived from the node type entity + plugin schema and
 * re-injected on read. Runtime code reads `node_type_id` exclusively — there is
 * no fallback to the legacy `metadata.id` key.
 *
 * The rename `metadata.id` → `metadata.node_type_id` happens once, on save, in
 * FlowDropWorkflow::slimNodesForStorage (the migration seam). Every stored
 * workflow is brought forward by the post_update slim hook; the `@internal`
 * migration form re-runs it on demand for configs that re-enter via `drush cim`
 * after the update. Until a node is migrated it carries the legacy `id` with no
 * `node_type_id`, which reads here as anchor-less and would otherwise slip
 * silently through callers' "no anchor → skip" guards. The assert turns that
 * exact case — a legacy `id` present but no `node_type_id` — into a loud
 * failure in dev/CI, rather than a silent misroute. Legitimately anchor-less
 * (Notes and other non-executable nodes) carry neither key and pass the assert,
 * returning an empty string for the caller to handle.
 */
final class NodeAnchor {

  /**
   * Reads the node-type anchor from a stored node.
   *
   * @param array<string, mixed> $node
   *   A stored workflow node (with `data.metadata`).
   *
   * @return string
   *   The node-type id, or '' when the node carries no anchor.
   */
  public static function read(array $node): string {
    $metadata = $node['data']['metadata'] ?? [];
    return self::readMetadata(is_array($metadata) ? $metadata : []);
  }

  /**
   * Reads the node-type anchor from a node's `data.metadata` array.
   *
   * @param array<string, mixed> $metadata
   *   A node's metadata array.
   *
   * @return string
   *   The node-type id, or '' when the metadata carries no anchor.
   */
  public static function readMetadata(array $metadata): string {
    $id = $metadata['node_type_id'] ?? '';
    $id = is_string($id) ? $id : '';
    assert(
      !array_key_exists('id', $metadata) || $id !== '',
      'Un-migrated workflow node: legacy data.metadata.id is present without node_type_id. Re-save the workflow, run database updates, or use the FlowDrop node-identity migration form.'
    );
    return $id;
  }

}
