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

/**
 * User trigger node processor for user action events.
 *
 * This processor is specifically designed for user-related events such as
 * login, logout, registration, and other user actions. It provides a
 * dedicated trigger type in the workflow editor for user events.
 *
 * When a user 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: "user_trigger",
  label: new TranslatableMarkup("User Trigger"),
  description: "Trigger workflow on user actions (login, logout, registration, etc.)",
  version: "1.0.0"
)]
class UserTrigger extends AbstractTrigger implements ConfigEditProviderInterface {

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

    // Extract user-specific data from the trigger context.
    $user_data = $initial_data["entity"] ?? NULL;

    // If entity data is available, ensure it's properly structured for
    // user events.
    if ($user_data !== NULL && is_array($user_data)) {
      return [
        "data" => $user_data,
        "user" => $user_data,
      ];
    }

    return [
      "data" => $initial_data,
      "user" => $initial_data["entity"] ?? NULL,
    ];
  }

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

  /**
   * {@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 user 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=user",
        label: "Configure User Trigger",
        icon: "mdi:account",
        description: "Open user 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=user",
        ],
      ),
      // Behavior options.
      // Prefer external link until JS library fully supports dynamic schema
      // forms.
      preferDynamicSchema: FALSE,
      showRefreshButton: TRUE,
      loadingMessage: "Loading user trigger configuration...",
      errorMessage: "Failed to load user trigger configuration",
    );
  }

  /**
   * {@inheritdoc}
   *
   * Defines the output schema for user trigger data passed to downstream nodes.
   */
  public function getOutputSchema(): array {
    return [
      "type" => "object",
      "title" => "User Trigger Data",
      "description" => "User event data from the trigger",
      "properties" => [
        "data" => [
          "type" => "object",
          "title" => "Output",
          "description" => "Complete trigger output containing user event data",
          "properties" => [
            "event_type" => [
              "type" => "string",
              "description" => "The user event that triggered this workflow (e.g., user.login, user.logout)",
            ],
            "entity_type" => [
              "type" => "string",
              "description" => "The entity type ID (always 'user' for user triggers)",
              "enum" => ["user"],
            ],
            "entity_id" => [
              "type" => "string",
              "description" => "The user ID",
            ],
            "bundle" => [
              "type" => "string",
              "description" => "The user bundle (typically 'user')",
            ],
            "entity" => [
              "type" => "object",
              "description" => "Complete serialized user entity data including all fields",
            ],
            "user" => [
              "type" => "object",
              "description" => "User-specific data extracted from the event",
              "properties" => [
                "username" => [
                  "type" => "string",
                  "description" => "The user's account name",
                ],
                "email" => [
                  "type" => "string",
                  "description" => "The user's email address",
                ],
                "roles" => [
                  "type" => "array",
                  "description" => "Array of user role IDs",
                  "items" => [
                    "type" => "string",
                  ],
                ],
                "last_login" => [
                  "type" => ["integer", "null"],
                  "description" => "Unix timestamp of last login (for login events)",
                ],
                "is_active" => [
                  "type" => "boolean",
                  "description" => "Whether the user account is active",
                ],
                "operation" => [
                  "type" => "string",
                  "description" => "The user operation (login, logout, cancel, etc.)",
                ],
              ],
            ],
            "original_entity" => [
              "type" => ["object", "null"],
              "description" => "Original user state before update (for update events)",
            ],
            "is_new" => [
              "type" => "boolean",
              "description" => "Whether the user 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",
            ],
            "trigger_execution" => [
              "type" => "boolean",
              "description" => "Indicates this was triggered by an event",
            ],
            "execution_source" => [
              "type" => "string",
              "description" => "Source of execution (user_event_trigger)",
            ],
            "trigger_timestamp" => [
              "type" => "integer",
              "description" => "Unix timestamp when trigger was processed",
            ],
            "trigger_type" => [
              "type" => "string",
              "description" => "Type of trigger (user_action)",
            ],
          ],
        ],
        "user" => [
          "type" => ["object", "null"],
          "title" => "User Data",
          "description" => "Direct access to user entity data (alias for data.user)",
        ],
      ],
    ];
  }

}
