<?php

namespace Drupal\azure_ad\Form;

use Drupal\azure_ad\Helper\moAzureADHelper;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;

/**
 * Mapping for Drupal to Azure AD Sync.
 */
class MoAzureMapping extends FormBase {
  /**
   * Immutable Azure AD module configuration.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   */
  private ImmutableConfig $config;

  /**
   * Entity field manager service.
   *
   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
   */
  private EntityFieldManagerInterface $entityFieldManager;

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

  /**
   * Current user service.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  private AccountProxyInterface $currentUser;

  /**
   * Azure to Drupal sync form service.
   *
   * @var \Drupal\azure_ad\Form\MoAzureToDrupalSync
   */
  private MoAzureToDrupalSync $azureToDrupalSyncForm;

  /**
   * Constructor for MoAzureMapping.
   */
  public function __construct(
    ConfigFactoryInterface $config_factory,
    MessengerInterface $messenger,
    EntityFieldManagerInterface $entity_field_manager,
    EntityTypeManagerInterface $entity_type_manager,
    AccountProxyInterface $current_user,
    MoAzureToDrupalSync $azure_to_drupal_sync_form,
  ) {
    $this->setConfigFactory($config_factory);
    $this->setMessenger($messenger);
    $this->config = $config_factory->get('azure_ad.settings');
    $this->entityFieldManager = $entity_field_manager;
    $this->entityTypeManager = $entity_type_manager;
    $this->currentUser = $current_user;
    $this->azureToDrupalSyncForm = $azure_to_drupal_sync_form;
  }

  /**
   * {@inheritDoc}
   */
  public static function create(ContainerInterface $container): static {
    return new static(
      $container->get('config.factory'),
      $container->get('messenger'),
      $container->get('entity_field.manager'),
      $container->get('entity_type.manager'),
      $container->get('current_user'),
      $container->get('azure_ad.form.mo_azure_to_drupal_sync')
    );
  }

  /**
   * Get the form ID.
   *
   * @return string
   *   The form ID.
   */
  public function getFormId() {
    return "mo_azure_azure_audit_logs";
  }

  /**
   * Build the form.
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['mo_user_provisioning_add_css'] = [
      '#attached' => [
        'library' => [
          'user_provisioning/user_provisioning.admin',
          'azure_ad/azure_ad.admin',
          'core/drupal.dialog.ajax',
        ],
      ],
    ];

    $form['mo_azure_ad_mapping_back_to_drupal_to_azure_sync'] = [
      '#type' => 'submit',
      '#value' => $this->t('&#11164; &nbsp;Back'),
      '#button_type' => 'danger',
      '#submit' => ['::moAzureProvBacktodrupaltoazuresync'],
    ];

    $form['Drupal_to_azure_sync'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Mapping for Drupal to Azure AD Sync'),
    ];

    $form['Drupal_to_azure_sync']['azure_ad_attribute_mapping'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Basic Attribute Mapping') . '<hr>',
    ];

    $this->moAzureAdAttributeMapTable($form);

    $form['Drupal_to_azure_sync']['azure_ad_attribute_mapping']['save'] = [
      '#type' => 'submit',
      '#value' => $this->t('Save Configuration&nbsp;'),
      '#button_type' => 'primary',
    ];

    $url = Url::fromRoute('azure_ad.azure_upgrade_plans')->toString();
    $mo_premium_tag = '<a href="' . $url . '" class="premium-badge">' . $this->t('PREMIUM') . '</a>';
    $form['Drupal_to_azure_sync']['azure_ad_custom_attribute_mapping'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Custom Attribute Mapping&nbsp;') . $mo_premium_tag,
    ];

    $form['Drupal_to_azure_sync']['azure_ad_custom_attribute_mapping']['attribute_mapping_info'] = [
      '#markup' => '<div class="mo_azure_highlight_background">' . $this->t('This feature allows you to map the user attributes from your Drupal to Azure AD.') . '</div>',
    ];

    $custom_fields = [];
    $usr = $this->entityTypeManager->getStorage('user')->load($this->currentUser->id());
    $usrVal = $usr ? $usr->toArray() : [];
    foreach ($usrVal as $key => $value) {
      $custom_fields[$key] = $key;
    }

    $header = [
      'drupal_attr' => $this->t('Drupal Attribute Name'),
      'azure_attr' => $this->t('Azure AD Attribute Name'),
      'add' => '',
      'delete' => '',
    ];

    $form['Drupal_to_azure_sync']['azure_ad_custom_attribute_mapping']['azure_ad_custom_attribute_mapping_table'] = [
      '#type' => 'table',
      '#responsive' => TRUE,
      '#header' => $header,
      '#attributes' => ['class' => ['custom_attribute_mapping_table']],
    ];

    $row = $this->moAzureAdCustomAttributeMapTable($custom_fields);
    $form['Drupal_to_azure_sync']['azure_ad_custom_attribute_mapping']['azure_ad_custom_attribute_mapping_table']['custom_mapping'] = $row;

    $this->azureToDrupalSyncForm->attributeMapping($form, $form_state);
    $azure_ad_helper = new moAzureADHelper();
    $azure_ad_helper->moAzureShowCustomerSupportIcon($form, $form_state);
    return $form;

  }

  /**
   * Create the custom attribute mapping table.
   */
  public function moAzureAdCustomAttributeMapTable($custom_fields) {
    $row['azure_ad_drupal_attr_name'] = [
      '#type' => 'select',
      '#options' => $custom_fields,
      '#disabled' => TRUE,
    ];

    $row['azure_ad_attribute_name'] = [
      '#type' => 'textfield',
      '#disabled' => TRUE,
    ];

    $row['azure_ad_add_button'] = [
      '#type' => 'submit',
      '#button_type' => 'primary',
      '#disabled' => TRUE,
      '#value' => '+',
    ];

    $row['azure_ad_sub_button'] = [
      '#type' => 'submit',
      '#button_type' => 'danger',
      '#disabled' => TRUE,
      '#value' => '-',
    ];

    return $row;
  }

