<?php

namespace Drupal\miniorange_2fa\Plugin\AuthenticationType;

use Drupal\miniorange_2fa\Plugin\AuthenticationTypePluginBase;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\miniorange_2fa\UsersAPIHandler;
use Drupal\miniorange_2fa\AuthenticationAPIHandler;
use Drupal\miniorange_2fa\MiniorangeUser;
use Drupal\miniorange_2fa\MoAuthUtilities;
use Drupal\miniorange_2fa\MoAuthConstants;
use Drupal\Core\Form\FormStateInterface;
use Drupal\user\Entity\User;
/**
 * Email Verification authentication type plugin.
 *
 * @AuthenticationType(
 *   id = "email_verification",
 *   name = @Translation("Email Verification"),
 *   code = "OUT OF BAND EMAIL",
 *   type = "OTHER",
 *   description = @Translation("You will receive an email with links to either Accept or Deny the login attempt."),
 *   supported_devices = {"Laptops", "Smartphones"},
 *   challenge = true,
 *   oob = true,
 *   doc_link = "https://www.drupal.org/docs/extending-drupal/contributed-modules/contributed-modules/setup-guides-to-configure-various-2fa-mfa-tfa-methods/other-tfa-methods/setup-email-verification-as-2fa-tfa-method",
 *   video_link = "https://www.youtube.com/watch?v=Uj6SiYeII1c&list=PL2vweZ-PcNpeOYZk3tPy6MoDV8ELT0odI&index=10"
 * )
 */
class EmailVerificationType extends AuthenticationTypePluginBase {

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
    
    global $base_url;
    
    if (!$this->validateUserSession()) {
      return $form;
    }

    $this->setFormTitle($form, 'email-verification-form');
    
    $input = $form_state->getUserInput();
    
    if (!array_key_exists('txId', $input)) {
      $challenge_response = $this->initiateEmailChallenge();
      if (!$challenge_response) {
        return $form;
      }
    } else {
      $challenge_response = (object)['txId' => $input['txId'], 'message' => 'Please check your email and click Accept or Deny.'];
    }
    
    $utilities = new MoAuthUtilities();
    
    $form['markup_library'] = array(
      '#attached' => array(
        'library' => array(
          "miniorange_2fa/miniorange_2fa.license",
        )
      ),
    );
    
    $form['mo_auth_otp_label'] = array(
      '#type' => 'label',
      '#title' => t($challenge_response->message),
    );
    
    $image_path = $utilities->fileCreateUrl($base_url . '/' . $utilities->moGetModulePath() . '/includes/images/ajax-loader-login.gif');
    $form['header']['#markup'] = '<img class="mo2f_image" src="' . $image_path . '">';
    
    $form['txId'] = array(
      '#type' => 'hidden',
      '#value' => $challenge_response->txId,
    );
    
    $form['url'] = array(
      '#type' => 'hidden',
      '#value' => MoAuthConstants::getBaseUrl() . MoAuthConstants::AUTH_STATUS_API,
    );

    $form['auto_submit'] = array(
      '#type' => 'submit',
      '#value' => t('Auto Submit'),
      '#attributes' => array(
        'style' => 'display: none;',
        'id' => 'mo-auth-configure-admin-2fa',
      ),
      '#name' => 'auto_submit',
    );

