from unittest import mock

from django.test import TestCase
from django.contrib.auth.models import User
from ivatar.ivataraccount.auth import FedoraOpenIdConnect
from ivatar.ivataraccount.models import ConfirmedEmail
from django.test import override_settings


@override_settings(SOCIAL_AUTH_FEDORA_OIDC_ENDPOINT="https://id.example.com/")
class AuthFedoraTestCase(TestCase):
    def _authenticate(self, response):
        backend = FedoraOpenIdConnect()
        pipeline = backend.strategy.get_pipeline(backend)
        return backend.pipeline(pipeline, response=response)

    def test_new_user(self):
        """Check that a Fedora user gets a ConfirmedEmail automatically."""
        user = self._authenticate({"nickname": "testuser", "email": "test@example.com"})
        self.assertEqual(user.confirmedemail_set.count(), 1)
        self.assertEqual(user.confirmedemail_set.first().email, "test@example.com")

    @mock.patch("ivatar.ivataraccount.auth.TRUST_EMAIL_FROM_SOCIAL_AUTH_BACKENDS", [])
    def test_new_user_untrusted_backend(self):
        """Check that ConfirmedEmails aren't automatically created for untrusted backends."""
        user = self._authenticate({"nickname": "testuser", "email": "test@example.com"})
        self.assertEqual(user.confirmedemail_set.count(), 0)

    def test_existing_user(self):
        """Checks that existing users are found."""
        user = User.objects.create_user(
            username="testuser",
            password="password",
            email="test@example.com",
            first_name="test",
            last_name="user",
        )
        auth_user = self._authenticate(
            {"nickname": "testuser", "email": "test@example.com"}
        )
        self.assertEqual(auth_user, user)
        # Only add ConfirmedEmails on account creation.
        self.assertEqual(auth_user.confirmedemail_set.count(), 0)

    def test_existing_user_with_confirmed_email(self):
        """Check that the authenticating user is found using their ConfirmedEmail."""
        user = User.objects.create_user(
            username="testuser1",
            password="password",
            email="first@example.com",
            first_name="test",
            last_name="user",
        )
        ConfirmedEmail.objects.create_confirmed_email(user, "second@example.com", False)
        auth_user = self._authenticate(
            {"nickname": "testuser2", "email": "second@example.com"}
        )
        self.assertEqual(auth_user, user)

    def test_existing_confirmed_email(self):
        """Check that ConfirmedEmail isn't created twice."""
        user = User.objects.create_user(
            username="testuser",
            password="password",
            email="testuser@example.com",
            first_name="test",
            last_name="user",
        )
        ConfirmedEmail.objects.create_confirmed_email(user, user.email, False)
        auth_user = self._authenticate({"nickname": user.username, "email": user.email})
        self.assertEqual(auth_user, user)
        self.assertEqual(auth_user.confirmedemail_set.count(), 1)
