<?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;

/**
 * Form trigger node processor for form events.
 *
 * This processor is specifically designed for form-related events such as
 * form submission, validation, and other form lifecycle events. It provides
 * a dedicated trigger type in the workflow editor for form events.
 *
 * When a form 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: "form_trigger",
  label: new TranslatableMarkup("Form Trigger"),
  description: "Trigger workflow on form events (submit, validate, etc.)",
  version: "1.0.0"
)]
class FormTrigger extends AbstractTrigger implements ConfigEditProviderInterface {

  /**
   * {@inheritdoc}
   */
  public function process(ParameterBagInterface $params): array {
    // Return form data from initial data if available.
    // When triggered by a form event, only the triggering node executes,
    // and it has access to the form event data in the initial data context.
    $initial_data = $this->executionContext->getInitialData();

    // Extract form-specific data from the trigger context.
    $form_data = $initial_data["form"] ?? NULL;
    $form_values = $initial_data["form_values"] ?? NULL;

    // Structure the output for form events.
    return [
      "data" => $initial_data,
      "form" => $form_data,
      "form_values" => $form_values,
      "form_id" => $initial_data["form_id"] ?? NULL,
      "form_state" => $initial_data["form_state"] ?? NULL,
    ];
  }

  /**
   * {@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.
      // For form triggers, we can filter event types by category.
      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}&category=form",
        label: "Configure Form Trigger",
        icon: "mdi:form-select",
        description: "Open form 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?category=form",
        ],
      ),
      // Behavior options.
      // Prefer external link until JS library fully supports dynamic schema
      // forms.
      preferDynamicSchema: FALSE,
      showRefreshButton: TRUE,
      loadingMessage: "Loading form trigger configuration...",
      errorMessage: "Failed to load form trigger configuration",
    );
  }

  /**
   * {@inheritdoc}
   *
   * Defines the output schema for form trigger data passed to downstream nodes.
   */
  public function getOutputSchema(): array {
    return [
      "type" => "object",
      "title" => "Form Trigger Data",
      "description" => "Form event data from the trigger",
      "properties" => [
        "data" => [
          "type" => "object",
          "title" => "Output",
          "description" => "Complete trigger output containing form event data",
          "properties" => [
            "event_type" => [
              "type" => "string",
              "description" => "The form event that triggered this workflow (e.g., form.submit, form.validate)",
            ],
            "form_id" => [
              "type" => "string",
              "description" => "The form ID (e.g., node_article_form, user_register_form)",
            ],
            "form" => [
              "type" => "object",
              "description" => "Form structure and definition",
            ],
            "form_values" => [
              "type" => "object",
              "description" => "Submitted form values",
            ],
            "form_state" => [
              "type" => "object",
              "description" => "Form state information",
            ],
            "entity" => [
              "type" => ["object", "null"],
              "description" => "Entity associated with the form (if applicable)",
            ],
            "entity_type" => [
              "type" => ["string", "null"],
              "description" => "Entity type if form is entity-based",
            ],
            "entity_id" => [
              "type" => ["string", "null"],
              "description" => "Entity ID if form is entity-based",
            ],
            "bundle" => [
              "type" => ["string", "null"],
              "description" => "Entity bundle if form is entity-based",
            ],
            "user" => [
              "type" => ["object", "null"],
              "description" => "User who submitted the form",
              "properties" => [
                "uid" => [
                  "type" => ["integer", "null"],
                  "description" => "User ID",
                ],
                "username" => [
                  "type" => ["string", "null"],
                  "description" => "Username",
                ],
                "email" => [
                  "type" => ["string", "null"],
                  "description" => "Email address",
                ],
              ],
            ],
            "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",
            ],
            "trigger_execution" => [
              "type" => "boolean",
              "description" => "Indicates this was triggered by an event",
            ],
            "execution_source" => [
              "type" => "string",
              "description" => "Source of execution (form_event_trigger)",
            ],
            "trigger_timestamp" => [
              "type" => "integer",
              "description" => "Unix timestamp when trigger was processed",
            ],
            "trigger_type" => [
              "type" => "string",
              "description" => "Type of trigger (form_action)",
            ],
          ],
        ],
        "form" => [
          "type" => ["object", "null"],
          "title" => "Form Data",
          "description" => "Direct access to form data (alias for data.form)",
        ],
        "form_values" => [
          "type" => ["object", "null"],
          "title" => "Form Values",
          "description" => "Direct access to form values (alias for data.form_values)",
        ],
      ],
    ];
  }

}
