<?php

namespace Drupal\ai_automators\PluginBaseClasses;

use Drupal\ai_automators\AiAutomatorInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;

/**
 * This is a base class that can be used for LLMs simple custom field rules.
 */
class CustomField extends RuleBase {

  /**
   * {@inheritDoc}
   */
  public function helpText() {
    return "This can help find complex amount of data and fill in complex field types with it.";
  }

  /**
   * {@inheritDoc}
   */
  public function placeholderText() {
    return "Based on the context extract all quotes and fill in the quote, a translated quote into english, the persons name and the persons role.\n\nContext:\n{{ context }}";
  }

  /**
   * {@inheritDoc}
   */
  public function checkIfEmpty($value, array $automatorConfig = []) {
    return isset($value[0]) && $value[0][key($value[0])] ? [1] : FALSE;
  }

  /**
   * {@inheritDoc}
   */
  public function buildAdvancedConfigurationForm(array $form, FormStateInterface $form_state, AiAutomatorInterface $automator): array {
    $fieldDefinition = $automator->getFieldDefinition();
    $config = $fieldDefinition->getConfig($automator->get('entity_type'))->getSettings();

    if (isset($config['field_settings'])) {
      foreach ($config['field_settings'] as $key => $value) {
        $form["llm_custom_value_" . $key] = [
          '#type' => 'textarea',
          '#title' => $value['widget_settings']['label'] ?? $key,
          '#description' => $this->t('One sentence how the %label should be filled out. For instance "the original quote".', [
            '%label' => $value['widget_settings']['label'] ?? $key,
          ]),
          '#attributes' => [
            'rows' => 2,
          ],
          '#default_value' => $this->configuration["llm_custom_value_" . $key] ?? '',
          '#weight' => 14,
        ];

        $form["llm_custom_oneshot_" . $key] = [
          '#type' => 'textarea',
          '#title' => $this->t('Example %label', [
            '%label' => $value['widget_settings']['label'] ?? $key,
          ]),
          '#description' => $this->t('One example %label of a filled out value for one shot learning. For instance "To be or not to be".', [
            '%label' => $value['widget_settings']['label'] ?? $key,
          ]),
          '#attributes' => [
            'rows' => 2,
          ],
          '#default_value' => $this->configuration["llm_custom_oneshot_" . $key] ?? '',
          '#weight' => 14,
        ];
      }
    }

    return $form;
  }

  /**
   * {@inheritDoc}
   */
  public function generate(ContentEntityInterface $entity, FieldDefinitionInterface $fieldDefinition, array $automatorConfig) {
    // Generate the real prompt if needed.
    $prompts = parent::generate($entity, $fieldDefinition, $automatorConfig);
    $this->setStructuredOutputSchema($entity, $fieldDefinition, $automatorConfig);

    $oneShot = [];
    foreach ($automatorConfig as $key => $value) {
      if (str_starts_with($key, 'llm_custom_oneshot_')) {
        $oneShot[substr($key, strlen('llm_custom_oneshot_'))] = $value;
      }
    }

    // Keep one-shot guidance for better consistency in generation.
    foreach ($prompts as $key => $prompt) {
      if ($oneShot) {
        $prompt .= "\n\nExample values for one entry:\n" . json_encode($oneShot) . "\n";
      }
      $prompts[$key] = $prompt;
    }

    $total = [];
    $instance = $this->prepareLlmInstance('chat', $automatorConfig);
    foreach ($prompts as $prompt) {
      // Create new messages.
      $values = $this->runChatMessage($prompt, $automatorConfig, $instance, $entity);

      if (!empty($values)) {
        $total = array_merge_recursive($total, $values);
      }
    }
    return $total;
  }

  /**
   * {@inheritDoc}
   */
  public function verifyValue(ContentEntityInterface $entity, $value, FieldDefinitionInterface $fieldDefinition, array $automatorConfig) {
    // Should be array, otherwise no validation for now.
    if (!is_array($value)) {
      return FALSE;
    }
    // Otherwise it is ok.
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  protected function getStructuredOutputValueSchema(ContentEntityInterface $entity, FieldDefinitionInterface $fieldDefinition, array $automatorConfig): array {
    $properties = [];
    foreach ($automatorConfig as $key => $value) {
      if (str_starts_with($key, 'llm_custom_value_')) {
        $properties[substr($key, strlen('llm_custom_value_'))] = [
          'type' => 'string',
        ];
      }
    }

    if (!$properties) {
      return parent::getStructuredOutputValueSchema($entity, $fieldDefinition, $automatorConfig);
    }

    return [
      'type' => 'object',
      'additionalProperties' => FALSE,
      'required' => array_keys($properties),
      'properties' => $properties,
    ];
  }

}
