<?php

declare(strict_types=1);

namespace Drupal\simple_interactive_maps\Form;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseModalDialogCommand;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
use Drupal\simple_interactive_maps\InteractiveMapFormTempStoreTrait;
use Drupal\simple_interactive_maps\InteractiveMapInterface;
use Drupal\simple_interactive_maps\MapActionPluginManager;
use Drupal\simple_interactive_maps\SimpleInteractiveMapsLoggerTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\HttpException;

/**
 * Provides a Simple Interactive Maps form.
 */
final class RegionEditForm extends FormBase {

  use InteractiveMapFormTempStoreTrait, SimpleInteractiveMapsLoggerTrait;

  public function __construct(protected MapActionPluginManager $mapActionPluginManager) {}

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    /** @var \Drupal\simple_interactive_maps\MapActionPluginManager $mapActionPluginManager */
    $mapActionPluginManager = $container->get('plugin.manager.map_action');

    return new RegionEditForm($mapActionPluginManager);
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return 'simple_interactive_maps_region_edit_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, ?InteractiveMapInterface $interactive_map = NULL, ?string $region_id = NULL): array {
    if (!($interactive_map instanceof InteractiveMapInterface)) {
      throw new HttpException(404, 'Interactive map not found.');
    }

    if ($region_id === NULL) {
      throw new HttpException(404, 'Region not found.');
    }

    $regionData = $interactive_map->getRegions();
    $region = $regionData[$region_id];

    $form['map'] = [
      '#type' => 'value',
      '#value' => $interactive_map,
    ];

    $form['id'] = [
      '#type' => 'hidden',
      '#value' => $region_id,
    ];

    $form['label'] = [
      '#type' => 'value',
      '#value' => $region['label'],
    ];

    $form['region'] = [
      '#type' => 'fieldset',
    ];

    $form['region']['tabs'] = [
      '#type' => 'horizontal_tabs',
      '#default_tab' => 'edit-general',
    ];

    $form['region']['tabs']['general'] = [
      '#type' => 'details',
      '#title' => $this->t('General'),
      '#group' => 'tabs',
      '#attributes' => ['class' => ['edit-general']],
    ];

    $form['region']['tabs']['general']['tooltip'] = [
      '#type' => 'text_format',
      '#title' => $this->t('Tooltip text'),
      '#default_value' => $region['tooltip']['value'] ?? '',
      '#format' => $region['tooltip']['format'] ?? 'full_html',
    ];

    $form['region']['tabs']['general']['hidden'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Hidden'),
      '#default_value' => $region['hidden'] ?: FALSE,
    ];

    $groups = $interactive_map->get('groups');

    $groupOptions = [];
    $groupActive = FALSE;
    if (!empty($groups)) {
      foreach ($groups as $groupId => $group) {
        $groupOptions[$groupId] = $group['label'];
      }

      $groupActive = TRUE;
    }

    $form['region']['tabs']['general']['group'] = [
      '#type' => 'select',
      '#title' => $this->t('Group'),
      '#options' => $groupOptions,
      '#empty_option' => '- None -',
      '#empty_value' => '',
      '#default_value' => $region['group'] ?? '',
      '#disabled' => !$groupActive,
    ];

    $form['region']['tabs']['color'] = [
      '#type' => 'details',
      '#title' => $this->t('Colors'),
      '#group' => 'tabs',
      '#attributes' => ['class' => ['edit-color']],
    ];

    $form['region']['tabs']['color']['fill_color'] = [
      '#type' => 'color',
      '#title' => $this->t('Fill Color'),
      '#default_value' => $region['fill_color'] ?? '#4ba0a6',
      '#description' => $this->t('The color to fill the region with.'),
    ];

    $form['region']['tabs']['color']['hover_color'] = [
      '#type' => 'color',
      '#title' => $this->t('Hover color'),
      '#default_value' => $region['hover_color'] ?? '#076369',
      '#description' => $this->t('The color to fill the region with when hovered over.'),
    ];

    $form['region']['tabs']['color']['stroke_color'] = [
      '#type' => 'color',
      '#title' => $this->t('Stroke color'),
      '#default_value' => $region['stroke_color'] ?? '#076369',
      '#description' => $this->t('The color to fill the region with when hovered over.'),
    ];

    $form['region']['tabs']['color']['text_color'] = [
      '#type' => 'color',
      '#title' => $this->t('Text color'),
      '#default_value' => $region['text_color'] ?? '#000000',
      '#description' => $this->t('The color of the text in the region.'),
    ];

    $form['region']['tabs']['action'] = [
      '#type' => 'details',
      '#title' => $this->t('Behaviors'),
      '#group' => 'tabs',
      '#attributes' => ['class' => ['edit-behaviors']],
    ];

    $actions = $this->mapActionPluginManager->getDefinitions();

