"""
Tests for aliases API endpoint in People's app mailbox_manager.
Focus on "delete" action.
"""
# pylint: disable=W0613

import re

import pytest
import responses
from rest_framework import status
from rest_framework.test import APIClient

from core import factories as core_factories

from mailbox_manager import enums, factories, models

pytestmark = pytest.mark.django_db


def test_api_aliases_delete__anonymous():
    """Anonymous user should not be able to delete aliases."""
    alias_ = factories.AliasFactory()

    response = APIClient().delete(
        f"/api/v1.0/mail-domains/{alias_.domain.slug}/aliases/{alias_.pk}/"
    )

    assert response.status_code == status.HTTP_401_UNAUTHORIZED
    assert models.Alias.objects.count() == 1


def test_api_aliases_delete__no_access_forbidden_not_found():
    """
    Authenticated users should not be allowed to delete an alias in a
    mail domain to which they are not related.
    """
    authenticated_user = core_factories.UserFactory()
    alias_ = factories.AliasFactory()

    client = APIClient()
    client.force_login(authenticated_user)
    response = client.delete(
        f"/api/v1.0/mail-domains/{alias_.domain.slug}/aliases/{alias_.pk}/"
    )

    assert response.status_code == status.HTTP_404_NOT_FOUND
    assert models.Alias.objects.count() == 1


def test_api_aliases_delete__viewer_forbidden():
    """
    Authenticated users should not be allowed to delete aliases for a
    mail domain in which they are a simple viewer.
    """
    authenticated_user = core_factories.UserFactory()
    mail_domain = factories.MailDomainFactory(
        users=[(authenticated_user, enums.MailDomainRoleChoices.VIEWER)]
    )
    alias_ = factories.AliasFactory(domain=mail_domain)

    client = APIClient()
    client.force_login(authenticated_user)
    response = client.delete(
        f"/api/v1.0/mail-domains/{mail_domain.slug}/aliases/{alias_.pk}/"
    )

    assert response.status_code == status.HTTP_403_FORBIDDEN
    assert models.Alias.objects.count() == 1


@responses.activate
def test_api_aliases_delete__administrators_allowed(dimail_token_ok):
    """
    Administrators of a mail domain should be allowed to delete aliases.
    """
    authenticated_user = core_factories.UserFactory()
    mail_domain = factories.MailDomainFactory(
        users=[(authenticated_user, enums.MailDomainRoleChoices.ADMIN)]
    )
    alias_ = factories.AliasFactory(domain=mail_domain)
    factories.AliasFactory.create_batch(
        2, domain=mail_domain, local_part=alias_.local_part
    )

    # additional aliases that shouldn't be affected
    factories.AliasFactory.create_batch(
        2, domain=mail_domain, destination=alias_.destination
    )
    factories.AliasFactory(
        local_part=alias_.local_part,
        destination=alias_.destination,
    )

    # Mock dimail response
    responses.delete(
        re.compile(r".*/aliases/"),
        status=status.HTTP_204_NO_CONTENT,
        content_type="application/json",
    )

    client = APIClient()
    client.force_login(authenticated_user)
    response = client.delete(
        f"/api/v1.0/mail-domains/{mail_domain.slug}/aliases/{alias_.pk}/"
    )
    assert response.status_code == status.HTTP_204_NO_CONTENT
    assert models.Alias.objects.count() == 5


@responses.activate
def test_api_aliases_delete__404_out_of_sync(dimail_token_ok):
    """
    Should return a clear message when dimail returns 404 not found.
    """
    authenticated_user = core_factories.UserFactory()
    mail_domain = factories.MailDomainFactory(
        users=[(authenticated_user, enums.MailDomainRoleChoices.ADMIN)]
    )
    alias_ = factories.AliasFactory(domain=mail_domain)
    # Mock dimail response
    responses.delete(
        re.compile(r".*/aliases/"),
        json={"detail": "Not found"},
        status=status.HTTP_404_NOT_FOUND,
        content_type="application/json",
    )

    client = APIClient()
    client.force_login(authenticated_user)
    response = client.delete(
        f"/api/v1.0/mail-domains/{mail_domain.slug}/aliases/{alias_.pk}/"
    )
    assert response.status_code == status.HTTP_200_OK
    assert (
        response.json()
        == "Domain out of sync with mailbox provider, please contact our support."
    )
    assert not models.Alias.objects.exists()