    $this->addFormSuffix($form);
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void {
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
    $form_values = $form_state->getValues();
    
    if (!isset($form_values['txId'])) {
      $this->addErrorMessage('Transaction ID not found. Please try again.');
      return;
    }
    $utilities = new MoAuthUtilities();
    $session = $utilities->getSession();
    $moMfaSession = $session->get("mo_auth", null);
    $email = $moMfaSession['email'];
    $auth_method = $this->getCode();
    
    $customer = $this->createCustomerProfile();
    $user_api_handler = new UsersAPIHandler($customer->getCustomerID(), $customer->getAPIKey());
    $auth_api_handler = new AuthenticationAPIHandler($customer->getCustomerID(), $customer->getAPIKey());
    
    $miniorange_user = new MiniorangeUser($customer->getCustomerID(), $email, NULL, NULL, $auth_method);
    $response = $auth_api_handler->getAuthStatus($form_values['txId']);
    if (is_object($response) && $response->status == 'SUCCESS') {
      $updateResponse = $user_api_handler->update($miniorange_user);
      if ($updateResponse->status == 'SUCCESS') {
        $result = $this->updateUserAuthenticationMethod($auth_method, $miniorange_user, $user_api_handler);
        $this->handlePostAuthenticationRedirection(
          $result['success'],
          $result['message'],
          $result['message'],
          $form_state
        );
      } else {
        $this->logError('Failed to update miniorange user after successful auth status: ' . print_r($updateResponse, TRUE), 'error');
        $this->handlePostAuthenticationRedirection(
          false,
          '',
          'An error occurred while processing your request. Please try again after sometime.',
          $form_state
        );
      }
    } elseif (is_object($response) && $response->status == 'DENIED') {
      $this->logError('Email verification DENIED for txId ' . ($form_values['txId'] ?? '') . ': ' . print_r($response, TRUE), 'warning');
      $this->handlePostAuthenticationRedirection(
        false,
        '',
        'Your transaction has been denied.',
        $form_state,
        [
          'error_route_registered' => 'miniorange_2fa.setup_twofactor',
          'error_route_unregistered' => 'user.login'
        ]
      );
    } else {
      $this->logError('Email verification pending for txId ' . ($form_values['txId'] ?? '') . ': ' . print_r($response, TRUE), 'info');
      $this->handlePostAuthenticationRedirection(
        false,
        '',
        'Email verification is still pending. Please check your email and try again.',
        $form_state,
        [
          'error_route_registered' => 'miniorange_2fa.setup_twofactor',
          'error_route_unregistered' => 'miniorange_2fa.setup_twofactor'
        ]
      );
    }
  }

  /**
   * Activate method for current user.
   */
  public function activateEmailVerification(array $configured_methods): RedirectResponse {
    $authType = $this->getCode();
    $url = Url::fromRoute('miniorange_2fa.setup_twofactor')->toString();

    if (!in_array($authType, $configured_methods)) {
      $this->addErrorMessage('Please configure this authentication method first to enable it.');
      return new RedirectResponse($url);
    }

    $miniorange_user = $this->createMiniorangeUser($authType);
    if (!$miniorange_user) {
      return new RedirectResponse($url);
    }

    $customer = $this->createCustomerProfile();
    $user_api_handler = new UsersAPIHandler($customer->getCustomerID(), $customer->getAPIKey());

    $result = $this->updateUserAuthenticationMethod($authType, $miniorange_user, $user_api_handler);

    if ($result['success']) {
      $this->addStatusMessage($result['message']);
    } else {
      $this->addErrorMessage($result['message']);
    }

    return new RedirectResponse($url);
  }

  /**
   * Initiate email verification challenge.
   */
  private function initiateEmailChallenge(): ?object {
    $session = MoAuthUtilities::getSession();
    $moMfaSession = $session->get('mo_auth');
    $email = $moMfaSession['email'];
    
    $customer = $this->createCustomerProfile();
    $miniorange_user = new MiniorangeUser($customer->getCustomerID(), $email, NULL, NULL, $this->getCode());
    
    $auth_api_handler = new AuthenticationAPIHandler($customer->getCustomerID(), $customer->getAPIKey());
    $response = $auth_api_handler->challenge($miniorange_user);
    
    if (is_object($response) && $response->status == 'SUCCESS') {
      return $response;
    } else {
      $this->addErrorMessage('Error initiating email verification: ' . MoAuthUtilities::getResponseMessage($response));
      return null;
    }
  }
}
