<?php

namespace Drupal\user_provisioning\Form;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Url;
use Drupal\user_provisioning\Helpers\AjaxTables;
use Drupal\user_provisioning\moUserProvisioningConstants;
use Drupal\user_provisioning\moUserProvisioningUtilities;
use Drupal\user_provisioning\ProviderSpecific\EntityHandler\moUserProvisioningUserHandler;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Main form controller for user provisioning configuration.
 */
class MoUserProvisioning extends FormBase {

  /**
   * Module image URL path.
   *
   * @var string
   *   Module image URL path.
   */
  private string $urlPath;

  /**
   * The site base URL.
   *
   * @var string
   *   The site base URL.
   */
  private string $baseUrl;

  /**
   * Editable user provisioning configuration.
   *
   * @var \Drupal\Core\Config\Config
   *   Editable configuration object.
   */
  private Config $editableConfig;

  /**
   * Immutable user provisioning configuration.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   *   Read-only configuration object.
   */
  private ImmutableConfig $config;

  /**
   * The current request.
   *
   * @var \Symfony\Component\HttpFoundation\Request
   *   The current request object.
   */
  private Request $request;

  /**
   * Logger channel for this module.
   *
   * @var \Psr\Log\LoggerInterface
   *   Logger instance.
   */
  private LoggerInterface $logger;

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

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

