<?php

declare(strict_types=1);

namespace Drupal\flowdrop_node_processor\Plugin\FlowDropNodeProcessor;

use Drupal\Core\Template\TwigEnvironment;
use Drupal\flowdrop\Attribute\FlowDropNodeProcessor;
use Drupal\flowdrop\DTO\ParameterBagInterface;
use Drupal\flowdrop\DTO\ValidationResult;
use Drupal\flowdrop\Plugin\FlowDropNodeProcessor\AbstractFlowDropNodeProcessor;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Executor for Prompt Template nodes.
 *
 * @internal This class is not part of the public API and may change without notice.
 */
#[FlowDropNodeProcessor(
  id: "prompt_template",
  label: new \Drupal\Core\StringTranslation\TranslatableMarkup("Prompt Template"),
  description: "Create prompts using templates with variable substitution",
  version: "1.0.0"
)]
class PromptTemplate extends AbstractFlowDropNodeProcessor {

  /**
   * Constructs a PromptTemplate object.
   *
   * @param array<string, mixed> $configuration
   *   The plugin configuration.
   * @param string $plugin_id
   *   The plugin ID.
   * @param mixed $plugin_definition
   *   The plugin definition.
   * @param \Drupal\Core\Template\TwigEnvironment $twig
   *   The Twig environment.
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    protected readonly TwigEnvironment $twig,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(
    ContainerInterface $container,
    array $configuration,
    $plugin_id,
    $plugin_definition,
  ): static {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get("twig"),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function validateParams(array $params): ValidationResult {
    // Prompt template can accept any inputs or none.
    return ValidationResult::success();
  }

  /**
   * {@inheritdoc}
   */
  public function process(ParameterBagInterface $params): array {
    $template = $params->get("template", "");
    $variables = $params->get("variables", []);
    if (is_array($variables)) {
      $context = $variables;
      $context['variables'] = $variables;
    }
    elseif (is_object($variables)) {
      $context = (array) $variables;
      $context['variables'] = $variables;
    }
    else {
      $context = [
        'variables' => $variables,
      ];
    }

    $prompt = $this->twig->createTemplate($template)
      ->render($context);

    return [
      "prompt" => $prompt,
      "template" => $template,
      "variables" => $variables,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getParameterSchema(): array {
    return [
      "type" => "object",
      "properties" => [
        "variables" => [
          "type" => "mixed",
          "title" => "Variables",
          "description" => "Default variables for the template",
          "default" => [],
        ],
        "template" => [
          "type" => "string",
          "title" => "Template",
          "description" => "The prompt template with variables in {{variable}} format",
          "default" => "",
          "format" => "template",
        ],
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getOutputSchema(): array {
    return [
      "type" => "object",
      "properties" => [
        "prompt" => [
          "type" => "string",
          "description" => "The generated prompt",
        ],
        "template" => [
          "type" => "string",
          "description" => "The original template",
        ],
        "variables" => [
          "type" => "mixed",
          "description" => "The variables used",
        ],
      ],
    ];
  }

}