    $actionOptions = [];
    foreach ($actions as $action) {
      $actionOptions[$action['id']] = $action['label'];
    }

    $selectedAction = $form_state->getValue('plugin_id') ?? $region['action']['plugin_id'] ?? 'none';

    $form['region']['tabs']['action']['plugin_id'] = [
      '#type' => 'select',
      '#title' => $this->t('Action'),
      '#options' => $actionOptions,
      '#default_value' => $region['action']['plugin_id'] ?? 'none',
    ];

    // Add an ajax callback to load the plugin settings form.
    $form['region']['tabs']['action']['plugin_id']['#ajax'] = [
      'callback' => '::ajaxActionPluginSettings',
      'wrapper' => 'action-settings',
      'method' => 'replaceWith',
    ];

    $form['region']['tabs']['action']['settings_wrapper'] = [
      '#type' => 'container',
      '#states' => [
        'visible' => [
          ':input[name="region[tabs][action][plugin_id]"]' => ['!value' => 'none'],
        ],
      ],
    ];

    $form['region']['tabs']['action']['settings_wrapper']['plugin_configuration'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Action settings'),
      '#attributes' => [
        'class' => ['action-settings'],
        'id' => 'action-settings',
      ],
      '#tree' => TRUE,
    ];

    if ($selectedAction && $selectedAction !== 'none') {
      $subform_state = SubformState::createForSubform($form['region']['tabs']['action']['settings_wrapper']['plugin_configuration'], $form, $form_state);

      $form['region']['tabs']['action']['settings_wrapper']['plugin_configuration'] = array_merge($form['region']['tabs']['action']['settings_wrapper']['plugin_configuration'], $this->mapActionPluginManager->createInstance($selectedAction, $region['action']['plugin_configuration'] ?? [])
        ->buildConfigurationForm([], $subform_state, $region));
    }

    $form['actions'] = [
      '#type' => 'actions',
      'submit' => [
        '#type' => 'submit',
        '#value' => $this->t('Save Region Info'),
        '#button_type' => 'primary',
      ],
      'cancel' => [
        '#type' => 'cancel',
        '#value' => $this->t('Cancel'),
        '#limit_validation_errors' => [],
      ],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state): void {
    /** @var \Drupal\simple_interactive_maps\MapActionPluginBase $actionPlugin */
    $actionPlugin = $this->mapActionPluginManager->createInstance($form_state->getValue('plugin_id'), $form_state->getValue('plugin_configuration') ?? []);

    $actionPlugin->validateConfigurationForm($form, SubformState::createForSubform($form['region']['tabs']['action']['settings_wrapper']['plugin_configuration'], $form, $form_state));
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    $interactive_map = $form_state->getValue('map');

    $regionData = $interactive_map->getRegions();

    $regionId = $form_state->getValue('id');

    $pluginId = $form_state->getValue('plugin_id');

    $actionPlugin = $this->mapActionPluginManager->createInstance($pluginId, $form_state->getValue('plugin_configuration') ?? []);

    $newRegionDetails = [
      'id' => $form_state->getValue('id'),
      'label' => $form_state->getValue('label'),
      'hidden' => $form_state->getValue('hidden'),
      'group' => $form_state->getValue('group'),
      'fill_color' => $form_state->getValue('fill_color'),
      'hover_color' => $form_state->getValue('hover_color'),
      'stroke_color' => $form_state->getValue('stroke_color'),
      'text_color' => $form_state->getValue('text_color'),
      'tooltip' => $form_state->getValue('tooltip'),
      'action' => [
        'plugin_id' => $form_state->getValue('plugin_id'),
        'plugin_configuration' => $actionPlugin->getConfiguration(),
      ],
    ];
    $regionData[$regionId] = $newRegionDetails;

    try {
      $interactive_map->setRegions($regionData);
      $interactive_map->save();

      $this->messenger()->addMessage($this->t('Region saved successfully.'));
    }
    catch (\Exception $e) {
      $this->getMapsLogger()->error($e->getMessage());
      $this->messenger()
        ->addMessage($this->t('An error occurred while saving the region.'), 'error');
    }
  }

  /**
   * Close the modal form.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return \Drupal\Core\Ajax\AjaxResponse
   *   The ajax response.
   */
  public function closeModalForm(array &$form, FormStateInterface $form_state): AjaxResponse {
    $response = new AjaxResponse();
    $response->addCommand(new CloseModalDialogCommand());
    return $response;
  }

  /**
   * Return the action configuration form.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array
   *   The action configuration form.
   */
  public function ajaxActionPluginSettings(array &$form, FormStateInterface $form_state): array {
    $value = $form['region']['tabs']['action']['settings_wrapper']['plugin_configuration'] ?: [];
    return $value;
  }

}
