<?php

namespace Drupal\keycloak_user_provisioning\Form;

use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\user_provisioning\Helpers\moUserProvisioningLogger;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Form for Drupal to Keycloak user provisioning configuration.
 */
class MoDrupalToKeycloak extends FormBase {
  use StringTranslationTrait;
  /**
   * Base URL of the site.
   *
   * @var string
   */
  private $baseUrl;

  /**
   * ImmutableConfig property.
   *
   * @var Drupal\Core\Config\ImmutableConfig
   */
  private ImmutableConfig $config;

  /**
   * Config property.
   *
   * @var \Drupal\Core\Config\ConfigInterface
   */
  protected $configFactory;

  /**
   * URL Path property.
   *
   * @var string
   */
  private $urlPath;

  /**
   * Logger property.
   *
   * @var Drupal\user_provisioning\Helpers\moUserProvisioningLogger
   */
  private moUserProvisioningLogger $moLogger;

  /**
   * Module extension list.
   *
   * @var \Drupal\Core\Extension\ModuleExtensionList
   */
  protected ModuleExtensionList $moduleExtensionList;

  /**
   * Constructs a new MoDrupalToKeycloak object.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   * @param \Drupal\Core\Extension\ModuleExtensionList $module_extension_list
   *   The module extension list.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   */
  public function __construct(
    ConfigFactoryInterface $config_factory,
    ModuleExtensionList $module_extension_list,
    RequestStack $request_stack,
  ) {
    $base_url = $request_stack->getCurrentRequest()->getSchemeAndHttpHost();
    $this->baseUrl = $base_url;
    $this->config = $config_factory->get('keycloak_user_provisioning.settings');
    $this->configFactory = $config_factory->getEditable('keycloak_user_provisioning.settings');
    $this->moLogger = new moUserProvisioningLogger();
    $this->moduleExtensionList = $module_extension_list;
    $this->urlPath = $base_url . '/' . $module_extension_list->getPath('keycloak_user_provisioning') . '/includes';
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('config.factory'),
      $container->get('extension.list.module'),
      $container->get('request_stack'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'mo_drupal_to_keycloak_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $this->configFactory->set('keycloak_user_provisioning_status1', 'mo_drupal_to_keycloak')->save();
    $form['mo_keycloak_sync_add_css'] = [
      '#attached' => [
        'library' => [
          'keycloak_user_provisioning/keycloak_user_provisioning.admin',
          'keycloak_user_provisioning/keycloak_user_provisioning.keycloak_test',
          'core/drupal.dialog.ajax',
        ],
      ],
    ];

    $keycloak_test_data = '';
    if (($this->config->get('mo_keycloak_attr_list_from_server')) != '') {
      $keycloak_test_data = Json::decode($this->config->get('mo_keycloak_attr_list_from_server'));
    }
    $disabled = FALSE;
    if (isset($keycloak_test_data['error'])) {
      $disabled = TRUE;
    }
    if ($disabled) {
      $this->messenger()->addError('An error occurred while performing the test configuration. Please click on the Review Keycloak Configurations button to perform the Test configuration again. Test Configuration must be successful to perform user sync from Drupal to Keycloak.');

    }

    $form['drupal_to_keycloak_review_configuration_button'] = [
      '#type' => 'link',
      '#title' => $this->t('Review Keycloak Configuration'),
      '#url' => Url::fromRoute('keycloak_user_provisioning.reviewKeycloakConfiguration'),
      '#attributes' => [
        'style' => ['float:right'],
        'class' => ['button', 'button--primary', 'use-ajax', 'js-form-submit', 'form-submit'],
        'data-dialog-type' => 'modal',
        'data-dialog-options' => json_encode(['width' => '65%']),
      ],
    ];

    if (!$disabled) {
      $form['drupal_to_keycloak_sync_manually_button'] = [
        '#type' => 'link',
        '#title' => $this->t('Sync User Manually'),
        '#url' => Url::fromRoute('keycloak_user_provisioning.syncUserManually'),
        '#attributes' => [
          'style' => ['float:right'],
          'class' => ['button', 'button--primary', 'use-ajax', 'js-form-submit', 'form-submit'],
          'data-dialog-type' => 'modal',
          'data-dialog-options' => json_encode(['width' => '65%']),
        ],
      ];
    }

    $this->manualConfiguration($form, $form_state);
    $this->automaticConfiguration($form, $form_state);
    $this->schedulerConfiguration($form, $form_state);

    $form['drupal_to_keycloak_save_button'] = [
      '#type' => 'submit',
      '#id' => 'save_drupal_to_keycloak_settings',
      '#value' => $this->t('Save Settings'),
      '#button_type' => 'primary',
      '#submit' => ["::saveAllSettings"],
    ];

    return $form;
  }

  /**
   * Builds manual provisioning configuration form elements.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array
   *   The form array.
   */
  public function manualConfiguration(array &$form, FormStateInterface $form_state) {
    $form['mo_keycloak_manual_provisioning_fieldset'] = [
      '#type' => 'fieldset',
      '#title' => Markup::create($this->t('Manual Provisioning Configuration') . '<hr>'),
      '#prefix' => '<br><br><br>',
    ];

    $this->moProvisioningOperations('manual', $form, 'mo_keycloak_manual_provisioning_fieldset');

    return $form;
  }

  /**
   * Builds automatic provisioning configuration form elements.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array
   *   The form array.
   */
  public function automaticConfiguration(array &$form, FormStateInterface $form_state) {
    $form['mo_keycloak_automatic_provisioning_fieldset'] = [
      '#type' => 'fieldset',
      '#title' => Markup::create($this->t('Automatic Provisioning Configuration') . '<hr>'),
    ];

    $this->moProvisioningOperations('automatic', $form, 'mo_keycloak_automatic_provisioning_fieldset');
    return $form;
  }

  /**
   * Builds scheduler-based provisioning configuration form elements.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array
   *   The form array.
   */
  public function schedulerConfiguration(array &$form, FormStateInterface $form_state) {
    $premium_badge = ' <span class="premium-badge">PREMIUM</span><hr>';
    $form['mo_keycloak_scheduler_provisioning_fieldset'] = [
      '#type' => 'fieldset',
      '#title' => Markup::create($this->t('Scheduler Based Provisioning Configuration') . $premium_badge),
    ];

    $this->moProvisioningOperations('scheduler', $form, 'mo_keycloak_scheduler_provisioning_fieldset');
    return $form;
  }

  /**
   * Provisioning operations for different provision types.
   *
   * @param string $provision_type
   *   The type of provisioning (manual, automatic, scheduler).
   * @param array $form
   *   The form array.
   * @param string $fieldset_name
   *   The name of the fieldset.
   */
  private function moProvisioningOperations($provision_type, &$form, $fieldset_name) {
    $keycloak_test_data = '';
    if (($this->config->get('mo_keycloak_attr_list_from_server')) != '') {
      $keycloak_test_data = Json::decode($this->config->get('mo_keycloak_attr_list_from_server'));
    }
    $disabled = FALSE;
    if (isset($keycloak_test_data['error'])) {
      $disabled = TRUE;
    }

    $form[$fieldset_name]['read_user_keycloak_' . $provision_type] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Read user'),
      '#default_value' => $provision_type != 'scheduler',
      '#disabled' => $provision_type == 'scheduler' || $disabled,
      '#prefix' => '<div class="keycloak_sync_checkboxes">',
    ];

    $form[$fieldset_name]['create_user_keycloak_' . $provision_type] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Create user'),
      '#default_value' => $provision_type == 'scheduler' ? FALSE : $this->config->get('keycloak_user_provisioning_enable_' . $provision_type . '_provisioning_checkbox'),
      '#disabled' => $provision_type == 'scheduler' || $disabled,
    ];

