<?php

namespace Drupal\miniorange_webauthn\MoService;

class MoPubKeyProfileGenFactory
{
  /**
   * todo below can be upgraded to something like Admin configurable
   *  1. security level cna be changed
   *  2. Algorithms can be changed
   */
  private function getContext(): array
  {
    $request = \Drupal::request();

    $user_agent = $request->headers->get('User-Agent');
    $deviceType = str_contains($user_agent, 'Mobile') ? 'mobile' : 'desktop';
    return [
      'security_level' => 'high',
      'device_type' => $deviceType,
    ];
  }

  public function generateRuntimeProfile(array $context = []): array {

    if (empty($context)) {
      $context = $this->getContext();
    }
    $securityLevel = $context['security_level'] ?? 'default';
    $deviceType = $context['device_type'] ?? 'unknown';

    // Basic RP entity setup
    $rp = $this->getRPBasics();

    // Determine challenge length based on security level
    $challengeLength = $this->getChallengeLength($securityLevel);

    // Timeout policy (in milliseconds)
    $timeout = $this->getTimeOut($deviceType);

    // Attestation preference
    $attestation = $this->getAttestation($securityLevel);

    // Choose algorithms based on device support
    $algorithms = $this->getAlgorithm($deviceType);

    // Authenticator selection preferences
    $authenticatorSelection = $this->getAuthenticatorSelection($deviceType, $securityLevel);

    // Extensions: Example of adding credProps or custom flags
    $extensions = [
      'credProps' => true
    ];

    return [
      'rp' => $rp,
      'challenge_length' => $challengeLength,
      'timeout' => $timeout,
      'attestation_conveyance' => $attestation,
      'public_key_credential_parameters' => $algorithms,
      'authenticator_selection_criteria' => $authenticatorSelection,
      'extensions' => $extensions,
    ];
  }

  /**
   * @param mixed $securityLevel
   * @return int
   */
  public function getChallengeLength(mixed $securityLevel): int
  {
    return match ($securityLevel) {
      'high' => 64,
      'medium' => 48,
      default => 32,
    };
  }

  /**
   * @param mixed $deviceType
   * @return int
   */
  public function getTimeOut(mixed $deviceType): int
  {
    return match ($deviceType) {
      'mobile' => 90000,
      'desktop' => 60000,
      default => 30000,
    };
  }

  /**
   * @param mixed $securityLevel
   * @return string
   */
  public function getAttestation(mixed $securityLevel): string
  {
    return match ($securityLevel) {
      'high' => 'direct',
      'medium' => 'indirect',
      default => 'none',
    };
  }

  /**
   * @param mixed $deviceType
   * @return int[]
   */
  public function getAlgorithm(mixed $deviceType): array
  {
    return match ($deviceType) {
      'mobile' => [-7],         // ES256 (ECDSA)
      'desktop' => [-7, -257],  // ES256 and RS256
      default => [-7],
    };
  }

  /**
   * @param mixed $deviceType
   * @param mixed $securityLevel
   * @return array
   */
  public function getAuthenticatorSelection(mixed $deviceType, mixed $securityLevel): array
  {
    return [
      'authenticator_attachment' => $deviceType === 'mobile' ? 'platform' : null,
      'user_verification' => $securityLevel === 'high' ? 'required' : 'preferred',
      'resident_key' => $securityLevel === 'high' ? 'required' : 'preferred',
    ];
  }

  /**
   * @return array
   */
  public function getRPBasics(): array
  {
    return [
      'name' => \Drupal::config('system.site')->get('name'),
      'id' => \Drupal::request()->getHost(),
    ];
  }


}
