import webauthn
from django.contrib.auth import get_user_model
from django.contrib.sites.shortcuts import get_current_site

from .models import AuthData


class WebAuthinBackend:
    def get_user(self, user_id):
        """Get a user by their primary key."""
        User = get_user_model()
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

    def authenticate(self, request, credential_id=None, credential_json=None):
        """Authenticate a user given a WebAuthn assertion response."""
        challenge = request.session.get("challenge")
        if not challenge:
            return None

        auth_data = AuthData.objects.filter(credential_id=credential_id).first()
        if not auth_data:
            return None

        site = get_current_site(request)

        try:
            verification = webauthn.verify_authentication_response(
                credential=credential_json,
                expected_challenge=webauthn.base64url_to_bytes(challenge),
                expected_rp_id=site.domain,
                expected_origin="https://%s" % site.domain,
                credential_public_key=webauthn.base64url_to_bytes(auth_data.public_key),
                credential_current_sign_count=auth_data.sign_count,
                require_user_verification=True,
            )
        except Exception:
            return None

        # TODO: Validate the sign count here (https://w3c.github.io/webauthn/#signature-counter)
        auth_data.set_sign_count(verification.new_sign_count)
        return auth_data.user
