<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Repository;

use Ferienpass\CoreBundle\Entity\User;
use Symfony\Component\Uid\Uuid;
use Webauthn\Bundle\Repository\CanGenerateUserEntity;
use Webauthn\Bundle\Repository\CanRegisterUserEntity;
use Webauthn\Bundle\Repository\PublicKeyCredentialUserEntityRepositoryInterface;
use Webauthn\PublicKeyCredentialUserEntity;

class WebauthnUserEntityRepository implements PublicKeyCredentialUserEntityRepositoryInterface, CanRegisterUserEntity, CanGenerateUserEntity
{
    /**
     * The UserRepository $userRepository is the repository
     * that already exists in the application.
     */
    public function __construct(private readonly UserRepository $userRepository)
    {
    }

    public function findOneByUsername(string $username): ?PublicKeyCredentialUserEntity
    {
        /** @var User|null $user */
        $user = $this->userRepository->findOneBy([
            'email' => $username,
        ]);

        return $this->getUserEntity($user);
    }

    public function findOneByUserHandle(string $userHandle): ?PublicKeyCredentialUserEntity
    {
        if (!Uuid::isValid($userHandle)) {
            return null;
        }

        /** @var User|null $user */
        $user = $this->userRepository->findOneBy([
            'uuid' => Uuid::fromString($userHandle),
        ]);

        return $this->getUserEntity($user);
    }

    /**
     * Members are created through the regular registration flow, so the user
     * entity always maps to an already-persisted {@see User}. Persisting the
     * credential itself is the credential repository's responsibility, so there
     * is nothing to store here.
     */
    public function saveUserEntity(PublicKeyCredentialUserEntity $userEntity): void
    {
    }

    public function generateUserEntity(?string $username, ?string $displayName): PublicKeyCredentialUserEntity
    {
        return new PublicKeyCredentialUserEntity(
            $username ?? '',
            Uuid::v7()->toRfc4122(),
            $displayName ?? $username ?? '',
            null
        );
    }

    /**
     * Converts a Symfony User (if any) into a Webauthn User Entity.
     *
     * The user handle is the user's UUID — a stable, opaque value that contains
     * no personal data, as required by the WebAuthn spec.
     */
    private function getUserEntity(?User $user): ?PublicKeyCredentialUserEntity
    {
        if (!$user instanceof User) {
            return null;
        }

        return new PublicKeyCredentialUserEntity(
            $user->getUsername(),
            $user->getUuid()->toRfc4122(),
            $user->getName(),
            null
        );
    }
}