  /**
   * The current user service.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

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

  /**
   * Constructs the user provisioning form.
   */
  public function __construct(
    ConfigFactoryInterface $config_factory,
    MessengerInterface $messenger,
    RequestStack $request_stack,
    ModuleExtensionList $module_extension_list,
    LoggerChannelFactoryInterface $logger_factory,
    ModuleHandlerInterface $module_handler,
    AccountProxyInterface $current_user,
    EntityTypeManagerInterface $entity_type_manager,
  ) {
    $this->requestStack = $request_stack;
    $this->request = $this->requestStack->getCurrentRequest();
    $this->baseUrl = $this->request->getSchemeAndHttpHost() . $this->request->getBaseUrl();
    $this->moduleExtensionList = $module_extension_list;
    $this->urlPath = $this->baseUrl . '/' . $this->moduleExtensionList->getPath('user_provisioning') . '/images';
    $this->config = $config_factory->get('user_provisioning.settings');
    $this->editableConfig = $config_factory->getEditable('user_provisioning.settings');
    $this->logger = $logger_factory->get('user_provisioning');
    $this->messenger = $messenger;
    $this->moduleHandler = $module_handler;
    $this->currentUser = $current_user;
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * Creates the class instance.
   */
  public static function create(ContainerInterface $container): MoUserProvisioning|static {
    return new static(
      $container->get('config.factory'),
      $container->get('messenger'),
      $container->get('request_stack'),
      $container->get('extension.list.module'),
      $container->get('logger.factory'),
      $container->get('module_handler'),
      $container->get('current_user'),
      $container->get('entity_type.manager'),
    );
  }

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

  /**
   * {@inheritDoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $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_name) && empty($application_selected))) {
      $this->moUserProvisioningMethod($form, $form_state);
    }
    elseif ($application_name == 'api_provisioning') {
      $this->moUserProvisioningApiDirectorySelection($form, $form_state);
    }
    else {
      if ($application_name == 'scim_provisioning') {
        $this->moUserProvisioningApplication($form, $form_state);
      }
      elseif (!empty($application_selected) || !empty($application_name)) {
        if ($application_name == 'scim_server') {
          $this->moUserProvisioningServer($form, $form_state);
        }
        else {
          $this->moUserProvisioningClient($form, $form_state);
        }
      }
    }

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

  /**
   * Builds provider selection for API provisioning integrations.
   */
  private function moUserProvisioningApiDirectorySelection(array &$form, FormStateInterface $form_state) {
    $this->moduleExtensionList->reset();

    // Check if modules are installed (enabled)
    $okta_installed = $this->moduleHandler->moduleExists('okta_user_sync');
    $azure_installed = $this->moduleHandler->moduleExists('azure_ad');
    $keycloak_installed = $this->moduleHandler->moduleExists('keycloak_user_provisioning');

    // Check if modules are downloaded.
    // Using Drupal extension discovery works regardless of folder structure.
    $okta_downloaded = FALSE;
    $azure_downloaded = FALSE;
    $keycloak_downloaded = FALSE;

    try {
      $this->moduleExtensionList->getPathname('okta_user_sync');
      $okta_downloaded = TRUE;
    }
    catch (\Exception $e) {
      // Module not found in filesystem.
      $okta_downloaded = FALSE;
    }

    try {
      $this->moduleExtensionList->getPathname('azure_ad');
      $azure_downloaded = TRUE;
    }
    catch (\Exception $e) {
      // Module not found in filesystem.
      $azure_downloaded = FALSE;
    }

    try {
      $this->moduleExtensionList->getPathname('keycloak_user_provisioning');
      $keycloak_downloaded = TRUE;
    }
    catch (\Exception $e) {
      // Module not found in filesystem.
      $keycloak_downloaded = FALSE;
    }

    $selected_directory = $form_state->getValue('directory') ?? 'okta';

    $form['directory_wrapper']['directory'] = [
      '#type' => 'radios',
      '#title' => $this->t('Select Directory'),
      '#options' => [
        'okta' => $this->t('Okta'),
        'azure' => $this->t('Azure'),
        'keycloak' => $this->t('Keycloak'),
      ],
      '#default_value' => $selected_directory,
      '#attributes' => [
        'class' => ['container-inline', 'custom-radio-spacing'],
      ],
    ];

    // Message field that shows module installation status.
    $form['directory_wrapper']['module_status_message'] = [
      '#type' => 'container',
      '#attributes' => ['class' => ['module-status-message']],
    ];

    // Okta message - not downloaded.
    if (!$okta_downloaded) {
      $form['directory_wrapper']['module_status_message']['okta_message_not_downloaded'] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => ['messages', 'messages--warning'],
        ],
        '#markup' => $this->t('Okta User Sync module is not downloaded. Please download the module first. <a href="https://www.drupal.org/project/okta_user_sync" target="_blank">Download Okta User Sync module</a>'),
        '#states' => [
          'visible' => [
            ':input[name="directory"]' => ['value' => 'okta'],
          ],
        ],
      ];
    }
    // Okta message - downloaded but not enabled.
    elseif ($okta_downloaded && !$okta_installed) {
      $form['directory_wrapper']['module_status_message']['okta_message_not_enabled'] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => ['messages', 'messages--warning'],
        ],
        '#markup' => $this->t('Okta User Sync module is downloaded but not enabled. Please install/enable the module to continue. Go to <a href="/admin/modules">Extend</a> and enable "Okta User Sync" module.'),
        '#states' => [
          'visible' => [
            ':input[name="directory"]' => ['value' => 'okta'],
          ],
        ],
      ];
    }

    // Azure message - not downloaded.
    if (!$azure_downloaded) {
      $form['directory_wrapper']['module_status_message']['azure_message_not_downloaded'] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => ['messages', 'messages--warning'],
        ],
        '#markup' => $this->t('Azure AD module is not downloaded. Please download the module first. <a href="https://www.drupal.org/project/azure_ad" target="_blank">Download Azure AD module</a>'),
        '#states' => [
          'visible' => [
            ':input[name="directory"]' => ['value' => 'azure'],
          ],
        ],
      ];
    }
    // Azure message - downloaded but not enabled.
    elseif ($azure_downloaded && !$azure_installed) {
      $form['directory_wrapper']['module_status_message']['azure_message_not_enabled'] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => ['messages', 'messages--warning'],
        ],
        '#markup' => $this->t('Azure AD module is downloaded but not enabled. Please install/enable the module to continue. Go to <a href="/admin/modules">Extend</a> and enable "Azure AD" module.'),
        '#states' => [
          'visible' => [
            ':input[name="directory"]' => ['value' => 'azure'],
          ],
        ],
      ];
    }

    // Keycloak message - not downloaded.
    if (!$keycloak_downloaded) {
      $form['directory_wrapper']['module_status_message']['keycloak_message_not_downloaded'] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => ['messages', 'messages--warning'],
        ],
        '#markup' => $this->t('Keycloak User Provisioning module is not downloaded. Please download the module first. <a href="https://www.drupal.org/project/keycloak_user_provisioning" target="_blank">Download Keycloak User Provisioning module</a>'),
        '#states' => [
          'visible' => [
            ':input[name="directory"]' => ['value' => 'keycloak'],
          ],
        ],
      ];
    }
    elseif ($keycloak_downloaded && !$keycloak_installed) {
      $form['directory_wrapper']['module_status_message']['keycloak_user_provisioning_message_not_enabled'] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => ['messages', 'messages--warning'],
        ],
        '#markup' => $this->t('Keycloak User Provisioning module is downloaded but not enabled. Please install/enable the module to continue. Go to <a href="/admin/modules">Extend</a> and enable "Keycloak User Provisioning" module.'),
        '#states' => [
          'visible' => [
            ':input[name="directory"]' => ['value' => 'keycloak'],
          ],
        ],
      ];
    }

    // Continue button - controlled purely by Drupal #states API.
    $form['directory_wrapper']['continue_button'] = [
      '#type' => 'submit',
      '#value' => $this->t('Continue'),
      '#button_type' => 'primary',
      '#submit' => ['::continueToModuleConfiguration'],
    ];

    // Build #states conditions based on module installation status.
    $disabled_conditions = [];

    if (!$okta_installed && !$azure_installed && !$keycloak_installed) {
      // None of the modules are installed - always disabled.
      $form['directory_wrapper']['continue_button']['#disabled'] = TRUE;
    }
    else {
      // Add conditions for when button should be disabled.
      if (!$okta_installed) {
        $disabled_conditions[] = [':input[name="directory"]' => ['value' => 'okta']];
      }
      if (!$azure_installed) {
        if (!empty($disabled_conditions)) {
          $disabled_conditions[] = 'or';
        }
        $disabled_conditions[] = [':input[name="directory"]' => ['value' => 'azure']];
      }
      if (!$keycloak_installed) {
        if (!empty($disabled_conditions)) {
          $disabled_conditions[] = 'or';
        }
        $disabled_conditions[] = [':input[name="directory"]' => ['value' => 'keycloak']];
      }

      // Apply #states only if there are conditions.
      if (!empty($disabled_conditions)) {
        $form['directory_wrapper']['continue_button']['#states'] = [
          'disabled' => $disabled_conditions,
        ];
      }
    }

    // Hidden fields to track module installation and download status.
    $form['okta_module_installed'] = [
      '#type' => 'hidden',
      '#value' => $okta_installed ? '1' : '0',
    ];

    $form['azure_module_installed'] = [
      '#type' => 'hidden',
      '#value' => $azure_installed ? '1' : '0',
    ];

    $form['keycloak_module_installed'] = [
      '#type' => 'hidden',
      '#value' => $keycloak_installed ? '1' : '0',
    ];

    $form['okta_module_downloaded'] = [
      '#type' => 'hidden',
      '#value' => $okta_downloaded ? '1' : '0',
    ];

    $form['azure_module_downloaded'] = [
      '#type' => 'hidden',
      '#value' => $azure_downloaded ? '1' : '0',
    ];

    $form['keycloak_module_downloaded'] = [
      '#type' => 'hidden',
      '#value' => $keycloak_downloaded ? '1' : '0',
    ];

    return $form;
  }

  /**
   * Shows the top-level provisioning method selector.
   */
  private function moUserProvisioningMethod(array &$form, FormStateInterface $form_state) {
    $form['#prefix'] = '<div class="user-provisioning-container">';
    $form['#suffix'] = '</div>';

    $form['title'] = [
      '#markup' => '<h2>' . $this->t('Configure Application') . '</h2>',
    ];

    $form['subtitle'] = [
      '#markup' => '<div class="provisioning-subtitle">' . $this->t('Choose Your Provisioning Method') . '</div>',
    ];

    $form['selected_provisioning'] = [
      '#type' => 'hidden',
      '#default_value' => 'api',
      '#attributes' => ['id' => 'selected-provisioning-method'],
    ];

    $cards = [
      [
        'id' => 'scim',
        'title' => $this->t('SCIM based Provisioning'),
        'description' => $this->t('Use the standard SCIM protocol to automate user provisioning between systems'),
        'url' => Url::fromRoute('user_provisioning.provisioning', ['app_name' => 'scim_provisioning'])->toString(),
        'selected' => FALSE,
      ],
      [
        'id' => 'api',
        'title' => $this->t('API based Provisioning'),
        'description' => $this->t('Set up direct user provisioning through IdP API integration.'),
        'url' => Url::fromRoute('user_provisioning.provisioning', ['app_name' => 'api_provisioning'])->toString(),
        'selected' => TRUE,
      ],
    ];

    $form['provisioning_options'] = [
      '#theme' => 'user-provisioning-cards',
      '#cards' => $cards,
    ];

    return $form;
  }

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

  /**
   * Submit handler for Continue button - redirects to selected module.
   */
  public function continueToModuleConfiguration(array &$form, FormStateInterface $form_state) {
    $selected_directory = $form_state->getValue('directory');

    if ($selected_directory == 'okta') {
      // Redirect to Okta User Sync module configuration.
      $form_state->setRedirect('okta_user_sync.overview');
    }
    elseif ($selected_directory == 'azure') {
      // Redirect to Azure AD module configuration.
      $form_state->setRedirect('azure_ad.overview');
    }
    elseif ($selected_directory == 'keycloak') {
      // Redirect to Azure AD module configuration.
      $form_state->setRedirect('keycloak_user_provisioning.overview');
    }
  }

  /**
   * Builds the SCIM application selection screen.
   */
  private function moUserProvisioningApplication(array &$form, FormStateInterface $form_state) {
    $form['mo_user_prov_header_style'] = [
      '#markup' => $this->t('<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;
    }
  }

  /**
   * Builds Drupal-as-SCIM-server configuration section.
   */
  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->baseUrl . moUserProvisioningConstants::USER_PROVISIONING_TAB),
      '#attributes' => ['class' => ['button', 'button--danger']],
    ];

    $form['mo_user_prov_header_style'] = [
      '#markup' => $this->t(
        '<h3>Changes from Provider to Drupal (Drupal as SCIM Server) 
<a href=":upgrade_plans">
<img class="scim_client_know_more" src=":pro_image" alt="Premium">
<span class="scim_client_know_more_hidden">Available in the Premium version</span>
</a>
<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>',
        [
          ':pro_image' => $this->urlPath . '/pro.png',
          ':upgrade_plans' => $this->baseUrl . moUserProvisioningConstants::UPGRADE_PLANS,
        ]
      ),
    ];

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

    $form['mo_user_provisioning_scim_server_configuration'] = [
      '#type' => 'details',
      '#title' => $this->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' => $this->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' => $this->t('Generate new Token'),
      '#disabled' => TRUE,
      '#prefix' => '<br/>',
      '#suffix' => '<br/>',
    ];

    $form['mo_user_provisioning_scim_server_configuration']['mo_user_provisioning_scim_server_description'] = [
      '#markup' => $this->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>',
    ];

  }

  /**
   * Builds Drupal-as-SCIM-client section.
   */
  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' => $this->t('<h3>Choose when to trigger User Sync & Provisioning <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>'),
      ];

      $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' => $this->t('<h3>Configure Drupal as SCIM Client (Changes from Drupal to Provider) <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>'),
      ];

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

  /**
   * Builds the summary table after configuration.
   */
  private function moUserProvSummaryTest(array &$form, FormStateInterface $form_state) {
    $form['mo_user_prov_header_style'] = [
      '#markup' => $this->t('<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();

  }

  /**
   * Returns summary table row data.
   */
  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>', ['@app' => $app]),
    ];

    $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 class="use-ajax" href=":url" data-dialog-type="modal" data-dialog-options="{&quot;width&quot;:&quot;40%&quot;}">Reset</a>',
        [':url' => Url::fromRoute('user_provisioning.reset_configurations')->toString()]
      ),
    ];

    $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;
  }

  /**
   * Builds SCIM client configuration and mapping sections.
   */
  private function moUserProvConf(array &$form, FormStateInterface $form_state, $summary = FALSE) {

    $form['mo_user_prov_scim_client'] = [
      '#type' => 'details',
      '#title' => $this->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' => $this->t('<strong>@note</strong> Enable this checkbox to update below configuration and activate the provisioning.', [
        '@note' => 'Note:-',
      ]),
    ];

    $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'],
      '#states' => [
        // Disable the button when the checkbox is unchecked.
        'disabled' => [
          ':input[name="mo_user_prov_scim_client_enable_api_integration"]' => ['checked' => FALSE],
        ],
      ],
    ];

    $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' => $this->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'),
      '#ajax' => [
        'callback' => '::showPremiumFeatureModal',
        'event' => 'click',
        'progress' => 'none',
      ],
      '#limit_validation_errors' => [],
      '#submit' => [],
    ];

    // Add library for AJAX dialogs.
    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';

    if (!$summary) {
      $form['mo_user_provisioning_save_and_next_wrapper'] = [
        '#type' => 'container',
        '#attributes' => [
          'style' => 'text-align: center; margin-top: 20px;',
        ],
      ];

      $form['mo_user_provisioning_save_and_next_wrapper']['mo_user_provisioning_next'] = [
        '#type' => 'submit',
        '#button_type' => 'primary',
        '#value' => $this->t('Save & Next Step  &#11166;'),
        '#submit' => ['::saveAndNextScimMapping'],
        '#validate' => ['::validateScimMapping'],
        '#disabled' => $this->config->get('mo_user_prov_authorization_success') != TRUE,
      ];
    }
  }

  /**
   * Builds provisioning operations section for SCIM client.
   */
  private function moUserProvScimClientProvConf(array &$form, FormStateInterface $form_state, $summary = FALSE) {

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

    $form['mo_user_prov_scim_client_prov_types']['user_prov_manual_provisioning'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Manual/On-Demand Provisioning'),
      '#description' => $this->t('Manually perform CRUD operations for any Drupal user in your provider.'),
      '#default_value' => $this->config->get('manual_provisioning'),
      '#disabled' => FALSE,
    ];

    $form['mo_user_prov_scim_client_prov_types']['user_prov_automatic_provisioning'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Automatic Provisioning'),
      '#description' => $this->t('Automatically perform CRUD operations for any Drupal user in your provider when user registers/updates profile in your Drupal site.'),
      '#default_value' => $this->config->get('event_based_provisioning'),
      '#disabled' => FALSE,
    ];

    $form['mo_user_prov_scim_client_prov_types']['user_prov_scheduler_provisioning'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Scheduler based Provisioning'),
      '#description' => $this->t('Manually perform CRUD operations for any Drupal user in your provider.'),
      '#disabled' => TRUE,
      '#attributes' => ['style' => 'cursor: not-allowed;'],
    ];

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

    $form['mo_user_prov_scim_client_prov_operations']['features'] = [
      '#markup' => '<div class="premium-upgrade-message">
        In the free version, only <strong>Read</strong> and <strong>Create User</strong> operations are available.
        Other features are part of the <strong>Premium Plan</strong>.
        Upgrade to unlock full access.
                        <a href="' . $this->baseUrl . moUserProvisioningConstants::UPGRADE_PLANS . '" class="upgrade-now">Upgrade Now</a>
                      </div>',
    ];

    $this->moProvisioningOperations($form, 'mo_user_prov_scim_client_prov_operations');

    $form['mo_user_prov_scim_client_prov_operations']['enable_role_filter'] = [
      '#type' => 'checkbox',
      '#description' => $this->t('Users with any of the selected roles will be provisioned.'),
      '#title' => $this->t('Enable Role Filter'),
      '#disabled' => TRUE,
      '#default_value' => $this->editableConfig->get('role_filter') ?? FALSE,
      '#prefix' => '<hr>',
    ];

    $roles = $this->entityTypeManager
      ->getStorage('user_role')
      ->loadMultiple();

    $drupal_roles = array_keys($roles);
    $count = 0;

    $form['mo_user_prov_scim_client_prov_operations']['role_table'] = [
      '#markup' => '<div class="user_provisioning_checkboxes">',
    ];

    foreach (array_chunk($drupal_roles, 3) as $attributes) {
      foreach ($attributes as $attribute) {
        $form['mo_user_prov_scim_client_prov_operations']['role_table'][$count][$attribute] = [
          '#type' => 'checkbox',
          '#title' => $attribute,
          '#default_value' => FALSE,
          '#disabled' => TRUE,
        ];
      }
      $count++;
    }

    $form['mo_user_prov_scim_client_prov_operations']['role_table']['awa'] = [
      '#markup' => '</div><hr>',
    ];

    $form['mo_user_prov_scim_client_prov_operations']['group_provisioning'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable Group Provisioning.'),
      '#description' => '<strong><span style="color: red">' . $this->t('Note:') . '</span></strong>' . $this->t('Enable this if you wish to provision the Drupal Roles of the Users to Roles/Groups of the connected application via SCIM Group APIs. Default roles will be omitted.'),
      '#default_value' => $this->config->get('group_provisioning') ?? FALSE,
    ];

    // Add Fetch Existing Groups button.
    $form['mo_user_prov_scim_client_prov_operations']['fetch_all_groups'] = [
      '#type' => 'submit',
      '#value' => $this->t('Fetch Existing Groups'),
      '#button_type' => 'primary',
      '#ajax' => [
        'callback' => '::fetchExistingGroupModal',
        'event' => 'click',
        'progress' => 'none',
      ],
      '#states' => [
        'enabled' => [
          ':input[name="group_provisioning"]' => ['checked' => TRUE],
        ],
      ],
      '#limit_validation_errors' => [],
      '#submit' => [],
    ];

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

      $form['mo_user_prov_all_done_step1'] = [
        '#type' => 'submit',
        '#value' => $this->t('All Done! &#11166;'),
        '#button_type' => 'primary',
        '#submit' => ['::moUserProvAllDone'],
        '#attributes' => ['style' => 'float: right;'],
        '#states' => [
          'visible' => [
            [
              ':input[id = "edit-user-prov-manual-provisioning"]' => ['checked' => TRUE],
              ':input[name = "create_user"]' => ['checked' => TRUE],
            ],
            'or',
            [
              ':input[id = "edit-user-prov-automatic-provisioning"]' => ['checked' => TRUE],
              ':input[name = "create_user"]' => ['checked' => TRUE],
            ],
          ],
        ],
      ];
    }
  }

  /**
   * Validates required attribute mappings.
   */
  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"));
      }
    }
  }

  /**
   * Saves mapping and continues to next setup step.
   */
  public function saveAndNextScimMapping(array &$form, FormStateInterface $form_state) {
    $form_values = $form_state->getValues();

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

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

  /**
   * Navigates user back to setup step 1.
   */
  public function moUserProvBackStep1(array &$form, FormStateInterface $form_state) {
    $this->editableConfig->set('mo_user_prov_scim_client_step', 'step1')->save();
  }

  /**
   * Returns SCIM client configuration keys.
   */
  private function moUserProvScimClientData() {
    return [
      'SCIM 2.0 Base URL: ' => 'mo_user_provisioning_scim_server_base_url',
      'SCIM Bearer Token: ' => 'mo_user_provisioning_scim_server_bearer_token',
    ];
  }

  /**
   * Builds a row for the SCIM client configuration table.
   */
  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;
  }

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

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

  /**
   * Returns provisioning card rows for title or actions.
   */
  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' => $this->t('&#9881; Configure'),
        '#name' => 'scim_client_button',
        '#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' => $this->t('&#9881; Configure'),
        '#name' => 'scim_server_button',
        '#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;
  }

  /**
   * Builds role-mapping premium feature advertisement section.
   */
  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'         => '<b>' . $this->t('Enable Role Mapping') . '</b>',
      '#description'   => $this->t('<b style="color: red">Note :</b> Enable this first if you want to use default role mapping feature.'),
      '#disabled'      => TRUE,
    ];

    $form['mo_user_provision_role_feature_advertise']['mo_up_scim_role_mapping_enable'] = [
      '#type'        => 'checkbox',
      '#title'       => '<b>' . $this->t('Update the users existing roles.') . '</b>',
      '#description' => $this->t('<b>Note :</b> Enable this if you want to update/delete the existing user roles in the Drupal.'),
      '#disabled'    => TRUE,
    ];

    $form['mo_user_provision_role_feature_advertise']['mo_up_scim_basic_role_mapping'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Basic Role Mapping'),
      '#attributes' => ['style' => 'padding:2% 2% 4%; margin-bottom:2%'],
    ];

    $roles = $this->entityTypeManager
      ->getStorage('user_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_up_scim_basic_role_mapping']['mo_user_provision_default_role'] = [
      '#type'          => 'select',
      '#title'         => $this->t('Select default group for new users'),
      '#description'   => $this->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_up_scim_custom_role_mapping'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Custom Role Mapping'),
      '#attributes' => ['style' => 'padding:2% 2% 4%; margin-bottom:2%'],
      '#disabled'   => TRUE,
    ];

    $form['mo_user_provision_role_feature_advertise']['mo_up_scim_custom_role_mapping']['mo_up_scim_role_attribute'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Role Attribute'),
      '#id' => 'text_field',
      '#attributes' => ['placeholder' => 'Enter Role Attribute'],
      '#disbled' => TRUE,
    ];

    $form['mo_user_provision_role_feature_advertise']['mo_up_scim_custom_role_mapping']['mo_up_scim_roles'] = [
      '#type' => 'table',
      '#title' => $this->t('Role mapping'),
      '#prefix' => '<div id="mo_up_scim_roles_ajax">',
      '#suffix' => '</div>',
      '#header' => [
        $this->t('Drupal Roles'),
        $this->t('SCIM Client Attribute Value'),
        '',
      ],
    ];

    $form['mo_user_provision_role_feature_advertise']['mo_up_scim_custom_role_mapping']['mo_up_scim_roles']['row_1'] = [
      [
        '#title' => $this->t('Drupal Role Name'),
        '#title_display' => 'invisible',
        '#type' => 'select',
        '#disabled' => TRUE,
        '#options' => ['- Select Drupal Role -'],
      ],
      [
        '#title' => $this->t('SCIM Client Attribute Name'),
        '#title_display' => 'invisible',
        '#type' => 'select',
        '#disabled' => TRUE,
        '#options' => ['- Select Attribute Value -'],
      ],
      [
        '#type' => 'button',
        '#disabled' => TRUE,
        '#value' => 'Delete',
        '#attributes' => ['class' => ['mo_user_prov_text_center']],
      ],
    ];

    $form['mo_user_provision_role_feature_advertise']['mo_up_scim_custom_role_mapping']['add'] = [
      '#type' => 'submit',
      '#name' => 'add',
      '#value' => $this->t('Add More Roles'),
      '#disabled' => TRUE,
    ];

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

  }

  /**
   * Builds attribute-mapping premium feature advertisement section.
   */
  private function attributeMappingAdvertise(&$form) {

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

    $form['mo_user_provisioning_scim_server_attribute_mapping']['markup_cam'] = [
      '#markup' => $this->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_up_scim_basic_attribute_mapping'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Basic Attribute Mapping'),
      '#attributes' => ['style' => 'padding:2% 2% 4%; margin-bottom:2%'],
    ];

    $form['mo_user_provisioning_scim_server_attribute_mapping']['mo_up_scim_basic_attribute_mapping']['mo_up_scim_username_attribute'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Username Attribute'),
      '#default_value' => $this->config->get('mo_up_scim_username_attribute'),
      '#disabled' => TRUE,
    ];

    $form['mo_user_provisioning_scim_server_attribute_mapping']['mo_up_scim_basic_attribute_mapping']['mo_up_scim_email_attribute'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Email Attribute'),
      '#default_value' => $this->config->get('mo_up_scim_email_attribute'),
      '#disabled' => TRUE,
    ];

    $form['mo_user_provisioning_scim_server_attribute_mapping']['mo_up_scim_custom_attribute_mapping'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Custom Attribute Mapping'),
      '#attributes' => ['style' => 'padding:2% 2% 4%; margin-bottom:2%'],

    ];

    $form['mo_user_provisioning_scim_server_attribute_mapping']['mo_up_scim_custom_attribute_mapping']['mo_user_provisioning_mapping']['mo_user_provisioning_attributes'] = [
      '#type' => 'table',
      '#title' => $this->t('Attribute mapping'),
      '#header' => [
        $this->t('SCIM Client Attribute Name'),
        $this->t('Drupal Attribute'),
        '',
      ],
    ];

    $form['mo_user_provisioning_scim_server_attribute_mapping']['mo_up_scim_custom_attribute_mapping']['mo_user_provisioning_mapping']['mo_user_provisioning_attributes']['row1'] = [
      [
        '#title' => $this->t('Attribute Name'),
        '#title_display' => 'invisible',
        '#type' => 'select',
        '#disabled' => TRUE,
        '#options' => ['- Select IDP Attribute -'],
      ],
      [
        '#title' => $this->t('User Attribute Machine Name'),
        '#title_display' => 'invisible',
        '#type' => 'select',
        '#disabled' => TRUE,
        '#options' => ['- Select Attribute Value -'],
      ],
      [
        '#type' => 'button',
        '#disabled' => TRUE,
        '#value' => 'Delete',
        '#attributes' => ['class' => ['mo_user_prov_text_center']],
      ],
    ];

    $form['mo_user_provisioning_scim_server_attribute_mapping']['mo_up_scim_custom_attribute_mapping']['mo_user_provisioning_attribute_mapping_add_more'] = [
      '#type'        => 'submit',
      '#button_type' => 'primary',
      '#value'       => $this->t('Add More'),
      '#disabled'    => TRUE,
    ];

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

  }

  /**
   * Builds group-mapping premium feature advertisement section.
   */
  private function groupMappingAdvertise(&$form) {

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

    $form['mo_user_provisioning_scim_server_group_mapping']['mo_user_provisioning_group_mapping_description'] = [
      '#markup' => $this->t('<br/><div class="mo_user_provisioning_background_note"><strong>@note</strong>@description</div>', [
        '@note' => $this->t('Note:'),
        '@description' => $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.'),
      ]),
    ];

    $form['mo_user_provisioning_scim_server_group_mapping']['mo_user_provisioning_enable_group_mapping'] = [
      '#type'          => 'checkbox',
      '#title'         => $this->t('Check this option if you want to <b>Enable Group Mapping</b>'),
      '#description'   => $this->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'       => $this->t('Save Configuration'),
      '#disabled'    => TRUE,
      '#prefix' => '<br>',

    ];

  }

  /**
   * Builds premium feature section for SCIM server settings.
   */
  private function featureAdvertise(&$form) {

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

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

    $form['mo_user_provisioning_scim_server_feature_setting']['enable_group_provisioning'] = [
      '#title' => $this->t('Enable Group Provisioning'),
      '#type' => 'checkbox',
      '#default_value' => 0,
      '#description' => $this->t('Enable to allow the SCIM server to synchronize group operations with a SCIM client.'),
      '#disabled' => TRUE,
    ];

    $form['mo_user_provisioning_scim_server_feature_setting']['group_modifications'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Group Provisioning Settings'),
      '#states' => [
        'visible' => [
          ':input[name="enable_group_provisioning"]' => ['checked' => FALSE],
        ],
      ],
    ];

    $form['mo_user_provisioning_scim_server_feature_setting']['group_modifications']['mo_user_provisioning_group_create'] = [
      '#title' => $this->t('Create Groups'),
      '#type' => 'checkbox',
      '#default_value' => 0,
      '#description' => $this->t('When a new group is created on the SCIM client, a Drupal role with the same name will be created.'),
      '#disabled' => TRUE,
    ];

    $form['mo_user_provisioning_scim_server_feature_setting']['group_modifications']['mo_user_provisioning_group_delete'] = [
      '#title' => $this->t('Delete Groups'),
      '#type' => 'checkbox',
      '#default_value' => 0,
      '#description' => $this->t('When a group is deleted on the SCIM client, the corresponding Drupal role will also be deleted.'),
      '#disabled' => TRUE,
    ];

    $form['mo_user_provisioning_scim_server_feature_setting']['group_modifications']['mo_user_provisioning_group_update'] = [
      '#title' => $this->t('Update Groups'),
      '#type' => 'checkbox',
      '#default_value' => 0,
      '#description' => $this->t('Changes to existing groups (e.g., renaming) on the SCIM client will be applied on this server.'),
      '#disabled' => TRUE,
    ];

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

  /**
   * Saves credentials and tests SCIM client authorization.
   */
  public function testApiCredentials(array &$form, FormStateInterface $form_state) {
    $this->submitScimClientForm($form, $form_state);
    $user = $this->entityTypeManager
      ->getStorage('user')
      ->load($this->currentUser->id());
    $user_provisioner = new moUserProvisioningUserHandler($user);
    [$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->editableConfig
          ->set('mo_user_prov_authorization_success', TRUE)
          ->save();
        $this->messenger->addMessage($this->t('Authorization successful! 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->editableConfig
          ->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=":logs_url" target="_blank">Drupal logs</a> for more details.', [':logs_url' => $this->baseUrl . moUserProvisioningConstants::DRUPAL_LOGS_PATH]));
    }

    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);
  }

  /**
   * Persists SCIM client configuration form values.
   */
  private function submitScimClientForm(array &$form, FormStateInterface $form_state) {
    $form_values = $form_state->getValues();

    $this->editableConfig->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->editableConfig->set($value, trim($form_values_table[$key][$value]))->save();
      }
      $this->editableConfig->set('mo_user_provisioning_app_name', $application_name)->save();
    }
  }

  /**
   * Resets module provisioning configurations.
   */
  public function resetConfigurations(array &$form, FormStateInterface $form_state) {
    moUserProvisioningUtilities::moDeleteConfigurations();
    $form_state->setRedirect('user_provisioning.provisioning', [], [
      'query' => [
        'app_name' => 'scim_client',
      ],
    ]);
  }

  /**
   * Builds dynamic SCIM attribute mapping table.
   */
  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' => 'userName', 'drupal_attr' => 'name'],
        '2' => ['scim_attr' => 'displayName', 'drupal_attr' => 'name'],
        '3' => ['scim_attr' => 'preferredLanguage', 'drupal_attr' => 'preferred_langcode'],
        '4' => ['scim_attr' => 'timezone', 'drupal_attr' => 'timezone'],
        '5' => ['scim_attr' => 'name.familyName' , 'drupal_attr' => 'name'],
        '6' => ['scim_attr' => 'name.givenName' , 'drupal_attr' => 'name'],
        '7' => ['scim_attr' => 'emails[type eq "work"].value', 'drupal_attr' => 'mail'],
      ];
    }

    $default_rows = ['1', '2', '3', '4', '5', '6', '7'];
    $form_state->set('default_rows', $default_rows);

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

    $select_list = [
      1 => [
        'userName' => 'userName',
        'displayName' => 'displayName',
        'preferredLanguage' => 'preferredLanguage',
        'timezone' => 'timezone',
        'name.familyName' => 'name.familyName',
        'name.givenName' => 'name.givenName',
        'emails[type eq "work"].value' => 'emails[type eq "work"].value',
      ],
      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, $default_rows);
    return $form;
  }

  /**
   * AJAX callback for SCIM mapping table updates.
   */
  public function ajaxCallback(array &$form, FormStateInterface $form_state) {
    return $form['mo_user_prov_scim_client_mapping']['mapping_table'];
  }

  /**
   * Ajax callback to show premium feature modal.
   */
  public function showPremiumFeatureModal() {
    $response = new AjaxResponse();
    $modal_content = '<div class="premium-feature-content">
      <p>' . $this->t('Adding additional attributes is a Premium feature and requires an upgrade to a higher plan.') . '</p>
      <p>' . $this->t('For assistance or questions, please reach out to our support team at: <a href="mailto:drupalsupport@xecurify.com">drupalsupport@xecurify.com</a>') . '</p>
      <a href="' . $this->baseUrl . moUserProvisioningConstants::UPGRADE_PLANS . '" class="button button--primary right" style="float: right;">' . $this->t('View Upgrade Plans') . '</a>
    </div>';

    $response->addCommand(new OpenModalDialogCommand(
      $this->t('Premium Feature'),
      $modal_content,
      [
        'width' => '800',
        'height' => '250',
        'dialogClass' => 'user-provisioning-premium-modal',
        'closeOnEscape' => TRUE,
      ]
    ));
    return $response;
  }

  /**
   * Returns dynamic table field definitions.
   */
  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',
      ],
    ];
  }

  /**
   * Adds provisioning operation checkboxes to the form.
   */
  private function moProvisioningOperations(&$form, $field) {
    $form[$field]['read_user'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Read user'),
      '#default_value' => TRUE,
      '#disabled' => TRUE,
      '#prefix' => '<div class="user_provisioning_checkboxes">',
    ];

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

    $form[$field]['update_user'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Update user'),
      '#disabled' => TRUE,
    ];

    $form[$field]['deactivate_user'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Deactivate user'),
      '#disabled' => TRUE,
    ];

    $form[$field]['delete_user'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Delete user'),
      '#disabled' => TRUE,
      '#suffix' => '</div>',
    ];
  }

  /**
   * Saves provisioning-operation preferences and completes setup.
   */
  public function moUserProvAllDone(array &$form, FormStateInterface $form_state) {

    $form_values = $form_state->getValues();
    $manual_prov = $form_values['user_prov_manual_provisioning'];
    $auto_prov = $form_values['user_prov_automatic_provisioning'];
    $create_user = $form_values['create_user'];

    $this->editableConfig
      ->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);
  }

  /**
   * Builds summary page content for SCIM client setup.
   */
  private function moUserProvScimClientProvSummary(array &$form, FormStateInterface $form_state) {
    $form['mo_user_prov_header_style'] = [
      '#markup' => $this->t('<h3>Summary</h3><hr>'),
    ];

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

    $form['mo_user_provisioning_save_all_wrapper'] = [
      '#type' => 'container',
      '#attributes' => [
        'style' => 'text-align: center; margin-top: 20px;',
      ],
    ];

    $form['mo_user_provisioning_save_all_wrapper']['mo_user_provisioning_save_all'] = [
      '#type' => 'submit',
      '#button_type' => 'primary',
      '#value' => $this->t('Save Summary Configuration'),
      '#submit' => ['::moUserProvAllDone'],
    ];
  }

  /**
   * Ajax callback to show premium feature modal.
   */
  public function fetchExistingGroupModal(array &$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();
    $modal_content = '<div class="premium-feature-content">
         <p>' . $this->t('Group Provisioning is a Premium feature and requires an upgrade to a higher plan.') . '</p>
         <p>' . $this->t('To enable automatic role/group creation and management, please upgrade your plan.') . '</p>
         <p>' . $this->t('For assistance or questions, please reach out to our support team at: <a href="mailto:drupalsupport@xecurify.com">drupalsupport@xecurify.com</a>') . '</p>
         <a href="' . $this->baseUrl . moUserProvisioningConstants::UPGRADE_PLANS . '" class="button button--primary" style="float: right;">' . $this->t('View Upgrade Plans') . '</a>
       </div>';

    $response->addCommand(new OpenModalDialogCommand(
          $this->t('Premium Feature'),
          $modal_content,
          [
            'width' => '700',
            'height' => '310',
            'dialogClass' => 'user-provisioning-premium-modal',
            'closeOnEscape' => TRUE,
          ]
      ));
    return $response;
  }

}
