<?php

declare(strict_types=1);

namespace Drupal\flowdrop_trigger\Plugin\FlowDropEventType;

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\flowdrop_orchestration\Service\Orchestrator\OrchestratorHelperInterface;
use Drupal\flowdrop_trigger\Attribute\FlowDropEventType;
use Drupal\flowdrop_trigger\Enum\EventCategory;
use Drupal\flowdrop_trigger\Enum\TriggerExecutionMode;
use Drupal\flowdrop_trigger\FlowDropEventTypeInterface;
use Drupal\flowdrop_trigger\Plugin\FlowDropEventTypeBase;

/**
 * Event type for entity presave events.
 *
 * Triggers before an entity is saved to the database.
 * This event fires synchronously, allowing workflows to modify
 * the entity before it is persisted.
 *
 * IMPORTANT: This event uses synchronous orchestration by default
 * because it must complete before the entity save continues.
 *
 * @internal This class is not part of the public API and may change without notice.
 */
#[FlowDropEventType(
  id: "entity.presave",
  label: new TranslatableMarkup("Entity Presave"),
  description: new TranslatableMarkup("Triggered before an entity is saved (can modify entity)"),
  category: EventCategory::Entity,
  defaultOrchestrator: OrchestratorHelperInterface::SYNCHRONOUS,
  defaultExecutionMode: TriggerExecutionMode::Sync,
  supportedEntityTypes: [],
)]
class EntityPresave extends FlowDropEventTypeBase implements FlowDropEventTypeInterface {

  /**
   * {@inheritdoc}
   */
  public function getDefaultOrchestrator(): string {
    // Presave MUST be synchronous to allow entity modification.
    return OrchestratorHelperInterface::SYNCHRONOUS;
  }

  /**
   * {@inheritdoc}
   */
  public function getDefaultExecutionMode(): TriggerExecutionMode {
    // Presave MUST be sync to complete before save.
    return TriggerExecutionMode::Sync;
  }

  /**
   * {@inheritdoc}
   */
  public function extractTriggerData(
    ?EntityInterface $entity,
    ?EntityInterface $originalEntity = NULL,
    array $context = [],
  ): array {
    if ($entity === NULL) {
      throw new \InvalidArgumentException("Entity cannot be NULL for entity presave events.");
    }

    $data = $this->getBaseTriggerData($entity);

    // Add presave-specific data.
    $isNew = $entity->isNew();
    $data["is_new"] = $isNew;
    $data["operation"] = $isNew ? "insert" : "update";
    $data["has_original"] = $originalEntity !== NULL;
    $data["presave"] = TRUE;

    return $data;
  }

  /**
   * {@inheritdoc}
   */
  public function getParameterSchema(): array {
    $baseSchema = parent::getParameterSchema();

    // Add presave-specific configuration options.
    $baseSchema["properties"]["trigger_on_new"] = [
      "type" => "boolean",
      "title" => "Trigger on New Entities",
      "description" => "Whether to trigger for new entity creation",
      "default" => TRUE,
    ];

    $baseSchema["properties"]["trigger_on_update"] = [
      "type" => "boolean",
      "title" => "Trigger on Updates",
      "description" => "Whether to trigger for entity updates",
      "default" => TRUE,
    ];

    return $baseSchema;
  }

}
