<?php

declare(strict_types=1);

namespace Drupal\flowdrop_trigger\Plugin\FlowDropNodeProcessor;

use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\flowdrop\Attribute\FlowDropNodeProcessor;
use Drupal\flowdrop\DTO\ConfigEdit\ConfigEdit;
use Drupal\flowdrop\DTO\ConfigEdit\ConfigEditApiEndpoints;
use Drupal\flowdrop\DTO\ConfigEdit\DynamicSchemaEndpoint;
use Drupal\flowdrop\DTO\ConfigEdit\ExternalEditLink;
use Drupal\flowdrop\DTO\ParameterBagInterface;
use Drupal\flowdrop\Plugin\FlowDropNodeProcessor\ConfigEditProviderInterface;

/**
 * Trigger node processor backed by FlowDropTriggerConfig entity.
 *
 * This processor represents a trigger in the visual workflow editor.
 * When a trigger node is dropped in the editor, a FlowDropTriggerConfig
 * entity is created via the API. The node stores only a reference to the
 * entity via trigger_config_id.
 *
 * Actual trigger configuration (event type, conditions, orchestrator settings)
 * is loaded dynamically from the entity via the trigger config API.
 *
 * Entity ID format: {workflow_id}__{node_id}
 *
 * Implements ConfigEditProviderInterface to provide dynamic configuration
 * editing capabilities via REST API and admin forms.
 *
 * @see \Drupal\flowdrop_trigger\Entity\FlowDropTriggerConfig
 * @see \Drupal\flowdrop_trigger\Controller\TriggerConfigApiController
 * @see \Drupal\flowdrop\Plugin\FlowDropNodeProcessor\ConfigEditProviderInterface
 */
#[FlowDropNodeProcessor(
  id: "trigger",
  label: new TranslatableMarkup("Trigger"),
  description: "Trigger workflow on events (entity changes, user actions, cron, etc.)",
  version: "2.0.0"
)]
class EntityTrigger extends AbstractTrigger implements ConfigEditProviderInterface {

  /**
   * {@inheritdoc}
   */
  protected function process(ParameterBagInterface $params): array {
    // Return entity data from initial data if available.
    // When triggered by an event, only the triggering node executes,
    // and it has access to the entity event data in the initial data context.
    $initial_data = $this->executionContext->getInitialData();
    return [
      'data' => $initial_data['entity'] ?? NULL,
    ];
  }

  /**
   * {@inheritdoc}
   */
  protected function processTriggerData(array $triggerData, array $params): array {
    // Trigger data is passed from TriggerManager with entity context.
    return array_merge($triggerData, [
      "trigger_execution" => TRUE,
      "execution_source" => "event_trigger",
      "trigger_timestamp" => time(),
    ]);
  }

  /**
   * {@inheritdoc}
   *
   * Minimal schema - trigger config is managed via the configure endpoint
   * which accepts workflow and node IDs. No need to store trigger_config_id
   * in the node as it's derived from workflow_id and node_id.
   */
  public function getParameterSchema(): array {
    $baseSchema = parent::getParameterSchema();

    // Terminal node variant - triggers are always "start" nodes.
    $baseSchema["properties"]["variant"] = [
      "type" => "string",
      "title" => "Variant",
      "description" => "Terminal node variant (start for triggers)",
      "enum" => ["start"],
      "default" => "start",
      "format" => "hidden",
    ];
    return $baseSchema;
  }

  /**
   * {@inheritdoc}
   */
  public function getConfigEdit(): ConfigEdit {
    return new ConfigEdit(
      // Dynamic schema from REST endpoint.
      // Schema endpoint returns JSON Schema for trigger configuration.
      dynamicSchema: new DynamicSchemaEndpoint(
        url: "/api/flowdrop/triggers/schema",
        method: "GET",
        // Map URL variables to node data.
        parameterMapping: [
          "event_type" => "config.event_type",
        ],
        // Don't cache - schema varies by event_type.
        cacheSchema: FALSE,
        timeout: 10000,
      ),
      // External edit link - opens admin form in new tab.
      // Uses a single configure endpoint that redirects to add or edit form
      // based on whether the trigger config exists.
      externalEditLink: new ExternalEditLink(
        url: "/admin/flowdrop/triggers/configure?workflow={workflowId}&node={nodeId}",
        label: "Configure Trigger",
        icon: "mdi:cog",
        description: "Open trigger configuration form in admin interface",
        // Map URL variables to node data.
        parameterMapping: [
          "workflowId" => "workflowId",
          "nodeId" => "id",
        ],
        openInNewTab: TRUE,
      ),
      // API endpoints for CRUD operations.
      api: new ConfigEditApiEndpoints(
        create: "/api/flowdrop/triggers",
        read: "/api/flowdrop/triggers/{trigger_config_id}",
        update: "/api/flowdrop/triggers/{trigger_config_id}",
        delete: "/api/flowdrop/triggers/{trigger_config_id}",
        custom: [
          "eventTypes" => "/api/flowdrop/triggers/event-types",
        ],
      ),
      // Behavior options.
      // Prefer external link until JS library fully supports dynamic schema
      // forms.
      preferDynamicSchema: FALSE,
      showRefreshButton: TRUE,
      loadingMessage: "Loading trigger configuration...",
      errorMessage: "Failed to load trigger configuration",
    );
  }

  /**
   * {@inheritdoc}
   *
   * Defines the output schema for trigger data passed to downstream nodes.
   */
  public function getOutputSchema(): array {
    return [
      "type" => "object",
      "title" => "Trigger Data",
      "description" => "Event data from the trigger",
      "properties" => [
        "data" => [
          "type" => "object",
          "title" => "Output",
          "description" => "Complete trigger output containing event data",
          "properties" => [
            "event_type" => [
              "type" => "string",
              "description" => "The event that triggered this workflow (e.g., entity.insert)",
            ],
            "entity_type" => [
              "type" => "string",
              "description" => "The entity type ID (e.g., node, user)",
            ],
            "entity_id" => [
              "type" => "string",
              "description" => "The entity ID",
            ],
            "bundle" => [
              "type" => "string",
              "description" => "The entity bundle (e.g., article, page)",
            ],
            "entity" => [
              "type" => "object",
              "description" => "Complete serialized entity data including all fields",
            ],
            "original_entity" => [
              "type" => "object",
              "description" => "Original entity state before update (for update events)",
            ],
            "is_new" => [
              "type" => "boolean",
              "description" => "Whether the entity is new",
            ],
            "timestamp" => [
              "type" => "integer",
              "description" => "Unix timestamp when the event occurred",
            ],
            "trigger_config_id" => [
              "type" => "string",
              "description" => "The ID of the trigger configuration that fired",
            ],
            "trigger_node_id" => [
              "type" => "string",
              "description" => "The node ID of the trigger in the workflow",
            ],
          ],
        ],
      ],
    ];
  }

}
