<?php

namespace Drupal\user_provisioning\Controller;

use Drupal\Component\Utility\Html;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\Core\Config\Config;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Form\FormBuilder;
use Drupal\Core\Url;
use Drupal\user\Entity\Role;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;

/**
 *
 */
class user_provisioningController extends ControllerBase {
  /**
   * The user storage.
   *
   * @var \Drupal\user\Entity\UserStorageInterface
   */
  protected $users;

  protected $roles;

  private $base_url;
  private ImmutableConfig $config;
  private Config $config_factory;
  private LoggerInterface $logger;
  protected $formBuilder;

  /**
   * Scim_clientController constructor.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function __construct(FormBuilder $formBuilder) {
    $this->base_url = \Drupal::request()->getSchemeAndHttpHost() . \Drupal::request()->getBaseUrl();
    $this->config = \Drupal::config('user_provisioning.settings');
    $this->config_factory = \Drupal::configFactory()->getEditable('user_provisioning.settings');
    $this->logger = \Drupal::logger('user_provisioning');

    // Loading all the users.
    $this->users = \Drupal::entityTypeManager()->getStorage('user')->loadMultiple();
    // Un-setting the Anonymous user which has uid=0.
    unset($this->users[0]);

    // Loading all the roles.
    $this->roles = Role::loadMultiple();
    $this->formBuilder = $formBuilder;
  }

  /**
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public static function create(ContainerInterface $container) {
    return new static(
          $container->get("form_builder")
      );
  }

  /**
   * Export the user in json or csv file.
   *
   * @return \Symfony\Component\HttpFoundation\RedirectResponse|void
   */
  public function exportUsers() {
    // Required attribute to export.
    $users_export = $this->config->get('mo_user_provisioning_export_config');
    // File extension.
    $fil_extension = $this->config->get('mo_user_provisioning_file_extension');
    $this->config_factory->clear('mo_export_config')->save();

    $configuration_array = [];

    $header = [];
    if ($fil_extension == 'csv') {
      foreach ($users_export as $key => $value) {
        if ($value) {
          $header[] = $key;
        }
      }
      $configuration_array[] = $header;
    }

    foreach ($this->users as $user) {
      $user_details = [];
      foreach ($users_export as $key => $val) {
        if ($val) {
          $user_key_value = $user->get($key)->value;
          $user_details[$key] = $user_key_value;
        }
      }
      if (!empty($user_details)) {
        $configuration_array[$user->getDisplayName()] = $user_details;
      }

    }

    // To unset the anonymous user.
    unset($configuration_array["Anonymous"]);

    if ($fil_extension == 'json') {
      header("Content-Disposition: attachment; filename = mo_user_provisioning_export.json");
      echo(json_encode($configuration_array, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
      exit;
    }
    elseif ($fil_extension == 'csv') {
      $f = fopen('php://memory', 'w');
      // Loop over the input array.
      foreach ($configuration_array as $line) {
        // Generate csv lines from the inner arrays.
        fputcsv($f, $line, ';');
      }
      // Reset the file pointer to the start of the file.
      fseek($f, 0);
      // Tell the browser it's going to be a csv file.
      header('Content-Type: text/csv');
      // Tell the browser we want to save it instead of displaying it.
      header('Content-Disposition: attachment; filename=mo_user_provisioning_export.csv');
      // Make php send the generated csv lines to the browser.
      fpassthru($f);
      exit;
    }

    return new RedirectResponse(Url::fromRoute('user_provisioning.advanced_settings')->toString());
  }

  // Ajax Response for Contact Us / Support Request form.

  /**
   * @return \Drupal\Core\Ajax\AjaxResponse
   */
  public function openSupportRequestForm() {
    $response = new AjaxResponse();
    $modal_form = $this->formBuilder->getForm('\Drupal\user_provisioning\Form\MoUserProvisioningRequestSupport');
    $response->addCommand(new OpenModalDialogCommand('Support Request/Contact Us', $modal_form, ['width' => '40%']));
    return $response;
  }

  /**
   *
   */
  public function openModalForm() {
    $response = new AjaxResponse();
    $modal_form = $this->formBuilder->getForm('\Drupal\user_provisioning\Form\MoUserProvisioningRemoveAccount');
    $response->addCommand(new OpenModalDialogCommand('Remove Account', $modal_form, ['width' => '40%']));
    return $response;
  }

  /**
   *
   */
  public function openCustomerRequestForm() {
    $response = new AjaxResponse();
    $modal_form = $this->formBuilder->getForm('\Drupal\user_provisioning\Form\MoUserProvisioningCustomerRequest');
    $response->addCommand(new OpenModalDialogCommand('Contact miniOrange Support', $modal_form, ['width' => '45%']));
    return $response;
  }

  /**
   *
   */
  public function openManualSyncFormAction() {
    $response = new AjaxResponse();
    $modal_form = $this->formBuilder->getForm('\Drupal\user_provisioning\Form\MoUserProvisioningManualSync');
    $response->addCommand(new OpenModalDialogCommand('Perform Manual Sync', $modal_form, ['width' => '80%']));
    return $response;
  }

  /**
   *
   */
  public function openConfigureAppForm($app_name) {
    $response = new AjaxResponse();
    $modal_form = $this->formBuilder->getForm('\Drupal\user_provisioning\Form\MoUserProvisioningChooseApp', $app_name);
    $response->addCommand(new OpenModalDialogCommand('Choose the sync', $modal_form, ['width' => '80%']));
    return $response;
  }

  /**
   *
   */
  public static function resetConfigurations() {
    \Drupal::configFactory()->getEditable('user_provisioning.settings')
      ->clear('mo_user_prov_scim_client_enable_api_integration')
      ->clear('mo_user_provisioning_app_name')
      ->clear('mo_user_provisioning_scim_server_base_url')
      ->clear('mo_user_provisioning_scim_server_bearer_token')
      ->clear('mo_user_prov_scim_client_step')
      ->clear('mo_user_provisioning_create_user')
      ->clear('event_based_provisioning')
      ->clear('manual_provisioning')
      ->set('mo_user_prov_authorization_success', FALSE)
      ->save();

    \Drupal::messenger()->addStatus(t('Configuration reset successfully.'));

    $response = new RedirectResponse(Url::fromRoute('user_provisioning.provisioning')->toString());
    return $response;
  }

  /**
   * @param \Symfony\Component\HttpFoundation\Request $request
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
  public function handleAutocomplete(Request $request): JsonResponse {
    $matches = [];

    // Fetching the entered query string.
    $typed_field_value = $request->query->get('q');

    // Loading all the users and preparing array for json response.
    foreach ($this->users as $user) {
      if (stripos($user->label(), $typed_field_value) === 0) {
        $matches[] = [
          'value' => $user->label(),
          'label' => Html::escape($user->label() . '(' . $user->getEntityType()->getLabel()->getUntranslatedString() . ')'),
        ];
      }
    }

    return new JsonResponse($matches);
  }


}
