<?php

namespace Drupal\nodehive_mcp\Plugin\Mcp;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\mcp\Attribute\Mcp;
use Drupal\mcp\Plugin\McpPluginBase;
use Drupal\mcp\ServerFeatures\Tool;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * MCP plugin for updating NodeHive Spaces.
 */
#[Mcp(
  id: 'update-space-tool',
  name: new TranslatableMarkup('Update Space Tool'),
  description: new TranslatableMarkup('Provides MCP tool for updating existing NodeHive Spaces.'),
)]
class UpdateSpaceTool extends McpPluginBase implements ContainerFactoryPluginInterface {

  use StringTranslationTrait;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * {@inheritDoc}
   */
  public static function create(
    ContainerInterface $container,
    array $configuration,
    $plugin_id,
    $plugin_definition,
  ) {
    $instance = parent::create(
      $container, $configuration, $plugin_id, $plugin_definition
    );
    $instance->entityTypeManager = $container->get('entity_type.manager');
    $instance->moduleHandler = $container->get('module_handler');

    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration(): array {
    return [
      'enabled' => TRUE,
      'config' => [],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(
    array $form,
    FormStateInterface $form_state,
  ): array {
    // No specific configuration needed for this tool.
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function getTools(): array {
    return [
      new Tool(
        name: 'update-nodehive-space',
        description: 'Update an existing NodeHive Space.',
        inputSchema: [
          'type' => 'object',
          'properties' => [
            'space_id' => [
              'type' => 'integer',
              'description' => 'The ID of the space to update.',
            ],
            'label' => [
              'type' => 'string',
              'description' => 'The name/label of the space.',
            ],
            'space_url' => [
              'type' => 'string',
              'format' => 'uri',
              'description' => 'The URL for the space.',
            ],
            'space_type' => [
              'type' => 'string',
              'description' => 'Type of space (website, application, documentation).',
              'enum' => ['full_website', 'directory', 'database', 'other'],
            ],
            'status' => [
              'type' => 'boolean',
              'description' => 'Whether the space is enabled.',
            ],
            'tags' => [
              'type' => 'array',
              'items' => [
                'type' => 'string',
              ],
              'description' => 'Tags for the space.',
            ],
          ],
          'required' => ['space_id'],
        ],
      ),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function executeTool(string $toolId, mixed $arguments): array {
    if ($toolId === md5('update-nodehive-space')) {
      return $this->executeUpdateSpace($arguments);
    }

    throw new \InvalidArgumentException('Unknown tool: ' . $toolId);
  }

  /**
   * Execute the update space tool.
   */
  protected function executeUpdateSpace(array $arguments): array {
    try {
      // Validate space ID.
      if (empty($arguments['space_id'])) {
        throw new \InvalidArgumentException('Space ID is required.');
      }

      // Load the space.
      $space_storage = $this->entityTypeManager->getStorage('nodehive_space');
      $space = $space_storage->load($arguments['space_id']);

      if (!$space) {
        throw new \InvalidArgumentException('Space with ID ' . $arguments['space_id'] . ' not found.');
      }

      // Update fields if provided.
      $updated_fields = [];

      if (isset($arguments['label'])) {
        $space->set('label', $arguments['label']);
        $updated_fields[] = 'label';
      }

      if (isset($arguments['space_url'])) {
        $space->set('space_url', ['uri' => $arguments['space_url']]);
        $updated_fields[] = 'space_url';
      }

      if (isset($arguments['space_type'])) {
        $space->set('space_type', $arguments['space_type']);
        $updated_fields[] = 'space_type';
      }

      if (isset($arguments['status'])) {
        $space->set('status', $arguments['status']);
        $updated_fields[] = 'status';
      }

      // Handle tags if provided.
      if (isset($arguments['tags'])) {
        $tag_ids = $this->createOrGetTags($arguments['tags']);
        $space->set('tags', $tag_ids);
        $updated_fields[] = 'tags';
      }

      $space->save();

      return [
        [
          'type' => 'text',
          'text' => sprintf(
            'Successfully updated NodeHive Space "%s" (ID: %d). Updated fields: %s',
            $space->label(),
            $space->id(),
            implode(', ', $updated_fields)
          ),
        ],
      ];
    }
    catch (\Exception $e) {
      return [
        [
          'type' => 'text',
          'text' => 'Error updating space: ' . $e->getMessage(),
        ],
      ];
    }
  }

  /**
   * Create or get existing tags.
   */
  protected function createOrGetTags(array $tag_names): array {
    $tag_ids = [];
    $term_storage = $this->entityTypeManager->getStorage('taxonomy_term');

    foreach ($tag_names as $tag_name) {
      // Try to find existing tag.
      $existing_terms = $term_storage->loadByProperties([
        'name' => $tag_name,
        'vid' => 'nodehive_space_tags',
      ]);

      if (!empty($existing_terms)) {
        $tag_ids[] = reset($existing_terms)->id();
      }
      else {
        // Create new tag.
        $term = $term_storage->create([
          'name' => $tag_name,
          'vid' => 'nodehive_space_tags',
        ]);
        $term->save();
        $tag_ids[] = $term->id();
      }
    }

    return $tag_ids;
  }

  /**
   * {@inheritdoc}
   */
  public function hasAccess(): AccessResult {
    return AccessResult::allowedIfHasPermission(
      $this->currentUser, 'use nodehive mcp tools'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function checkRequirements(): bool {
    return $this->moduleHandler->moduleExists('nodehive_core') &&
           $this->moduleHandler->moduleExists('mcp');
  }

}