  /**
   * Create the attribute mapping table.
   */
  public function moAzureAdAttributeMapTable(&$form) {

    $default_user_fields = $this->entityFieldManager->getFieldDefinitions('user', NULL);
    $filtered_fields = [];

    foreach ($default_user_fields as $key => $field) {
      if (in_array($key, ['name', 'mail'])) {
        $filtered_fields[$key] = $key;
      }
    }

    $default_user_fields = $filtered_fields;

    $email_attr = $this->config->get('azure_ad_mapping_mail_attr');
    $username_attr = $this->config->get('azure_ad_mapping_username_attr');

    if (!isset($email_attr)) {
      $this->configFactory()->getEditable('azure_ad.settings')->set('azure_ad_mapping_mail_attr', 'name')->save();
    }

    if (!isset($username_attr)) {
      $this->configFactory()->getEditable('azure_ad.settings')->set('azure_ad_mapping_username_attr', 'name')->save();
    }

    $form['Drupal_to_azure_sync']['azure_ad_attribute_mapping']['username_attribute'] = [
      '#type' => 'select',
      '#title' => $this->t('Username Attribute'),
      '#options' => $default_user_fields,
      '#default_value' => $this->config->get('azure_ad_mapping_username_attr'),
    ];

    $form['Drupal_to_azure_sync']['azure_ad_attribute_mapping']['email_attribute'] = [
      '#type' => 'select',
      '#title' => $this->t('Email Attribute'),
      '#options' => $default_user_fields,
      '#default_value' => $this->config->get('azure_ad_mapping_mail_attr'),
    ];
  }

  /**
   * Submit the form.
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {

    $form_values = $form_state->getValues();

    $username_attribute = $form_values['username_attribute'];
    $email_attribute = $form_values['email_attribute'];

    $this->configFactory()->getEditable('azure_ad.settings')->set('azure_ad_mapping_mail_attr', $email_attribute)->save();
    $this->configFactory()->getEditable('azure_ad.settings')->set('azure_ad_mapping_username_attr', $username_attribute)->save();
    $this->messenger->addStatus($this->t('Configurations saved successfully.'));
  }

  /**
   * Back to Drupal to Azure Sync.
   */
  public function moAzureProvBacktodrupaltoazuresync() {
    $response = new RedirectResponse(Url::fromRoute('azure_ad.configure_azure')->toString());
    $response->send();
    return new Response();
  }

}
