<?php

declare(strict_types=1);

namespace Drupal\flowdrop_workflow\Form;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\flowdrop_workflow\Entity\FlowDropWorkflow;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Re-saves every stored workflow into the slim node-identity format.
 *
 * The post_update slim-node-identity hook already migrates every workflow on
 * `drush updb`. This form is the worst-case manual
 * re-trigger: config that re-enters active storage AFTER the update ran — `cim`
 * of
 * 1.x YAML, a hand-edited config import — lands with the legacy `metadata.id`
 * anchor and no `node_type_id`, which runtime readers (via NodeAnchor) reject
 * loudly. Re-saving each workflow runs FlowDropWorkflow::preSave, which renames
 * the anchor and drops the legacy `data.nodeId`. Idempotent — an already-slim
 * workflow re-saves unchanged.
 *
 * @internal
 *   Operational recovery tool, not an API. No backwards-compatibility promise.
 */
final class MigrateNodeIdentityForm extends ConfirmFormBase {

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

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

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

  /**
   * {@inheritdoc}
   */
  public function getQuestion(): TranslatableMarkup {
    return $this->t('Re-save all workflows into the slim node-identity format?');
  }

  /**
   * {@inheritdoc}
   */
  public function getDescription(): TranslatableMarkup {
    return $this->t('Each stored workflow is re-saved so its nodes adopt the current <code>data.metadata.node_type_id</code> anchor and drop the legacy <code>data.nodeId</code>. Run this only if workflows imported from 1.x config are failing to render or execute. The operation is idempotent and safe to repeat.');
  }

  /**
   * {@inheritdoc}
   */
  public function getConfirmText(): TranslatableMarkup {
    return $this->t('Re-save workflows');
  }

  /**
   * {@inheritdoc}
   */
  public function getCancelUrl(): Url {
    return Url::fromRoute('entity.flowdrop_workflow.collection');
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    $storage = $this->entityTypeManager->getStorage('flowdrop_workflow');
    $ids = $storage->getQuery()->accessCheck(FALSE)->execute();

    $count = 0;
    foreach ($storage->loadMultiple($ids) as $entity) {
      if (!$entity instanceof FlowDropWorkflow) {
        continue;
      }
      // No setSyncing(): let preSave slim and rename the stored nodes.
      $entity->save();
      $count++;
    }

    $this->messenger()->addStatus($this->formatPlural(
      $count,
      'Re-saved 1 workflow into the slim node-identity format.',
      'Re-saved @count workflows into the slim node-identity format.',
    ));
    $form_state->setRedirectUrl($this->getCancelUrl());
  }

}
