<?php

namespace Drupal\miniorange_2fa\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\user\Entity\User;
use Drupal\miniorange_2fa\MoAuthUtilities;
use Drupal\miniorange_2fa\AuthenticationAPIHandler;
use Drupal\miniorange_2fa\MiniorangeCustomerProfile;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\miniorange_2fa\MoAuthConstants;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;

/**
 * Provides the admin 2FA configuration form.
 */
class ConfigureAdmin2fa extends FormBase {
  use DependencySerializationTrait;

  protected MoAuthUtilities $utilities;
  protected $user;
  protected $user_id;
  protected $custom_attribute;
  protected $authMethod;
  protected $user_email;
  protected MiniorangeCustomerProfile $customer;
  protected AuthenticationAPIHandler $auth_api_handler;
  protected $loggerFactory;
  protected AccountProxyInterface $currentUser;


  public function __construct(RequestStack $request_stack, LoggerChannelFactoryInterface $logger_factory, AccountProxyInterface $current_user) {
    $this->requestStack = $request_stack;
    $this->utilities = new MoAuthUtilities();
    $this->currentUser = $current_user;
    $this->user = User::load($this->currentUser->id());
    $this->user_id = $this->user->id();
    $this->custom_attribute = $this->utilities::get_users_custom_attribute($this->user_id);
    $this->user_email = $this->custom_attribute[0]->miniorange_registered_email ?? '';
    $this->authMethod = $this->requestStack->getCurrentRequest()->query->get('authMethod', '');
    $this->customer = new MiniorangeCustomerProfile();
    $this->auth_api_handler = new AuthenticationAPIHandler(
      $this->customer->getCustomerID(),
      $this->customer->getAPIKey()
    );
    $this->loggerFactory = $logger_factory;
  }

  /**
  * {@inheritdoc}
  */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('request_stack'),
      $container->get('logger.factory'),
      $container->get('current_user')
    );
  }

  public function getFormId(): string {
    return 'mo_auth_configure_admin_2fa';
  }

  public function buildForm(array $form, FormStateInterface $form_state): array {
    $form['#attached']['library'] = [
      'miniorange_2fa/miniorange_2fa.admin',
      'core/drupal.ajax',
      'miniorange_2fa/miniorange_2fa.country_flag_dropdown',
      'miniorange_2fa/miniorange_2fa.custom_kba_validation',
    ];

    if (in_array($this->authMethod, MoAuthConstants::AUTHENTICATION_JS_REQUIRED)) {
      $form['#attached']['library'][] = 'miniorange_2fa/miniorange_2fa.license';
    }

    try {
      $plugin_manager = \Drupal::service('plugin.manager.miniorange_2fa.authentication_type');
      $auth_method_code = $this->authMethod ?? '';
      $plugin_id = MoAuthUtilities::mapAuthMethodToPluginId($auth_method_code);

      if (!$plugin_id) {
        throw new \Exception("No plugin found for auth method code: {$auth_method_code}");
      }

      $plugin = $plugin_manager->createInstance($plugin_id);
      $form = $plugin->buildConfigurationForm($form, $form_state);

      $plugin_key = str_replace('-', '_', $plugin_id) . '_plugin';
      $form_state->set($plugin_key, $plugin);
    }
    catch (\Exception $e) {
      $this->loggerFactory->get('miniorange_2fa')->error('@method Plugin error: @msg', [
        '@method' => $this->authMethod,
        '@msg' => $e->getMessage(),
      ]);
    }

    return $form;
  }

  public function validateForm(array &$form, FormStateInterface $form_state): void {
    $this->callPluginMethod('validateConfigurationForm', $form, $form_state);
  }

  public function submitForm(array &$form, FormStateInterface $form_state): void {
    if (!$this->callPluginMethod('submitConfigurationForm', $form, $form_state)) {
      \Drupal::messenger()->addError('Invalid authentication method.');
    }

    if (!$form_state->getRedirect()) {
      $form_state->setRedirect('miniorange_2fa.setup_twofactor');
    }
  }

  private function callPluginMethod(string $method, array &$form, FormStateInterface $form_state): bool {
    $plugin_id = MoAuthUtilities::mapAuthMethodToPluginId($this->authMethod ?? '');

    if (!$plugin_id) {
      return false;
    }

    try {
      $plugin_key = str_replace('-', '_', $plugin_id) . '_plugin';
      $plugin = $form_state->get($plugin_key) ?:Drupal::service('plugin.manager.miniorange_2fa.authentication_type')->createInstance($plugin_id);

      if (!$plugin) {
        $this->loggerFactory->get('miniorange_2fa')->error('Failed to create plugin instance for plugin ID: @plugin_id', [
          '@plugin_id' => $plugin_id,
        ]);
        return false;
      }

      $plugin->$method($form, $form_state);
      return true;
    }
    catch (\Exception $e) {
      $this->loggerFactory->get('miniorange_2fa')->error('Plugin @method error: @msg', [
        '@method' => $method,
        '@msg' => $e->getMessage(),
      ]);
      return false;
    }
  }


}
