<?php

namespace Drupal\eb\Plugin\EbOperation;

use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\eb\Attribute\EbOperation;
use Drupal\eb\PluginBase\OperationBase;
use Drupal\eb\Result\ExecutionResult;
use Drupal\eb\Result\PreviewResult;
use Drupal\eb\Result\RollbackResult;
use Drupal\eb\Result\ValidationResult;

/**
 * Operation for creating menus.
 */
#[EbOperation(
  id: 'create_menu',
  label: new TranslatableMarkup('Create Menu'),
  description: new TranslatableMarkup('Creates a new menu'),
  operationType: 'create',
)]
class CreateMenuOperation extends OperationBase {

  /**
   * {@inheritdoc}
   */
  public function validate(): ValidationResult {
    $result = new ValidationResult();

    // Validate required fields.
    $this->validateRequiredFields(['menu_id', 'label'], $result);

    if (!$result->isValid()) {
      return $result;
    }

    $menu_id = $this->getDataValue('menu_id');

    // Check if menu already exists.
    $existing_menu = $this->entityTypeManager
      ->getStorage('menu')
      ->load($menu_id);

    if ($existing_menu) {
      $result->addError(
        $this->t('Menu "@menu" already exists.', ['@menu' => $menu_id]),
        'menu_exists'
      );
    }

    return $result;
  }

  /**
   * {@inheritdoc}
   */
  public function preview(): PreviewResult {
    $menu_id = $this->getDataValue('menu_id');
    $label = $this->getDataValue('label');
    $description = $this->getDataValue('description', '');

    $preview = new PreviewResult();
    $preview->addOperation(
      'create',
      'menu',
      $menu_id,
      $this->t('Create menu "@label" (@name)', [
        '@label' => $label,
        '@name' => $menu_id,
      ])
    );

    $details = [
      'Menu Name' => $menu_id,
      'Label' => $label,
    ];

    if (!empty($description)) {
      $details['Description'] = $description;
    }

    $preview->addDetails($details);

    return $preview;
  }

  /**
   * {@inheritdoc}
   */
  public function execute(): ExecutionResult {
    $menu_id = $this->getDataValue('menu_id');
    $label = $this->getDataValue('label');
    $description = $this->getDataValue('description', '');

    return $this->executeWithErrorHandling(function () use ($menu_id, $label, $description) {
      // Create the menu entity.
      $menu = $this->entityTypeManager->getStorage('menu')->create([
        'id' => $menu_id,
        'label' => $label,
        'description' => $description,
      ]);

      $menu->save();

      $result = new ExecutionResult(TRUE);
      $result->addMessage($this->t('Menu "@label" created successfully.', [
        '@label' => $label,
      ]));

      $result->addAffectedEntity([
        'type' => 'menu',
        'id' => $menu_id,
        'label' => $label,
      ]);

      $result->setRollbackData([
        'menu_id' => $menu_id,
      ]);

      return $result;
    }, 'create menu');
  }

  /**
   * {@inheritdoc}
   */
  public function rollback(): RollbackResult {
    $rollback_data = $this->getRequiredRollbackData();

    return $this->rollbackWithErrorHandling(function () use ($rollback_data) {
      $menu_id = $rollback_data['menu_id'];

      // Load and delete the menu.
      $menu = $this->entityTypeManager->getStorage('menu')->load($menu_id);

      if ($menu) {
        $menu->delete();
        $result = new RollbackResult(TRUE);
        $result->addMessage($this->t('Menu "@menu" deleted successfully.', [
          '@menu' => $menu_id,
        ]));
        $result->addRestoredEntity([
          'type' => 'menu',
          'id' => $menu_id,
        ]);
        $this->logInfo('Rolled back menu creation: @menu', ['@menu' => $menu_id]);
      }
      else {
        $result = new RollbackResult(FALSE);
        $result->addMessage($this->t('Menu "@menu" not found for rollback.', [
          '@menu' => $menu_id,
        ]));
      }

      return $result;
    }, 'menu creation');
  }

}
