<?php

namespace Drupal\user_provisioning\Form;

use Drupal\Core\Config\Config;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
use Drupal\user_provisioning\Controller\user_provisioningController;
use Drupal\user_provisioning\Helpers\AjaxTables;
use Drupal\user_provisioning\Helpers\moSCIMClient;
use Drupal\user_provisioning\Helpers\moUserProvisioningLogger;
use Drupal\user_provisioning\moUserProvisioningConstants;
use Drupal\user_provisioning\moUserProvisioningUtilities;
use Drupal\user_provisioning\ProviderSpecific\EntityHandler\moUserProvisioningUserHandler;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 *
 */
class MoUserProvisioning extends FormBase {
  private string $url_path;
  private $base_url;
  private Config $config_factory;
  private ImmutableConfig $config;
  private Request $request;
  private LoggerInterface $logger;
  protected $messenger;
  private moUserProvisioningLogger $mo_logger;

  /**
   *
   */
  public function __construct() {
    $this->base_url = \Drupal::request()->getSchemeAndHttpHost() . \Drupal::request()->getBaseUrl();
    $this->url_path = $this->base_url . '/' . \Drupal::service('extension.list.module')->getPath('user_provisioning') . '/images';
    $this->config = \Drupal::config('user_provisioning.settings');
    $this->config_factory = \Drupal::configFactory()->getEditable('user_provisioning.settings');
    $this->request = \Drupal::request();
    $this->logger = \Drupal::logger('user_provisioning');
    $this->messenger = \Drupal::messenger();
    $this->mo_logger = new moUserProvisioningLogger();

  }

  /**
   * {@inheritDoc}
   */
  public function getFormId() {
    return 'mo_provisioning';
  }