    $premium_badge = Markup::create('<span class="premium-badge">PREMIUM</span>');
    $form[$fieldset_name]['deactivate_user_keycloak_' . $provision_type] = [
      '#type' => 'checkbox',
      '#title' => $provision_type == 'scheduler' ? $this->t('Update user') : Markup::create($this->t('Update user @premium', ['@premium' => $premium_badge])),
      '#disabled' => TRUE,
    ];

    $form[$fieldset_name]['update_user_keycloak_' . $provision_type] = [
      '#type' => 'checkbox',
      '#title' => $provision_type == 'scheduler' ? $this->t('Update user') : Markup::create($this->t('Update user @premium', ['@premium' => $premium_badge])),
      '#disabled' => TRUE,
    ];

    $form[$fieldset_name]['delete_user_keycloak_' . $provision_type] = [
      '#type' => 'checkbox',
      '#title' => $provision_type == 'scheduler' ? $this->t('Delete user') : Markup::create($this->t('Delete user @premium', ['@premium' => $premium_badge])),
      '#disabled' => TRUE,
      '#suffix' => '</div>',
    ];

  }

  /**
   * Saves provisioning configurations.
   */
  public function saveAllSettings(array $form, FormStateInterface $form_state) {
    $create_user_automatically = $form_state->getValues()['create_user_keycloak_automatic'];

    $this->configFactory
      ->set('keycloak_user_provisioning_enable_manual_provisioning_checkbox', $form_state->getValues()['create_user_keycloak_manual'])
      ->set('keycloak_user_provisioning_enable_automatic_provisioning_checkbox', $create_user_automatically)
      ->set('keycloak_user_provisioning_deactivate_user_automatic_provisioning_checkbox', $form_state->getValues()['deactivate_user_keycloak_automatic'])
      ->set('keycloak_user_provisioning_deactivate_user_manual_provisioning_checkbox', $form_state->getValues()['deactivate_user_keycloak_manual'])
      ->save();

    $this->messenger()->addMessage('Configuration saved successfully.');
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Handle form submission.
    $this->messenger()->addMessage($this->t('Configuration has been saved.'));
  }

}
