<?php

namespace Drupal\canvas_ai\Plugin\AiFunctionCall;

use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\ai\Attribute\FunctionCall;
use Drupal\ai\Base\FunctionCallBase;
use Drupal\ai\Service\FunctionCalling\ExecutableFunctionCallInterface;
use Drupal\ai\Service\FunctionCalling\FunctionCallInterface;
use Drupal\ai_agents\PluginInterfaces\AiAgentContextInterface;
use Drupal\Component\Serialization\Yaml;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\canvas_ai\AiResponseValidator;
use Drupal\canvas_ai\CanvasAiPageBuilderHelper;
use Drupal\canvas_ai\CanvasAiPermissions;
use Drupal\canvas_ai\CanvasAiTempStore;

/**
 * Function call to set the template data generated by AI.
 */
#[FunctionCall(
  id: 'canvas_ai:set_template_data',
  function_name: 'set_template_data',
  name: 'Set Template Data',
  description: 'This tool is used to add components across various regions of the page to build the desired templates. The component structure must be provided in valid YAML format.',
  group: 'modification_tools',
  context_definitions: [
    'component_structure' => new ContextDefinition(
      data_type: 'string',
      label: new TranslatableMarkup("Component structure in yml format"),
      description: new TranslatableMarkup("The component structure to store in YAML format."),
      required: TRUE,
    ),
  ],
)]
final class SetAIGeneratedTemplateData extends FunctionCallBase implements ExecutableFunctionCallInterface, AiAgentContextInterface, BuilderResponseFunctionCallInterface {

  /**
   * The Canvas page builder helper service.
   *
   * @var \Drupal\canvas_ai\CanvasAiPageBuilderHelper
   */
  protected CanvasAiPageBuilderHelper $pageBuilderHelper;

  /**
   * The logger factory.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected LoggerChannelFactoryInterface $loggerFactory;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected AccountProxyInterface $currentUser;

  /**
   * The Canvas AI temp store service.
   *
   * @var \Drupal\canvas_ai\CanvasAiTempStore
   */
  protected CanvasAiTempStore $tempStore;

  /**
   * The AI response validator service.
   *
   * @var \Drupal\canvas_ai\AiResponseValidator
   */
  protected AiResponseValidator $responseValidator;

  /**
   * Load from dependency injection container.
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): FunctionCallInterface | static {
    $instance = new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('ai.context_definition_normalizer'),
    );
    $instance->pageBuilderHelper = $container->get('canvas_ai.page_builder_helper');
    $instance->loggerFactory = $container->get('logger.factory');
    $instance->currentUser = $container->get('current_user');
    $instance->tempStore = $container->get('canvas_ai.tempstore');
    $instance->responseValidator = $container->get('canvas_ai.response_validator');
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function execute(): void {
    // Make sure that the user has the right permissions.
    if (!$this->currentUser->hasPermission(CanvasAiPermissions::USE_CANVAS_AI)) {
      throw new \Exception('The current user does not have the right permissions to run this tool.');
    }
    try {
      $component_structure = $this->getContextValue('component_structure');
      // Try to decode the YAML structure.
      try {
        $component_structure_array = Yaml::decode($component_structure);
      }
      catch (\Exception $e) {
        throw new \Exception('Invalid YAML format provided.');
      }

      // Validate if regions are correct.
      $current_layout = $this->tempStore->getData(CanvasAiTempStore::CURRENT_LAYOUT_KEY) ?? '';
      $layout_regions = $this->pageBuilderHelper->getRegionIndex($current_layout);
      foreach (\array_keys($component_structure_array) as $region) {
        if (!\array_key_exists($region, $layout_regions)) {
          $available_regions = implode(', ', \array_keys($layout_regions));
          throw new \Exception(\sprintf(
            'Region "%s" does not exist. Available regions are: %s.',
            $region,
            $available_regions
          ));
        }
      }

      // Validate the component structure for each region.
      foreach ($component_structure_array as $components) {
        $this->responseValidator->validateComponentStructure($components);
      }
      // Process the YAML structure for UI representation.
      $processed_structure = $this->pageBuilderHelper->processSetTemplateDataToolInput($component_structure_array, $current_layout);
      $this->setStructuredOutput($processed_structure);
      $this->setOutput('Template data has been successfully set.');
    }
    catch (\Exception $e) {
      $this->loggerFactory->get('canvas_ai')->error($e->getMessage());
      $this->setOutput(\sprintf('Failed to save: %s', $e->getMessage()));
    }
  }

}
