<?php

declare(strict_types=1);

namespace Drupal\flowdrop_trigger\Form;

use Drupal\Core\Form\FormStateInterface;
use Drupal\user\RoleStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * User events settings form for FlowDrop Trigger module.
 *
 * Allows configuration of user-related trigger settings including:
 * - Which user event types to allow (login, logout)
 * - Which user roles should trigger workflows (allowlist)
 * - Which user roles should be excluded (blocklist)
 * - Additional user-specific options.
 *
 * @see \Drupal\flowdrop_trigger\Form\TriggerSettingsCategoryFormBase
 */
final class TriggerSettingsUserForm extends TriggerSettingsCategoryFormBase {

  /**
   * The role storage.
   *
   * @var \Drupal\user\RoleStorageInterface
   */
  protected RoleStorageInterface $roleStorage;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): static {
    $instance = parent::create($container);
    $instance->roleStorage = $container->get("entity_type.manager")->getStorage("user_role");
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return "flowdrop_trigger_settings_user";
  }

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames(): array {
    return ["flowdrop_trigger.settings.user"];
  }

  /**
   * {@inheritdoc}
   */
  protected function getCategoryId(): string {
    return "user";
  }

  /**
   * {@inheritdoc}
   */
  protected function getCategoryLabel(): string {
    return "User";
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $config = $this->config("flowdrop_trigger.settings.user");

    $form["description"] = [
      "#type" => "markup",
      "#markup" => "<p>" . $this->t("Configure which user events should trigger workflows. These settings apply to user authentication and session events.") . "</p>",
    ];

    // =========================================================================
    // Master Toggle.
    // =========================================================================
    $form["enabled"] = $this->buildEnabledField($form_state);

    // =========================================================================
    // Event Types Section.
    // =========================================================================
    $form["event_types_wrapper"] = $this->buildEventTypesField($form_state);

    // =========================================================================
    // Role Allowlist.
    // =========================================================================
    $allowedRoles = $config->get("allowed_roles") ?? [];
    $roleOptions = $this->getRoleOptions();

    $form["roles_wrapper"] = [
      "#type" => "details",
      "#title" => $this->t("Allowed Roles"),
      "#open" => !empty($allowedRoles),
      "#description" => $this->t("Select which user roles should trigger workflows. If none selected, events from all users trigger workflows."),
      "#tree" => TRUE,
    ];

    $form["roles_wrapper"]["allowed_roles"] = [
      "#type" => "checkboxes",
      "#title" => $this->t("Allowed Roles"),
      "#options" => $roleOptions,
      "#default_value" => array_combine($allowedRoles, $allowedRoles),
    ];

    // =========================================================================
    // Role Blocklist.
    // =========================================================================
    $excludedRoles = $config->get("excluded_roles") ?? [];

    $form["excluded_wrapper"] = [
      "#type" => "details",
      "#title" => $this->t("Excluded Roles"),
      "#open" => !empty($excludedRoles),
      "#description" => $this->t("Select roles to explicitly exclude from triggering workflows. These take precedence over allowed roles."),
      "#tree" => TRUE,
    ];

    $form["excluded_wrapper"]["excluded_roles"] = [
      "#type" => "checkboxes",
      "#title" => $this->t("Excluded Roles"),
      "#options" => $roleOptions,
      "#default_value" => array_combine($excludedRoles, $excludedRoles),
    ];

    // =========================================================================
    // Additional Options.
    // =========================================================================
    $form["options"] = [
      "#type" => "details",
      "#title" => $this->t("Data Options"),
      "#open" => FALSE,
      "#tree" => TRUE,
    ];

    $form["options"]["track_login_history"] = [
      "#type" => "checkbox",
      "#title" => $this->t("Track login history"),
      "#description" => $this->t("When enabled, previous login timestamps are included in the trigger data."),
      "#default_value" => $config->get("track_login_history") ?? FALSE,
    ];

    $form["options"]["include_ip_address"] = [
      "#type" => "checkbox",
      "#title" => $this->t("Include IP address"),
      "#description" => $this->t("When enabled, the user's IP address is included in trigger data. <strong>Consider privacy implications before enabling.</strong>"),
      "#default_value" => $config->get("include_ip_address") ?? FALSE,
    ];

    // =========================================================================
    // Privacy Notice.
    // =========================================================================
    $form["privacy"] = [
      "#type" => "details",
      "#title" => $this->t("Privacy Considerations"),
      "#open" => FALSE,
    ];

    $form["privacy"]["notice"] = [
      "#type" => "markup",
      "#markup" => "<div class=\"messages messages--warning\">" .
      "<p>" . $this->t("User event triggers may process personal data. Ensure compliance with applicable privacy regulations (GDPR, CCPA, etc.):") . "</p>" .
      "<ul>" .
      "<li>" . $this->t("Only enable IP address tracking if necessary and disclosed in your privacy policy") . "</li>" .
      "<li>" . $this->t("Consider data retention policies for workflow execution logs") . "</li>" .
      "<li>" . $this->t("Ensure workflows processing user data have appropriate security measures") . "</li>" .
      "</ul></div>",
    ];

    return parent::buildForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    $config = $this->config("flowdrop_trigger.settings.user");

    $config->set("enabled", (bool) $form_state->getValue("enabled"));

    // Process event types from nested structure.
    $eventTypesWrapper = $form_state->getValue("event_types_wrapper", []);
    $allowedEventTypes = $this->filterCheckboxValues(
      $eventTypesWrapper["allowed_event_types"] ?? []
    );
    $config->set("allowed_event_types", $allowedEventTypes);

    // Process allowed roles from nested structure.
    $rolesWrapper = $form_state->getValue("roles_wrapper", []);
    $allowedRoles = $this->filterCheckboxValues(
      $rolesWrapper["allowed_roles"] ?? []
    );
    $config->set("allowed_roles", $allowedRoles);

    // Process excluded roles from nested structure.
    $excludedWrapper = $form_state->getValue("excluded_wrapper", []);
    $excludedRoles = $this->filterCheckboxValues(
      $excludedWrapper["excluded_roles"] ?? []
    );
    $config->set("excluded_roles", $excludedRoles);

    // Process additional options from nested structure.
    $options = $form_state->getValue("options", []);
    $config->set("track_login_history", (bool) ($options["track_login_history"] ?? FALSE));
    $config->set("include_ip_address", (bool) ($options["include_ip_address"] ?? FALSE));

    $config->save();

    parent::submitForm($form, $form_state);
  }

  /**
   * Get user role options for the form.
   *
   * @return array<string, string>
   *   Array of role options keyed by role ID.
   */
  protected function getRoleOptions(): array {
    $options = [];
    $roles = $this->roleStorage->loadMultiple();

    foreach ($roles as $roleId => $role) {
      // Skip the anonymous role as it doesn't apply to login/logout events.
      if ($roleId === "anonymous") {
        continue;
      }
      $options[$roleId] = $role->label();
    }

    return $options;
  }

}
