<?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 exploring content type structures.
 */
#[Mcp(
  id: 'explore-content-type-tool',
  name: new TranslatableMarkup('Explore Content Type Tool'),
  description: new TranslatableMarkup('Provides MCP tool for exploring content type structures and field definitions.'),
)]
class ExploreContentTypeTool 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;

  /**
   * The language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * The entity field manager.
   *
   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $entityFieldManager;

  /**
   * The content translation manager.
   *
   * @var \Drupal\content_translation\ContentTranslationManagerInterface
   */
  protected $contentTranslationManager;

  /**
   * {@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');
    $instance->languageManager = $container->get('language_manager');
    $instance->entityFieldManager = $container->get('entity_field.manager');
    if ($container->has('content_translation.manager')) {
      $instance->contentTranslationManager = $container->get('content_translation.manager');
    }

    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: 'explore-content-type',
        description: 'Explore the structure and field definitions of a content type to understand what fields are available for node creation, including language and translation capabilities.',
        inputSchema: [
          'type' => 'object',
          'properties' => [
            'content_type' => [
              'type' => 'string',
              'description' => 'The machine name of the content type to explore (e.g., article, page).',
            ],
            'include_field_details' => [
              'type' => 'boolean',
              'description' => 'Include detailed field configuration and constraints.',
              'default' => TRUE,
            ],
            'include_language_info' => [
              'type' => 'boolean',
              'description' => 'Include language and translation information.',
              'default' => TRUE,
            ],
            'space_id' => [
              'type' => 'integer',
              'description' => 'Optional: Filter to show only content types allowed in a specific space.',
            ],
          ],
          'required' => ['content_type'],
        ],
      ),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function executeTool(string $toolId, mixed $arguments): array {
    if ($toolId === md5('explore-content-type')) {
      return $this->executeExploreContentType($arguments);
    }

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

  /**
   * Execute the explore content type tool.
   */
  protected function executeExploreContentType(array $arguments): array {
    try {
      // Validate content type.
      if (empty($arguments['content_type'])) {
        throw new \InvalidArgumentException('Content type is required.');
      }

      // Load the content type.
      $node_type_storage = $this->entityTypeManager->getStorage('node_type');
      $node_type = $node_type_storage->load($arguments['content_type']);

      if (!$node_type) {
        throw new \InvalidArgumentException('Content type "' . $arguments['content_type'] . '" does not exist.');
      }

      // Check if content type is allowed in space if space_id is provided.
      $space_id = $arguments['space_id'] ?? NULL;
      if ($space_id) {
        $space_storage = $this->entityTypeManager->getStorage('nodehive_space');
        $space = $space_storage->load($space_id);

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

        $allowed_content_types = [];
        if (!$space->get('content_types')->isEmpty()) {
          foreach ($space->get('content_types')->referencedEntities() as $content_type_entity) {
            $allowed_content_types[] = $content_type_entity->id();
          }

          if (!empty($allowed_content_types) && !in_array($arguments['content_type'], $allowed_content_types)) {
            return [
              [
                'type' => 'text',
                'text' => sprintf(
                  'Content type "%s" is not allowed in space "%s". Allowed types: %s',
                  $arguments['content_type'],
                  $space->label(),
                  implode(', ', $allowed_content_types)
                ),
              ],
            ];
          }
        }
      }

      $include_field_details = $arguments['include_field_details'] ?? TRUE;
      $include_language_info = $arguments['include_language_info'] ?? TRUE;

      $exploration_data = [
        'content_type_info' => $this->getContentTypeInfo($node_type),
        'fields' => $include_field_details ? $this->getContentTypeFields($arguments['content_type']) : [],
        'language_info' => $include_language_info ? $this->getLanguageInfo($arguments['content_type']) : [],
        'space_context' => $space_id ? $this->getSpaceContext($space_id) : NULL,
      ];

      return [
        [
          'type' => 'text',
          'text' => $this->formatContentTypeExploration($exploration_data),
        ],
      ];
    }
    catch (\Exception $e) {
      return [
        [
          'type' => 'text',
          'text' => 'Error exploring content type: ' . $e->getMessage(),
        ],
      ];
    }
  }

  /**
   * Get content type information.
   */
  protected function getContentTypeInfo($node_type): array {
    return [
      'id' => $node_type->id(),
      'label' => $node_type->label(),
      'description' => $node_type->getDescription() ?: 'No description available.',
    ];
  }

  /**
   * Get content fields for a content type.
   */
  protected function getContentTypeFields($content_type_id): array {
    $field_definitions = $this->entityFieldManager->getFieldDefinitions('node', $content_type_id);

    $fields = [];
    foreach ($field_definitions as $field_name => $field_definition) {
      // Skip computed fields and internal fields.
      $internal_fields = [
        'nid', 'uuid', 'vid', 'langcode', 'type',
        'revision_timestamp', 'revision_uid', 'revision_log',
      ];
      if ($field_definition->isComputed() || in_array($field_name, $internal_fields)) {
        continue;
      }

      $field_info = [
        'name' => $field_name,
        'label' => (string) $field_definition->getLabel(),
        'type' => $field_definition->getType(),
        'description' => (string) $field_definition->getDescription() ?: 'No description available.',
        'required' => $field_definition->isRequired(),
        'cardinality' => $field_definition->getFieldStorageDefinition()->getCardinality(),
        'settings' => [],
      ];

      // Add field-specific settings.
      $settings = $field_definition->getSettings();
      if (!empty($settings)) {
        $field_info['settings'] = $this->formatFieldSettings($field_definition->getType(), $settings);
      }

      // Add form display information if available.
      $form_display = $this->entityTypeManager
        ->getStorage('entity_form_display')
        ->load('node.' . $content_type_id . '.default');

      if ($form_display) {
        $component = $form_display->getComponent($field_name);
        if ($component) {
          $field_info['form_widget'] = $component['type'] ?? 'default';
          $field_info['form_settings'] = $component['settings'] ?? [];
        }
      }

      $fields[] = $field_info;
    }

    return $fields;
  }

  /**
   * Format field settings for display.
   */
  protected function formatFieldSettings($field_type, array $settings): array {
    $formatted_settings = [];

    switch ($field_type) {
      case 'string':
      case 'string_long':
        if (isset($settings['max_length'])) {
          $formatted_settings['max_length'] = $settings['max_length'];
        }
        break;

      case 'text':
      case 'text_long':
      case 'text_with_summary':
        if (isset($settings['allowed_formats'])) {
          $formatted_settings['allowed_formats'] = $settings['allowed_formats'];
        }
        break;

      case 'entity_reference':
        if (isset($settings['target_type'])) {
          $formatted_settings['target_type'] = $settings['target_type'];
        }
        if (isset($settings['handler_settings']['target_bundles'])) {
          $formatted_settings['target_bundles'] = array_keys($settings['handler_settings']['target_bundles']);
        }
        break;

      case 'image':
        if (isset($settings['file_extensions'])) {
          $formatted_settings['allowed_extensions'] = $settings['file_extensions'];
        }
        if (isset($settings['max_filesize'])) {
          $formatted_settings['max_filesize'] = $settings['max_filesize'];
        }
        break;

      case 'list_string':
      case 'list_integer':
        if (isset($settings['allowed_values'])) {
          $formatted_settings['allowed_values'] = $settings['allowed_values'];
        }
        break;
    }

    return $formatted_settings;
  }

  /**
   * Get space context information.
   */
  protected function getSpaceContext($space_id): array {
    $space_storage = $this->entityTypeManager->getStorage('nodehive_space');
    $space = $space_storage->load($space_id);

    if (!$space) {
      return [];
    }

    $context = [
      'space_id' => $space->id(),
      'space_label' => $space->label(),
      'allowed_content_types' => [],
    ];

    if (!$space->get('content_types')->isEmpty()) {
      foreach ($space->get('content_types')->referencedEntities() as $content_type) {
        $context['allowed_content_types'][] = [
          'id' => $content_type->id(),
          'label' => $content_type->label(),
        ];
      }
    }

    return $context;
  }

  /**
   * Get language and translation information for a content type.
   */
  protected function getLanguageInfo($content_type_id): array {
    $language_info = [
      'multilingual_enabled' => $this->moduleHandler->moduleExists('language'),
      'content_translation_enabled' => $this->moduleHandler->moduleExists('content_translation'),
      'available_languages' => [],
      'default_language' => '',
      'translation_enabled_for_type' => FALSE,
    ];

    // Get default language.
    $default_language = $this->languageManager->getDefaultLanguage();
    $language_info['default_language'] = $default_language->getId();

    // Get all available languages if language module is enabled.
    if ($language_info['multilingual_enabled']) {
      $languages = $this->languageManager->getLanguages();
      foreach ($languages as $langcode => $language) {
        $language_info['available_languages'][] = [
          'langcode' => $langcode,
          'name' => $language->getName(),
          'direction' => $language->getDirection(),
          'is_default' => $langcode === $default_language->getId(),
        ];
      }

      // Check if content translation is enabled for this content type.
      if ($language_info['content_translation_enabled'] && $this->contentTranslationManager) {
        $language_info['translation_enabled_for_type'] = $this->contentTranslationManager->isEnabled('node', $content_type_id);

        if ($language_info['translation_enabled_for_type']) {
          // Get translatable fields.
          $field_definitions = $this->entityFieldManager->getFieldDefinitions('node', $content_type_id);
          $translatable_fields = [];

          foreach ($field_definitions as $field_name => $field_definition) {
            if ($field_definition->isTranslatable()) {
              $translatable_fields[] = [
                'name' => $field_name,
                'label' => (string) $field_definition->getLabel(),
                'type' => $field_definition->getType(),
              ];
            }
          }

          $language_info['translatable_fields'] = $translatable_fields;
        }
      }
    }

    return $language_info;
  }

  /**
   * Format content type exploration data for display.
   */
  protected function formatContentTypeExploration(array $data): string {
    $output = [];

    // Content Type Info.
    $content_type_info = $data['content_type_info'];
    $output[] = "=== CONTENT TYPE OVERVIEW ===";
    $output[] = sprintf("Name: %s (Machine Name: %s)", $content_type_info['label'], $content_type_info['id']);
    $output[] = sprintf("Description: %s", $content_type_info['description']);

    // Language Information.
    if (!empty($data['language_info'])) {
      $language_info = $data['language_info'];
      $output[] = "\n=== LANGUAGE & TRANSLATION INFO ===";

      if ($language_info['multilingual_enabled']) {
        $output[] = sprintf("Multilingual: Enabled | Default Language: %s", $language_info['default_language']);

        if ($language_info['content_translation_enabled']) {
          $translation_status = $language_info['translation_enabled_for_type'] ? 'Enabled' : 'Disabled';
          $output[] = sprintf("Content Translation: %s for this content type", $translation_status);

          if ($language_info['translation_enabled_for_type'] && !empty($language_info['translatable_fields'])) {
            $output[] = "\nTranslatable Fields:";
            foreach ($language_info['translatable_fields'] as $field) {
              $output[] = sprintf("  • %s (%s) - %s", $field['label'], $field['name'], $field['type']);
            }
          }
        }

        $output[] = "\nAvailable Languages:";
        foreach ($language_info['available_languages'] as $lang) {
          $default_marker = $lang['is_default'] ? ' [DEFAULT]' : '';
          $output[] = sprintf("  • %s (%s)%s", $lang['name'], $lang['langcode'], $default_marker);
        }
      }
      else {
        $output[] = "Multilingual: Disabled (only default language available)";
      }
    }

    // Space Context.
    if (!empty($data['space_context'])) {
      $space_context = $data['space_context'];
      $output[] = sprintf("\n=== SPACE CONTEXT ===");
      $output[] = sprintf("Space: %s (ID: %d)", $space_context['space_label'], $space_context['space_id']);
      if (!empty($space_context['allowed_content_types'])) {
        $output[] = "Allowed Content Types in this Space:";
        foreach ($space_context['allowed_content_types'] as $type) {
          $output[] = sprintf("  - %s (%s)", $type['label'], $type['id']);
        }
      }
    }

    // Fields.
    if (!empty($data['fields'])) {
      $output[] = "\n=== AVAILABLE FIELDS ===";
      foreach ($data['fields'] as $field) {
        $cardinality = $field['cardinality'] == -1 ? 'Unlimited' : $field['cardinality'];
        $required = $field['required'] ? 'Required' : 'Optional';

        $output[] = sprintf("• %s (%s)", $field['label'], $field['name']);
        $output[] = sprintf("  Type: %s | %s | Cardinality: %s", $field['type'], $required, $cardinality);
        $output[] = sprintf("  Description: %s", $field['description']);

        if (!empty($field['settings'])) {
          $output[] = "  Settings:";
          foreach ($field['settings'] as $setting_name => $setting_value) {
            if (is_array($setting_value)) {
              $setting_value = implode(', ', $setting_value);
            }
            $output[] = sprintf("    - %s: %s", $setting_name, $setting_value);
          }
        }

        if (isset($field['form_widget'])) {
          $output[] = sprintf("  Form Widget: %s", $field['form_widget']);
        }

        $output[] = "";
      }

      // Usage examples.
      $output[] = "=== USAGE EXAMPLES ===";
      $output[] = "When creating a node with the 'create-node-in-space' tool, you can use these fields:";
      $output[] = "";
      $output[] = "Basic example:";
      $output[] = '{';
      $output[] = '  "space_id": 1,';
      $output[] = '  "title": "My New Content",';
      $output[] = '  "content_type": "' . $content_type_info['id'] . '",';
      $output[] = '  "status": true';
      if (!empty($data['language_info']['available_languages']) && count($data['language_info']['available_languages']) > 1) {
        $default_lang = $data['language_info']['default_language'];
        $output[] = '  "langcode": "' . $default_lang . '"';
      }
      $output[] = '}';
      $output[] = "";

      // Language-specific example if multilingual.
      if (!empty($data['language_info']['available_languages']) && count($data['language_info']['available_languages']) > 1) {
        $non_default_langs = array_filter($data['language_info']['available_languages'], fn($lang) => !$lang['is_default']);
        if (!empty($non_default_langs)) {
          $example_lang = reset($non_default_langs);
          $output[] = sprintf("Example for %s language:", $example_lang['name']);
          $output[] = '{';
          $output[] = '  "space_id": 1,';
          $output[] = '  "title": "My Content in ' . $example_lang['name'] . '",';
          $output[] = '  "content_type": "' . $content_type_info['id'] . '",';
          $output[] = '  "langcode": "' . $example_lang['langcode'] . '",';
          $output[] = '  "status": true';
          $output[] = '}';
          $output[] = "";
        }
      }

      // Find body field for example.
      $body_field = array_filter($data['fields'], fn($field) => $field['name'] === 'body');
      if (!empty($body_field)) {
        $output[] = "With custom fields:";
        $output[] = '{';
        $output[] = '  "space_id": 1,';
        $output[] = '  "title": "My New Content",';
        $output[] = '  "content_type": "' . $content_type_info['id'] . '",';
        $output[] = '  "fields": {';
        $output[] = '    "body": "This is the main content of the node."';
        $output[] = '  },';
        $output[] = '  "status": true';
        $output[] = '}';
      }
    }

    return implode("\n", $output);
  }

  /**
   * {@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');
  }

}
