<?php

namespace Drupal\miniorange_2fa\Plugin;

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\miniorange_2fa\UsersAPIHandler;
use Drupal\miniorange_2fa\MoAuthUtilities;
use Drupal\miniorange_2fa\MoAuthConstants;
use Drupal\user\Entity\User;
/**
 * Base class for QR-based authentication types.
 */
abstract class QrBasedAuthenticationTypePluginBase extends AuthenticationTypePluginBase {

  use StringTranslationTrait;

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
    $input = $form_state->getUserInput();
    
    if (!$this->validateUserSession()) {
      return $form;
    }
    
    $user = $this->getCurrentUser();
    $user_id = $user->id();
    
    if (!$this->validateUserEmail($user_id)) {
      return $form;
    }

    if (!array_key_exists('txId', $input)) {
      $qr_response = $this->initiateQrRegistration($user_id);
      if (!$qr_response) {
        return $form;
      }
      $form = $this->QrConfigurationForm($form, $qr_response['qr_code'], $qr_response['tx_id']);
    } else {
      $tx_id = $input['txId'];
      $form = $this->QrConfigurationForm($form, '', $tx_id);
    }

    return $form;
  }

  /**
   * Initiate QR registration process.
   *
   * @param int $user_id
   *   The user ID.
   *
   * @return array|false
   *   Array with qr_code and tx_id or false on failure.
   */
  protected function initiateQrRegistration(int $user_id) {
        $miniorange_user = $this->createMiniorangeUser($this->getCode());
    if (!$miniorange_user) {
      return false;
    }
    
    $auth_api_handler = $this->createAuthApiHandler();
    $response = $auth_api_handler->register($miniorange_user, 'MOBILE AUTHENTICATION', null, null, null);
  
    if (!$this->validateApiResponse($response, 'QR registration')) {
      $utilities = new MoAuthUtilities();
      $utilities->redirectUserToSetupTwoFactor('An error occurred while processing your request. Please try again after sometime.');
      return false;
    }
    
    if ($response->status != 'IN_PROGRESS') {
      $this->logError('QR registration failed: ' . ($response->message ?? 'Unknown error'));
      $utilities = new MoAuthUtilities();
      $utilities->redirectUserToSetupTwoFactor('An error occurred while processing your request. Please try again after sometime.');
      return false;
    }
    
    $utilities = new MoAuthUtilities();
    $session = $utilities->getSession();
    $moMfaSession = $session->get("mo_auth", null);
    $moMfaSession['mo_challenge_response'] = $response;
    $session->set("mo_auth", $moMfaSession);

    return [
      'qr_code' => $response->qrCode ?? '',
      'tx_id' => $response->txId ?? ''
    ];
  }

  /**
   * Build the QR configuration form.
   *
   * @param array $form
   *   The form array.
   * @param string $qr_code
   *   The QR code data.
   * @param string $tx_id
   *   The transaction ID.
   *
   * @return array
   *   The form array.
   */
  protected function QrConfigurationForm(array $form, string $qr_code, string $tx_id): array {
    $this->setFormTitle($form, 'qr-based-methods');
    $this->addFormSuffix($form);
 
    $current_route = \Drupal::routeMatch()->getRouteName();
    $form_id = ($current_route === 'miniorange_2fa.configure_enduser_2fa') ? 'mo-auth-configure-enduser-2fa' : 'mo-auth-configure-admin-2fa';
    
    $form['#attributes']['id'] = $form_id;
    
    $form['markup_library'] = [
      '#attached' => [
        'library' => [
          "miniorange_2fa/miniorange_2fa.license",
        ]
      ],
    ];
    
    $qr_method = $this->toArray();

    if (!empty($qr_code)) {
      $form['mo_install_miniorange_authenticator'] = [
        '#markup' => $this->buildDownloadInstructions($qr_method),
      ];

      $form['step_two'] = [
        '#markup' => '<h5>' . $this->t('Step 2: Scan this QR code with the app, the form will submit automatically') . '</h5>',
      ];

      $image = new FormattableMarkup('<img class="mo_2fa_qr_code_image" src="data:image/jpg;base64, @qr_code"/>', ['@qr_code' => $qr_code]);
      $form['mo_qr_code_miniorange_authenticator']['actions_qrcode'] = [
        '#markup' => $image,
      ];
    }

    $form['mo_qr_code_miniorange_authenticator']['txId'] = [
      '#type' => 'hidden',
      '#value' => $tx_id
    ];
    
    $form['mo_qr_code_miniorange_authenticator']['url'] = [
      '#type' => 'hidden',
      '#value' => MoAuthConstants::getBaseUrl() . MoAuthConstants::AUTH_REGISTRATION_STATUS_API,
    ];
    
    $form['mo_qr_code_miniorange_authenticator']['authTypeCode'] = [
      '#type' => 'hidden',
      '#value' => $this->getCode()
    ];

    $form['actions_submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Save'),
      '#id' => $form_id,
      '#hidden' => TRUE,
      '#attributes' => ['class' => ['hidebutton']],
    ];

    return $form;
  }

  /**
   * Build download instructions markup.
   *
   * @param array $qr_method
   *   The QR method configuration.
   *
   * @return string
   *   The download instructions markup.
   */
  protected function buildDownloadInstructions(array $qr_method): string {
    $ios_link = $qr_method['ios_link'] ?? '';
    $android_link = $qr_method['android_link'] ?? '';
    $method_name = $qr_method['name'] ?? 'miniOrange Authenticator';

    return '<h5>' . $this->t('Step 1: Download the @method_name app', ['@method_name' => $method_name]) . '</h5>
            <ul>
              <li class="two-step-verification--app-item--ios">iPhone, iPod Touch, or iPad: <a target="_blank" href="' . $ios_link . '">' . $this->t('Download @method_name', ['@method_name' => $method_name]) . '</a></li>
              <li class="two-step-verification--app-item--android">Android devices: <a target="_blank" href="' . $android_link . '">' . $this->t('Download Authenticator') . '</a></li>
            </ul><hr>';
  }

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

  }
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
    $input = $form_state->getUserInput();
    $auth_method = $this->getCode();

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

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

    $tx_id = $input['txId'] ?? '';
    $response = $auth_api_handler->getRegistrationStatus($tx_id);

    \Drupal::messenger()->deleteAll();

    if (!$this->validateApiResponse($response, 'QR registration status')) {
      $form_state->setRedirect('miniorange_2fa.setup_twofactor');
      return;
    }
    
    if (is_object($response) && $response->status == 'SUCCESS') {
      $this->handleSuccessfulQrRegistration($auth_method, $user_api_handler, $user, $form_state);
    } else {
      $this->addErrorMessage('QR code registration failed. Please try again.');
      $form_state->setRedirect('miniorange_2fa.setup_twofactor');
    }
  }
  /**
   * Handle successful QR registration for AJAX submission.
   *
   * @param string $auth_method
   *   The authentication method.
   * @param UsersAPIHandler $user_api_handler
   *   The user API handler.
   * @param object $user
   *   The user object.
   */
  protected function handleSuccessfulQrRegistration(string $auth_method, UsersAPIHandler $user_api_handler, $user, FormStateInterface $form_state = null) {
    $miniorange_user = $this->createMiniorangeUser($auth_method);
    if (!$miniorange_user) {
      if ($form_state) {
        $form_state->setRedirect('miniorange_2fa.setup_twofactor');
        return;
      }
      return $this->createRedirectResponse('miniorange_2fa.setup_twofactor');
    }
  
    $utilities = new MoAuthUtilities();
    $custom_attribute = $utilities::get_users_custom_attribute($user->id());
    $has_registered_email = !empty($custom_attribute) && !empty($custom_attribute[0]->miniorange_registered_email);
    
    $qr_methods = $has_registered_email ? $this->getQrBasedMethodCodes() : [];
    
    $result = $this->updateUserAuthenticationMethod($auth_method, $miniorange_user, $user_api_handler, [], false, $qr_methods);
    
    return $this->handlePostAuthenticationRedirection(
      $result['success'],
      $result['message'],
      $result['message']
    );
  }

  /**
   * Get QR-based method codes.
   *
   * @return array
   *   Array of QR-based method codes.
   */
  protected function getQrBasedMethodCodes(): array {
    return [
      'SOFT TOKEN',
      'MOBILE AUTHENTICATION', 
      'PUSH NOTIFICATIONS'
    ];
  }
} 