<?php

declare(strict_types=1);

namespace Drupal\miniorange_webauthn\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\miniorange_webauthn\MoCredOptBuilder\MoPubKeyCredCreateOptBuildInterface;
use Drupal\miniorange_webauthn\MoCredOptBuilder\MoPubKeyCredCreateOptionBuilder;
use Drupal\miniorange_webauthn\MoProtector\MoHandler\MoFailureHandlerInterface;
use Drupal\miniorange_webauthn\MoProtector\MoPredictor\MoUserPredictorInterface;
use Drupal\miniorange_webauthn\MoProtector\MoStorage\MoItem;
use Drupal\user\Entity\User;
use ParagonIE\ConstantTime\Base64UrlSafe;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Throwable;

final class MoAttestationReqController extends ControllerBase
{
    public function __construct(
      private readonly MoPubKeyCredCreateOptBuildInterface $extractor,
      private readonly MoUserPredictorInterface $userPredictor,
      private readonly PrivateTempStoreFactory $tempStore,
      private readonly MoFailureHandlerInterface $moFailureHandler
    ) {
    }

    public static function create(ContainerInterface $container)
    {
      return new static(
        $container->get('mo_webauthn.pub_key_cred_create_opt_builder'),
        $container->get('mo_webauthn.current_user_predictor'),
        $container->get('tempstore.private'),
        $container->get('mo_webauthn.failure_handler')
      );
    }

    public function __invoke(Request $request): Response
    {
      try {
        $userEntity = $this->userPredictor->findUser();
        $publicKeyCredentialCreationOptions = $this->extractor->getFromRequest($request, $userEntity);
        $tempStore = $this->tempStore->get('miniorange_webauthn');
        $tempStore->set('mo_webauthn_cred_create_opt', MoItem::create($publicKeyCredentialCreationOptions, $userEntity));
        return new JsonResponse($publicKeyCredentialCreationOptions);
      } catch (Throwable $throwable) {
        return $this->moFailureHandler->onAuthenticationFailure($request, $throwable);
      }
    }
}