  /**
   * {@inheritDoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['mo_user_prov_add_css'] = [
      '#attached' => [
        'library' => [
          'user_provisioning/user_provisioning.admin',
          'user_provisioning/user_provisioning.mo_search_field',
          'core/drupal.dialog.ajax',
        ],
      ],
    ];

    if ($this->request->get('summary')) {
      $this->moUserProvScimClientProvSummary($form, $form_state);
    }

    $application_name = $this->request->get('app_name');
    $application_selected = $this->config->get('mo_user_provisioning_app_name');

    if (!empty($application_selected) || !empty($application_name)) {
      if ($application_name == 'scim_server') {
        $this->moUserProvisioningServer($form, $form_state);
      }
      else {
        $this->moUserProvisioningClient($form, $form_state);
      }
    }
    else {
      $this->moUserProvisioningApplication($form, $form_state);
    }

    moUserProvisioningUtilities::moProvShowCustomerSupportIcon($form, $form_state);
    return $form;
  }

  /**
   * {@inheritDoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // @todo Implement submitForm() method.
  }

  /**
   *
   */
  private function moUserProvisioningApplication(array &$form, FormStateInterface $form_state) {
    $form['mo_user_prov_header_style'] = [
      '#markup' => t('<div class="mo_user_provisioning_container_3">
            <h3>Configure Application <a class="button mo_top_guide_button" target="_blank" href="https://www.drupal.org/docs/contributed-modules/user-sync-provisioning-in-drupal">&#128366; Setup Guides</a></h3><hr><br>'),
    ];

    $form['mo_user_prov_scim'] = [
      '#type' => 'table',
      '#responsive' => TRUE,
      '#attributes' => ['class' => ['mo_azure_provisioning_types']],
    ];

    $data = ['title', 'description'];
    foreach ($data as $data_shown) {
      $row = $this->moUserProvisioningTypes($data_shown);
      $form['mo_user_prov_scim'][$data_shown] = $row;
    }

    $form['mo_user_prov_choose_app'] = [
      '#markup' => t('<br><div class="mo_user_provisioning_tab_heading">Not sure what to choose?<hr></div>'),
    ];

    $form['mo_user_prov_text_search'] = [
      '#type' => 'textfield',
      '#prefix' => '<div class="mo_user_provisioning_search_provider">',
      '#title' => $this->t('Search Provider/Application'),
      '#placeholder' => $this->t('Search your Provider'),
      '#attributes' => [
        'id' => 'mo_text_search',
        'onkeyup' => 'searchApp()',
      ],
      '#suffix' => '</div><br>',
    ];

    $provider_specific_provisioning = new moSCIMClient();
    $api_providers = $provider_specific_provisioning->providerList();
    $custom_application = $provider_specific_provisioning->providerList('custom');

    $form['mo_user_provisioning_application_list'] = [
      '#prefix' => '<ul id="mo_search_ul" class="mo_user_provisioning_wrap mo_user_provisioning_flex_container"><li class="mo_user_provisioning_flex_item">',
      '#markup' => implode('</li><li class="mo_user_provisioning_flex_item">', $api_providers),
      '#suffix' => '</li></ul>',
    ];

    $form['mo_markup_1'] = [
      '#markup' => '<br><div class="mo-select-app-margin mo_user_provisioning_highlight_background">
        <strong>Note:</strong> If your provider is not listed, you can select <b>Custom Provider</b> to configure the module. Please send us a query using <a href="CustomerSupportProv" class="use-ajax"><b>miniOrange Support</b></a> icon <i>(bottom right corner)</i> if you need any help in the configurations.</div>',
    ];

    $form['mo_user_provisioning_custom_application'] = [
      '#prefix' => '<ul class="mo_user_provisioning_wrap mo_user_provisioning_flex_container"><li class="mo_user_provisioning_flex_item">',
      '#markup' => implode('</li><li class="mo_user_provisioning_flex_item">', $custom_application),
      '#suffix' => '</li></ul>',
    ];

  }

  /**
   *
   */
  private function moUserProvisioningServer(array &$form, FormStateInterface $form_state) {
    $form['mo_user_prov_add_js'] = [
      '#attached' => [
        'library' => [
          'user_provisioning/user_provisioning.openPopup',
        ],
      ],
    ];

    $form['mo_user_provisioning_previous_page'] = [
      '#type' => 'link',
      '#title' => $this->t('&#11164; &nbsp;Back'),
      '#url' => Url::fromUri($this->base_url . moUserProvisioningConstants::USER_PROVISIONING_TAB),
      '#attributes' => ['class' => ['button', 'button--danger']],
      '#prefix' => '<div class="mo_user_provisioning_container_3">',
    ];

    $form['mo_user_prov_header_style'] = [
      '#markup' => t('
            <h3>Changes from Provider to Drupal (Drupal as SCIM Server) <a href="upgrade_plans"><img class="scim_client_know_more" src="' . $this->url_path . '/pro.png" alt="Premium"><span class="scim_client_know_more_hidden">Available in the Premium version</span></a></h3><hr><br>'),
    ];

    $mo_table_content = [
      [
        'SCIM Base URL',
        $this->t('This feature is available in the <a href="' . $this->base_url . moUserProvisioningConstants::UPGRADE_PLANS . '">Premium</a> version of the module.'),
      ],
      [
        'SCIM Bearer Token',
        $this->t('This feature is available in the <a href="' . $this->base_url . moUserProvisioningConstants::UPGRADE_PLANS . '">Premium</a> version of the module.'),
      ],
    ];

    $form['mo_user_provisioning_scim_server_configuration'] = [
      '#type' => 'details',
      '#title' => t('Configure Drupal as SCIM Server'),
      '#open' => TRUE,
    ];

    $form['mo_user_provisioning_scim_server_configuration']['mo_user_provisioning_scim_server_metadata'] = [
      '#type' => 'table',
      '#header' => ['ATTRIBUTE', 'VALUE'],
      '#rows' => $mo_table_content,
      '#empty' => t('Something is not right. Please run the update script or contact us at <a href="mailto:drupalsupport@xecurify.com">drupalsupport@xecurify.com</a>'),
      '#responsive' => TRUE,
      '#sticky' => TRUE,
      '#size' => 2,
      '#attributes' => ['class' => ['mo_user_provisioning_table_server']],
    ];

    $form['mo_user_provisioning_scim_server_configuration']['mo_user_provisioning_scim_server_generate_new_token'] = [
      '#type' => 'submit',
      '#button_type' => 'primary',
      '#value' => t('Generate new Token'),
      '#disabled' => TRUE,
      '#prefix' => '<br/>',
      '#suffix' => '<br/>',
    ];

    $form['mo_user_provisioning_scim_server_configuration']['mo_user_provisioning_scim_server_description'] = [
      '#markup' => t('</br></br>
            <div class="mo_user_provisioning_tab_sub_heading">This tab is capable of doing following SCIM Operations</div><hr>
            <br><div class="mo_user_provisioning_background_note">
                <strong>Create:</strong>
                <ol>It will create users using usernames and other attributes of Provider.<br/>
                <strong>Note: </strong>If Username field is blank, it will copy email as a username, as Drupal does not accept blank Username.</ol>
                <strong>Update:</strong>
                <ol>It will update the user fields, all attributes/fields except email and username.</ol>
                <strong>Delete:</strong>
                <ol>Once a user is deleted from Provider, it would delete a user from Drupal User list as well.</ol>
                <strong>Deactivate:</strong>
                <ol>Once a user is deleted from Provider, it would deactivate a user from the Drupal user list.</ol>
            </div>
            '),
    ];

    $this->featureAdvertise($form);

    $this->attributeMappingAdvertise($form);

    $this->roleMappingAdvertise($form);

    $this->groupMappingAdvertise($form);

    $form['markup_close_div'] = [
      '#markup' => '</div>',
    ];

  }

  /**
   *
   */
  private function moUserProvisioningClient(array &$form, FormStateInterface $form_state) {

    $step = $this->config->get('mo_user_prov_scim_client_step');
    $configuration_edit = $this->request->get('summary');

    if ($step == 'step2') {

      $form['mo_user_prov_header_style'] = [
        '#markup' => t('<div class="mo_user_provisioning_container_3"><h3>Choose when to trigger User Sync & Provisioning</h3><hr>'),
      ];

      $this->moUserProvScimClientProvConf($form, $form_state);
    }
    elseif ($step == 'step3' && $configuration_edit == NULL) {
      $this->moUserProvSummaryTest($form, $form_state);
    }
    elseif ($step == 'step3' && $configuration_edit == 'configuration') {
      $this->moUserProvScimClientProvSummary($form, $form_state);
    }
    else {

      $form['mo_user_prov_header_style'] = [
        '#markup' => t('<div class="mo_user_provisioning_container_3"><h3>Configure Drupal as SCIM Client (Changes from Drupal to Provider)</h3><hr>'),
      ];

      $this->moUserProvConf($form, $form_state);
    }
  }

  /**
   *
   */
  private function moUserProvSummaryTest(array &$form, FormStateInterface $form_state) {
    $form['mo_user_prov_header_style'] = [
      '#markup' => t('<div class="mo_user_provisioning_container_3"><a class="button mo_user_provisioning_right_side" href="audits_and_logs">Audits and Logs</a><br><h3>Summary</h3><hr>'),

    ];

    $form['mo_user_prov_scim_client_summary_table'] = [
      '#type' => 'table',
      '#responsive' => TRUE,
      '#header' => [
        $this->t('Application Name'),
        $this->t('Edit Configurations'),
        $this->t('Mapping'),
        $this->t('Reset Configurations'),
        $this->t('Manual Provisioning'),
      ],
      '#attributes' => ['class' => ['mo_user_prov_summary_table']],
    ];

    $form['mo_user_prov_scim_client_summary_table']['data'] = $this->moUserProvSummaryTableData();

  }

  /**
   *
   */
  private function moUserProvSummaryTableData() {
    $app = ($this->config->get('mo_user_provisioning_app_name') == 'scim_client') ? 'Custom SCIM Server' : $this->config->get('mo_user_provisioning_app_name');

    $row['app_name'] = [
      '#markup' => $this->t('<strong>' . $app . '<strong>'),
    ];

    $row['edit_conf'] = [
      '#markup' => $this->t('<a href="provisioning?summary=configuration">Edit</a>'),
    ];

    $row['edit_mapping'] = [
      '#markup' => $this->t('<a id="edit-mo-user-prov-scim-client-mapping" href="provisioning?summary=configuration#edit-mo-user-prov-scim-client-mapping">Edit Mapping</a>'),
    ];

    $row['reset_conf'] = [
      '#markup' => $this->t('<a href="resetConfiguration">Reset</a>'),
    ];

    $row['perform_manual_sync'] = [
      '#markup' => $this->t('<a class="button button--primary button--small js-form-submit form-submit use-ajax" href="PerformManualSync">Perform Manual Sync</a>'),
    ];

    return $row;
  }

  /**
   *
   */
  private function moUserProvConf(array &$form, FormStateInterface $form_state, $summary = FALSE) {

    $form['mo_user_prov_scim_client'] = [
      '#type' => 'details',
      '#title' => t('Configure Drupal as SCIM Client'),
      '#open' => TRUE,
    ];

    $form['mo_user_prov_scim_client']['mo_user_prov_scim_client_enable_api_integration'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable SCIM Client API integration'),
      '#default_value' => $this->config->get('mo_user_prov_scim_client_enable_api_integration'),
      '#description' => '<strong>Note:-</strong> ' . $this->t('Enable this checkbox to update below configuration and activate the provisioning.'),
    ];

    $form['mo_user_prov_scim_client']['mo_user_prov_client_conf_table'] = [
      '#type' => 'table',
      '#responsive' => TRUE,
      '#attributes' => ['style' => 'border-collapse: separate;'],
    ];

    $data = $this->moUserProvScimClientData();

    foreach ($data as $key => $value) {
      $row = $this->moUserProvScimClientTable($key, $value);
      $form['mo_user_prov_scim_client']['mo_user_prov_client_conf_table'][$key] = $row;
    }

    $form['mo_user_prov_scim_client']['mo_user_provisioning_configuration_test'] = [
      '#type' => 'submit',
      '#button_type' => 'primary',
      '#value' => $this->t('Save and Test Credentials'),
      '#submit' => ['::testAPICredentials'],
    ];

    $form['mo_user_prov_scim_client']['mo_user_provisioning_configuration_reset'] = [
      '#type' => 'submit',
      '#button_type' => 'danger',
      '#value' => $this->t('Reset Configuration'),
      '#limit_validation_errors' => [],
      '#submit' => ['::resetConfigurations'],
    ];

    $form['mo_user_prov_scim_client_mapping'] = [
      '#type' => 'details',
      '#title' => t('Attribute Mapping'),
      '#open' => TRUE,
    ];

    $this->moUserProvMappingTable($form, $form_state);

    $form['mo_user_prov_scim_client_mapping']['mo_user_provisioning_add_more'] = [
      '#type' => 'submit',
      '#button_type' => 'primary',
      '#value' => $this->t('Add more'),
      '#attributes' => ['style' => 'cursor: not-allowed;'],
      '#disabled' => TRUE,
    ];

    $form['mo_user_prov_scim_client_mapping']['mo_user_provisioning_save_mapping'] = [
      '#type' => 'submit',
      '#button_type' => 'primary',
      '#value' => $this->t('Save mapping'),
      '#submit' => ['::saveScimMapping'],
      '#validate' => ['::validateScimMapping'],
    ];

    if (!$summary) {
      $form['mo_user_prov_scim_client_mapping']['mo_user_prov_scim_client_config_next'] = [
        '#type' => 'submit',
        '#button_type' => 'primary',
        '#value' => $this->t('Next Step  &#11166;'),
        '#attributes' => ['class' => ['mo_user_provisioning_right_side']],
        '#submit' => ['::scimClientConfigNext'],
        '#validate' => ['::validateScimMapping'],
        '#disabled' => $this->config->get('mo_user_prov_authorization_success') != TRUE,
      ];
    }
  }

  /**
   *
   */
  private function moUserProvScimClientProvConf(array &$form, FormStateInterface $form_state, $summary = FALSE) {

    $form['mo_user_prov_scim_client_prov_types'] = [
      '#type' => 'details',
      '#title' => t('Provisioning Types'),
      '#open' => TRUE,
    ];

    $form['mo_user_prov_scim_client_prov_types']['provisioning_types_table'] = [
      '#type' => 'table',
      '#responsive' => TRUE,
      '#attributes' => ['class' => ['mo_user_provisioning_types']],
    ];

    $data = ['title', 'description'];
    foreach ($data as $data_shown) {
      $row = $this->moUserProvProvisioningTypes($data_shown);
      $form['mo_user_prov_scim_client_prov_types']['provisioning_types_table'][$data_shown] = $row;
    }

    $form['mo_user_prov_scim_client_prov_operations'] = [
      '#type' => 'details',
      '#title' => t('Provisioning Operations'),
      '#open' => TRUE,
      '#states' => [
        'visible' => [
          [':input[id = "edit-provisioning-types-table-title-user-prov-manual-provisioning"]' => ['checked' => TRUE]], 'or',
          [':input[id = "edit-provisioning-types-table-title-user-prov-automatic-provisioning"]' => ['checked' => TRUE]],
        ],
      ],
    ];

    $form['mo_user_prov_scim_client_prov_operations']['operations_types_table'] = [
      '#type' => 'table',
      '#responsive' => TRUE,
      '#attributes' => ['class' => ['mo_user_prov_ops_table']],
    ];

    $form['mo_user_prov_scim_client_prov_operations']['operations_types_table']['operations'] = $this->moProvisioningOperations();
    ;

    if (!$summary) {
      $form['mo_user_prov_back_step1'] = [
        '#type' => 'submit',
        '#value' => t('&#11164; Back to configuration'),
        '#button_type' => 'danger',
        '#submit' => ['::moUserProvBackStep1'],
      ];

      $form['mo_user_prov_all_done_step1'] = [
        '#type' => 'submit',
        '#value' => t('All Done! &#11166; '),
        '#button_type' => 'primary',
        '#submit' => ['::moUserProvAllDone'],
        '#attributes' => ['style' => 'float: right;'],
        '#states' => [
          'visible' => [
            [
              ':input[name = "provisioning_types_table[title][user_prov_manual_provisioning]"]' => ['checked' => TRUE],
              'and',
              ':input[name = "operations_types_table[operations][create_user]"]' => ['checked' => TRUE],
            ],
            'or',
            [
              ':input[name = "provisioning_types_table[title][user_prov_automatic_provisioning]"]' => ['checked' => TRUE],
              'and',
              ':input[name = "operations_types_table[operations][create_user]"]' => ['checked' => TRUE],
            ],
          ],
        ],
      ];
    }
    else {
      $form['mo_user_prov_scim_client_prov_operations']['mo_user_prov_save_summary'] = [
        '#type' => 'submit',
        '#value' => t('Save Configurations'),
        '#button_type' => 'primary',
        '#submit' => ['::moUserProvAllDone'],
      ];
    }
  }

  /**
   *
   */
  public function validateScimMapping(array &$form, FormStateInterface $form_state) {
    $form_values = $form_state->getValues();
    foreach ($form_values['mapping_table'] as $key => $attribute_row) {
      if (empty($attribute_row['drupal_attr'])) {
        $form_state->setErrorByName("mapping_table][$key][drupal_attr", $this->t("Please choose a valid attribute from the dropdown"));
      }
    }
  }

  /**
   *
   */
  public function saveScimMapping(array &$form, FormStateInterface $form_state) {
    $form_values = $form_state->getValues();

    $this->config_factory->set('mo_user_prov_mapping_conf', json_encode($form_values['mapping_table']))->save();
    $this->messenger->addMessage($this->t('Attribute mapping saved successfully.'));

    $redirect_url = Url::fromRoute('user_provisioning.provisioning');
    $form_state->setRedirectUrl($redirect_url);
  }

  /**
   *
   */
  public function scimClientConfigNext(array &$form, FormStateInterface $form_state) {
    $form_values = $form_state->getValues();
    $this->config_factory->set('mo_user_prov_mapping_conf', json_encode($form_values['mapping_table']))->save();
    $this->config_factory->set('mo_user_prov_scim_client_step', 'step2')->save();
  }

  /**
   *
   */
  public function moUserProvBackStep1(array &$form, FormStateInterface $form_state) {
    $this->config_factory->set('mo_user_prov_scim_client_step', 'step1')->save();
  }

  /**
   *
   */
  private function moUserProvScimClientData() {
    return $data = [
      'SCIM 2.0 Base URL: ' => 'mo_user_provisioning_scim_server_base_url',
      'SCIM Bearer Token: ' => 'mo_user_provisioning_scim_server_bearer_token',
    ];
  }

  /**
   *
   */
  private function moUserProvScimClientTable($key, $value) {
    $row[$key . $key] = [
      '#markup' => '<div class="container-inline"><strong>' . $key . '</strong>',
    ];

    if ($key == 'SCIM 2.0 Base URL: ') {
      $row[$value] = [
        '#type' => 'url',
        '#required' => TRUE,
        '#default_value' => !empty($this->config->get($value)) ? $this->config->get($value) : '',
        '#attributes' => ['class' => ['mo_user_prov_client_conf_table']],
        '#states' => ['disabled' => [':input[name = "mo_user_prov_scim_client_enable_api_integration"]' => ['checked' => FALSE]]],
        '#suffix' => '</div>',
      ];
    }
    else {
      $row[$value] = [
        '#type' => 'textfield',
        '#required' => TRUE,
        '#default_value' => $this->config->get($value),
        '#maxlength' => 1048,
        '#attributes' => ['class' => ['mo_user_prov_client_conf_table']],
        '#states' => ['disabled' => [':input[name = "mo_user_prov_scim_client_enable_api_integration"]' => ['checked' => FALSE]]],
        '#suffix' => '</div>',
      ];
    }

    return $row;
  }

  /**
   *
   */
  public function moScimServerButton() {
    $this->redirect('user_provisioning.provisioning', ['app_name' => 'scim_server'])->send();
  }

  /**
   *
   */
  public function moScimClientButton() {
    $this->redirect('user_provisioning.provisioning', ['app_name' => 'scim_client'])->send();
  }

  /**
   *
   */
  private function moUserProvisioningTypes($data) {

    if ($data == 'title') {
      $row['azure_ad_manual_provisioning'] = [
        '#markup' => '<div class="mo_user_prov_text_center"><h4>Changes from Drupal to Provider (SCIM Client)</h4></div>',
      ];

      $row['azure_ad_automatic_provisioning'] = [
        '#markup' => '<div class="mo_user_prov_text_center"><h4>Changes from Provider to Drupal (SCIM Server)</h4></div>',
      ];
    }
    else {
      $row['azure_ad_manual_provisioning_button'] = [
        '#type' => 'submit',
        '#value' => t('&#9881; Configure '),
        '#button_type' => 'primary',
        '#submit' => ['::moScimClientButton'],
        '#prefix' => 'Drupal as a SCIM client allows for smooth and secure synchronization of changes made to user identities from Drupal to any SCIM-compatible provider.<br><br><div class="mo_user_prov_text_center">',
        '#suffix' => '</div>',
      ];

      $row['azure_ad_automatic_provisioning_button'] = [
        '#type' => 'submit',
        '#value' => t('&#9881; Configure'),
        '#button_type' => 'primary',
        '#submit' => ['::moScimServerButton'],
        '#prefix' => 'Drupal as a SCIM server allows for smooth and secure synchronization of changes made to user identities from any SCIM-compatible provider to Drupal.<br><br><div class="mo_user_prov_text_center">',
        '#suffix' => '</div>',
      ];
    }
    return $row;
  }

  /**
   *
   */
  private function roleMappingAdvertise(&$form) {

    $form['mo_user_provision_role_feature_advertise'] = [
      '#type' => 'details',
      '#title' => $this->t('Role Mapping '),
    ];

    $form['mo_user_provision_role_feature_advertise']['mo_user_provision_enable_role_mapping'] = [
      '#type'          => 'checkbox',
      '#title'         => t('Enable Role Mapping'),
      '#description'   => t('<b style="color: red">Note :</b> Enable this first if you want to use default role mapping feature.'),
      '#disabled'      => TRUE,
    ];

    $roles = Role::loadMultiple();
    $role_label = [];

    foreach ($roles as $role){
      if($role->label() !== 'Anonymous user')
        $role_label[] = $role->label();
    }

    $form['mo_user_provision_role_feature_advertise']['mo_user_provision_default_role'] = [
      '#type'          => 'select',
      '#title'         => t('Select default group for new users'),
      '#description'   => t('<strong>Note: </strong>This role will be assigned to user at the time of user creation in Drupal site.'),
      '#attributes'    => ['style' => 'width:40%;height:29px;'],
      '#options'       => $role_label,
      '#disabled'      => TRUE,
    ];

    $form['mo_user_provision_role_feature_advertise']['mo_user_provision_role_mapping_submit'] = [
      '#type'        => 'submit',
      '#button_type' => 'primary',
      '#value'       => t('Save Configuration'),
      '#disabled'    => TRUE,
    ];

  }

  /**
   *
   */
  private function attributeMappingAdvertise(&$form) {

    $form['mo_user_provisioning_scim_server_attribute_mapping'] = [
      '#type'       => 'details',
      '#title'      => t('Attribute Mapping'),
    ];

    $form['mo_user_provisioning_scim_server_attribute_mapping']['markup_cam'] = [
      '#markup' => t('
				<div class="mo_user_provisioning_background_note"><p> This feature allows you to map the user attributes from your provider to the user attributes in Drupal.				</div>'),
    ];

    $form['mo_user_provisioning_scim_server_attribute_mapping']['mo_user_provisioning_mapping']['mo_user_provisioning_attributes'] = [
      '#type' => 'table',
      '#title' => $this->t('Attribute mapping'),
      '#header' => [
        $this->t('Provider Attribute Name'),
        $this->t('Drupal User Attribute Name'),
        $this->t(''),
        $this->t('<button type="button" class="button" disabled>+</button>'),
      ],
    ];

    $form['mo_user_provisioning_scim_server_attribute_mapping']['mo_user_provisioning_mapping']['mo_user_provisioning_attributes']['row1'] = [
      [
        '#title' => $this->t('Attribute Name'),
        '#title_display' => 'invisible',
        '#type' => 'textfield',
        '#disabled' => TRUE,
      ],
      [
        '#title' => $this->t('User Attribute Machine Name'),
        '#title_display' => 'invisible',
        '#type' => 'textfield',
        '#disabled' => TRUE,
      ],

      [
        '#type' => 'button',
        '#disabled' => 'true',
        '#value' => '-',
        '#attributes' => ['class' => ['button button--danger mo_user_prov_text_center']],
      ],
      [],

    ];

    $form['mo_user_provisioning_scim_server_attribute_mapping']['mo_user_provisioning_attribute_mapping_submit'] = [
      '#type'        => 'submit',
      '#button_type' => 'primary',
      '#value'       => t('Save Configuration'),
      '#disabled'    => TRUE,
    ];

  }

  /**
   *
   */
  private function groupMappingAdvertise(&$form) {

    $form['mo_user_provisioning_scim_server_group_mapping'] = [
      '#type'       => 'details',
      '#title'      => t('Group Mapping '),
    ];

    $form['mo_user_provisioning_scim_server_group_mapping']['mo_user_provisioning_group_mapping_description'] = [
      '#markup' => t('<br/><div class="mo_user_provisioning_background_note"><strong>' . $this->t('Note: ') . '</strong>'
        . $this->t('This section maps the groups created using the Group module. The mapping is done based on the user attribute value received from the SCIM Provider. The module will look for the group name based on the received value under the mapped field and assign that group to the user if that group exists.')
        . '</div>'),
    ];

    $form['mo_user_provisioning_scim_server_group_mapping']['mo_user_provisioning_enable_group_mapping'] = [
      '#type'          => 'checkbox',
      '#title'         => t('Check this option if you want to <b>Enable Group Mapping</b>'),
      '#description'   => t('<b style="color: red">Note :</b> Enable this first if you want to use group mapping feature below.'),
      '#disabled'      => TRUE,
      '#prefix'        => '<br>',
      '#suffix'        => '<br/>',
    ];

    $form['mo_user_provisioning_scim_server_group_mapping']['group_mapping_field_attribute_name'] = [
      '#type'          => 'textfield',
      '#title'         => $this->t('User attribute name for group mapping'),
      '#description'   => $this->t('Enter the attribute name under which you will be receiving the group name. E.g., name.givenName'),
      '#maxlength'     => 255,
      '#disabled'      => TRUE,
    ];

    $form['mo_user_provisioning_scim_server_group_mapping']['group_mapping_field_machine_name'] = [
      '#type'          => 'textfield',
      '#title'         => $this->t('Machine name of the field'),
      '#description'   => $this->t('Enter the machine name of the field with which you want to compare the received value to assign group.'),
      '#disabled'      => TRUE,
      '#states'        => ['disabled' => [':input[name = "mo_user_provisioning_enable_group_mapping"]' => ['checked' => FALSE]]],
      '#maxlength'     => 255,
    ];

    $form['mo_user_provisioning_scim_server_group_mapping']['mo_user_provisioning_group_mapping_submit'] = [
      '#type'        => 'submit',
      '#button_type' => 'primary',
      '#value'       => t('Save Configuration'),
      '#disabled'    => TRUE,
      '#prefix' => '<br>',

    ];

  }

  /**
   *
   */
  private function featureAdvertise(&$form) {

    $form['mo_user_provisioning_scim_server_feature_setting'] = [
      '#type' => 'details',
      '#title' => t('Features '),
      '#attributes' => ['class' => ['mo_details_css']],
      '#open' => TRUE,
    ];

    $form['mo_user_provisioning_scim_server_feature_setting']['set_of_radiobuttons']['miniorange_scim_options'] = [
      '#title' => t('Perform the following action on Drupal user list when user is deleted from Provider:'),
      '#type' => 'radios',
      '#tree' => TRUE,
      '#options' => [
        'NONE' => t('Do Nothing'),
        'DELETE' => t('Delete Users'),
        'DEACTIVATE' => t('Deactivate Users'),
      ],
      '#disabled' => TRUE,
      '#prefix' => '<div class="container-inline">',
      '#suffix' => '</div>',
    ];
    $form['mo_user_provisioning_scim_server_feature_setting']['set_of_radiobuttons']['mo_user_provisioning_group_endpoint_allowed'] = [
      '#title' => t('Group modifications:'),
      '#type' => 'radios',
      '#tree' => TRUE,
      '#options' => [
        'allowed' => t("Allowed"),
        'not_allowed' => t("Not Allowed"),
      ],
      '#disabled' => TRUE,
      '#prefix' => '<div class="container-inline">',
      '#suffix' => '</div>',
    ];

    $form['mo_user_provisioning_scim_server_feature_setting']['mo_user_provisioning_newGroupCreation'] = [
      '#title' => t('Disable new Role creation'),
      '#type' => 'checkbox',
      '#tree' => TRUE,
      '#disabled' => TRUE,
    ];

    $form['mo_user_provisioning_scim_server_feature_setting']['mo_user_provisioning_advance_mapping'] = [
      '#type' => 'submit',
      '#button_type' => 'primary',
      '#value' => t('Save Settings'),
      '#disabled' => TRUE,
    ];

  }

  /**
   *
   */
  public function testAPICredentials(array &$form, FormStateInterface $form_state) {
    $this->submitSCIMClientForm($form, $form_state);
    $user_provisioner = new moUserProvisioningUserHandler(User::load(\Drupal::currentUser()->id()));
    [$status_code, $content] = $user_provisioner->searchResource();
    $redirect_step = '';

    if (!is_null($content)) {
      $body = json_decode($content, TRUE);
      if ($status_code == 409 || !is_null($body)) {
        $this->logger->info('<b> ' . __FUNCTION__ . ':</b> ' . '<pre><code>' . print_r($content, TRUE) . '</code></pre>');
        $this->config_factory
          ->set('mo_user_prov_authorization_success', TRUE)
          ->save();
        $this->messenger->addMessage('Authorization successful!');
        $this->messenger->addMessage($this->t('SCIM Client configuration saved successfully. Scroll down to the <a href="#edit-mo-user-prov-scim-client-mapping">Attribute Mapping</a> section and configure it according to your use-case.'));
      }
      else {
        $redirect_step = $this->request->get('summary') == 'configuration' ? 'configuration' : '';
        $this->config_factory
          ->set('mo_user_prov_authorization_success', FALSE)
          ->save();
        $this->logger->error('<b> ' . __FUNCTION__ . ':</b> ' . '<pre><code>' . print_r($content, TRUE) . '</code></pre>');
        $this->messenger->addError('Invalid Authorization.');

      }
    }
    else {
      $this->messenger->addError($this->t('Either base url or bearer token is invalid. Check' . ' <a href="' . $this->base_url . moUserProvisioningConstants::DRUPAL_LOGS_PATH . '" target="_blank">Drupal logs</a> ' . ' for more details.'));
    }

    if (!empty($redirect_step)) {
      $redirect_url = Url::fromRoute('user_provisioning.provisioning', ['summary' => $redirect_step]);
    }
    else {
      $redirect_url = Url::fromRoute('user_provisioning.provisioning');
    }

    $form_state->setRedirectUrl($redirect_url);
  }

  /**
   *
   */
  private function submitSCIMClientForm(array &$form, FormStateInterface $form_state) {
    $form_values = $form_state->getValues();

    $this->config_factory->set('mo_user_prov_scim_client_enable_api_integration', $form_values['mo_user_prov_scim_client_enable_api_integration'])
      ->save();

    $application_name = $this->request->get('app_name');
    if (empty($application_name)) {
      $application_name = $this->config->get('mo_user_provisioning_app_name');
    }

    $form_values_table = ($form_state->getValues())['mo_user_prov_client_conf_table'];

    $data = $this->moUserProvScimClientData();

    if ($form_values['mo_user_prov_scim_client_enable_api_integration']) {
      foreach ($data as $key => $value) {
        $this->config_factory->set($value, trim($form_values_table[$key][$value]))->save();
      }
      $this->config_factory->set('mo_user_provisioning_app_name', $application_name)->save();
    }
  }

  /**
   *
   */
  public function resetConfigurations() {
    user_provisioningController::resetConfigurations();
  }

  /**
   *
   */
  private function moUserProvMappingTable(array &$form, FormStateInterface $form_state) {

    $mapped_data = $this->config->get('mo_user_prov_mapping_conf') !== NULL ? json_decode($this->config->get('mo_user_prov_mapping_conf'), TRUE) : '';

    if (isset($mapped_data) && !empty($mapped_data)) {
      $options = $mapped_data;
    }
    else {
      $options = [
        '1' => ['scim_attr' => 'emails[type eq "work"].value', 'drupal_attr' => 'mail'],
        '2' => ['scim_attr' => 'name.givenName' , 'drupal_attr' => 'name'],
        '3' => ['scim_attr' => 'name.familyName' , 'drupal_attr' => 'name'],
      ];
    }

    $header = [
      'scim_attr' => $this->t('SCIM Provider Attribute'),
      'drupal_attr' => $this->t('Drupal User Attribute'),
      'delete' => '',
    ];

    $select_list = [
      1 => [
        'emails[type eq "work"].value' => 'emails[type eq "work"].value',
        'name.givenName' => 'name.givenName',
        'name.familyName' => 'name.familyName',
      ],
      2 => moUserProvisioningUtilities::customUserFields(),
    ];

    $fields = $this->getFieldsList();
    $unique_array_id = AjaxTables::getUniqueID($form_state->get('unique_id'), $options);
    $form_state->set('unique_id', $unique_array_id);
    $form['mo_user_prov_scim_client_mapping']['mapping_table'] = AjaxTables::generateTables('names-fieldset-wrapper', $fields, $unique_array_id, $options, $header, $select_list);
    return $form;
  }

  /**
   *
   */
  public function ajaxCallback(array &$form, FormStateInterface $form_state) {
    return $form['mo_user_prov_scim_client_mapping']['mapping_table'];
  }

  /**
   *
   */
  public function getFieldsList() {
    return [
      'scim_attr' => [
        'type' => 'select',
        'disabled' => TRUE,
      ],

      'drupal_attr' => [
        'type' => 'select',
      ],

      'delete_button' => [
        'type' => 'submit',
        'disabled' => 'disabled',
        'submit' => '::removeRow',
        'callback' => '::ajaxCallback',
        'wrapper' => 'names-fieldset-wrapper',
      ],
    ];
  }

  /**
   *
   */
  private function moUserProvProvisioningTypes($data) {

    if ($data == 'title') {
      $row['user_prov_manual_provisioning'] = [
        '#type' => 'checkbox',
        '#title' => '<strong>' . $this->t('<h5>Manual/On-Demand Provisioning</h5>') . '</strong>',
        '#default_value' => $this->config->get('manual_provisioning'),
      ];

      $row['user_prov_automatic_provisioning'] = [
        '#type' => 'checkbox',
        '#title' => '<strong>' . $this->t('<h5>Automatic Provisioning</h5>') . '</strong>',
        '#default_value' => $this->config->get('event_based_provisioning'),
      ];

      $row['user_prov_scheduler_provisioning'] = [
        '#type' => 'checkbox',
        '#title' => '<strong>' . $this->t('<h5>Scheduler based Provisioning</h5>') . '</strong>',
        '#disabled' => TRUE,
        '#attributes' => ['style' => 'cursor: not-allowed;'],
      ];
    }
    else {
      $row['user_prov_manual_provisioning_button'] = [
        '#type' => 'markup',
        '#markup' => $this->t('This will allow you to manually perform CRUD operations for any Drupal user in your provider.'),
        '#suffix' => '</div>',
      ];

      $row['user_prov_automatic_provisioning_button'] = [
        '#type' => 'markup',
        '#markup' => $this->t('This will allow you to automatically perform CRUD operations for any Drupal user in your provider when user registers/updates profile in your Drupal site.'),
        '#suffix' => '</div>',
      ];

      $row['user_prov_scheduler_provisioning_button'] = [
        '#type' => 'markup',
        '#markup' => $this->t('This will allow you to perform CRUD operations for any Drupal user in your provider on the CRON.'),
        '#suffix' => '</div>',
      ];
    }
    return $row;
  }

  /**
   *
   */
  private function moProvisioningOperations(): array {
    $row['read_user'] = [
      '#type' => 'checkbox',
      '#title' => t('Read user'),
      '#default_value' => TRUE,
      '#disabled' => TRUE,
    ];

    $row['create_user'] = [
      '#type' => 'checkbox',
      '#title' => t('Create user'),
      '#default_value' => $this->config->get('mo_user_provisioning_create_user'),
    ];

    $row['update_user'] = [
      '#type' => 'checkbox',
      '#title' => t('Update user <a href="upgrade_plans"><img class="mo_user_prov_pro" src="' . $this->url_path . '/pro.png" alt="Premium"></a>'),
      '#disabled' => TRUE,
    ];

    $row['deactivate_user'] = [
      '#type' => 'checkbox',
      '#title' => t('Deactivate user <a href="upgrade_plans"><img class="mo_user_prov_pro" src="' . $this->url_path . '/pro.png" alt="Premium"></a>'),
      '#disabled' => TRUE,
    ];

    $row['delete_user'] = [
      '#type' => 'checkbox',
      '#title' => t('Delete user <a href="upgrade_plans"><img class="mo_user_prov_pro" src="' . $this->url_path . '/pro.png" alt="Premium"></a>'),
      '#disabled' => TRUE,
    ];

    return $row;
  }

  /**
   *
   */
  public function moUserProvAllDone(array &$form, FormStateInterface $form_state) {

    $form_values = $form_state->getValues();

    $manual_prov = $form_values['provisioning_types_table']['title']['user_prov_manual_provisioning'];
    $auto_prov = $form_values['provisioning_types_table']['title']['user_prov_automatic_provisioning'];
    $create_user = $form_values['operations_types_table']['operations']['create_user'];

    $this->config_factory
      ->set('mo_user_provisioning_create_user', $create_user)
      ->set('event_based_provisioning', $auto_prov)
      ->set('manual_provisioning', $manual_prov)
      ->set('mo_user_prov_scim_client_step', 'step3')
      ->save();

    $this->messenger->addMessage($this->t('Configuration saved successfully. Now, you can perform the sync operations.'));
    $redirect_url = Url::fromRoute('user_provisioning.provisioning');
    $form_state->setRedirectUrl($redirect_url);
  }

  /**
   *
   */
  private function moUserProvScimClientProvSummary(array &$form, FormStateInterface $form_state) {
    $form['mo_user_prov_header_style'] = [
      '#markup' => t('<div class="mo_user_provisioning_container_3"><h3>Summary</h3><hr>'),
    ];

    $this->moUserProvScimClientProvConf($form, $form_state, TRUE);
    $this->moUserProvConf($form, $form_state, TRUE);
  }

}
