"""Utility functions shared by all crashreport stats tests."""

from datetime import datetime
from typing import Any, Union, Type

import pytz
from django.contrib.auth.models import Group
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.test import APITestCase, APIClient

from crashreport_stats.models import (
    Version,
    VersionDaily,
    RadioVersion,
    RadioVersionDaily,
    StatsMetadata,
)

from crashreports.models import User
from crashreports.tests.utils import Dummy as CrashreportsDummy
from hiccup.allauth_adapters import FP_STAFF_GROUP_NAME


class Dummy(CrashreportsDummy):
    """Class for creating dummy instances for testing."""

    DEFAULT_VERSION_VALUES = {
        "build_fingerprint": CrashreportsDummy.BUILD_FINGERPRINTS[0],
        "first_seen_on": CrashreportsDummy.DATES[1],
        "released_on": CrashreportsDummy.DATES[0],
        "is_beta_release": False,
        "is_official_release": True,
    }

    DEFAULT_VERSION_DAILY_VALUES = {"date": CrashreportsDummy.DATES[1]}

    DEFAULT_RADIO_VERSION_VALUES = {
        "radio_version": CrashreportsDummy.RADIO_VERSIONS[0],
        "first_seen_on": CrashreportsDummy.DATES[1],
        "released_on": CrashreportsDummy.DATES[0],
    }

    DEFAULT_RADIO_VERSION_DAILY_VALUES = {"date": CrashreportsDummy.DATES[1]}

    DEFAULT_STATSMETADATA_VALUES = {
        "updated_at": datetime(2018, 6, 15, 2, 12, 24, tzinfo=pytz.utc)
    }

    @staticmethod
    def create_version(
        version_type: Type[Union[Version, RadioVersion]] = Version,
        **kwargs: Any
    ) -> Union[Version, RadioVersion]:
        """Create a dummy version instance.

        The dummy instance is created and saved to the database.
        Args:
            version_type: The class of the version type to be created.
            **kwargs:
                Optional arguments to extend/overwrite the default values.

        Returns: The created version instance.

        Raises:
            ValueError: If version_type is not a valid version class type.

        """
        if version_type == Version:
            entity = Version(
                **Dummy._update_copy(Dummy.DEFAULT_VERSION_VALUES, kwargs)
            )
        elif version_type == RadioVersion:
            entity = RadioVersion(
                **Dummy._update_copy(Dummy.DEFAULT_RADIO_VERSION_VALUES, kwargs)
            )
        else:
            raise ValueError(
                "No dummy version instance can be created for {}".format(
                    version_type.__name__
                )
            )
        entity.save()
        return entity

    @staticmethod
    def create_daily_version(version: Version, **kwargs: Any) -> VersionDaily:
        """Create a dummy daily version instance.

        The dummy instance is created and saved to the database.
        Args:
            **kwargs:
                Optional arguments to extend/overwrite the default values.

        Returns: The created daily version instance.

        """
        entity = VersionDaily(
            version=version,
            **Dummy._update_copy(Dummy.DEFAULT_VERSION_DAILY_VALUES, kwargs)
        )
        entity.save()
        return entity

    @staticmethod
    def create_daily_radio_version(
        version: RadioVersion, **kwargs: Any
    ) -> RadioVersionDaily:
        """Create a dummy daily radio version instance.

        The dummy instance is created and saved to the database.
        Args:
            **kwargs:
                Optional arguments to extend/overwrite the default values.

        Returns: The created daily radio version instance.

        """
        entity = RadioVersionDaily(
            version=version,
            **Dummy._update_copy(
                Dummy.DEFAULT_RADIO_VERSION_DAILY_VALUES, kwargs
            )
        )
        entity.save()
        return entity

    @staticmethod
    def create_stats_metadata(**kwargs: Any) -> StatsMetadata:
        """Create a dummy stats metadata instance.

        The dummy instance is created and saved to the database.
        Args:
            **kwargs:
                Optional arguments to extend/overwrite the default values.

        Returns: The created stats metadata instance.

        """
        entity = StatsMetadata(
            **Dummy._update_copy(Dummy.DEFAULT_STATSMETADATA_VALUES, kwargs)
        )
        entity.save()
        return entity


class HiccupStatsAPITestCase(APITestCase):
    """Abstract class for Hiccup stats REST API test cases to inherit from."""

    @classmethod
    def setUpTestData(cls):  # noqa: N802
        """Create client users for accessing the API.

        The APIClient that can be used to make authenticated requests as
        Fairphone staff user is stored in self.fp_staff_client. Additionally, a
        client which is related to a device owner user is stored in
        self.device_owner_client.
        """
        fp_staff_group = Group.objects.get(name=FP_STAFF_GROUP_NAME)
        fp_staff_user = User.objects.create_user(
            "fp_staff", "somebody@fairphone.com", "thepassword"
        )
        fp_staff_user.groups.add(fp_staff_group)
        cls.fp_staff_client = APIClient()
        cls.fp_staff_client.force_login(fp_staff_user)

        cls.device_owner_user = User.objects.create_user(
            "device_owner", "somebody@somemail.com", "thepassword"
        )
        Token.objects.create(user=cls.device_owner_user)
        cls.device_owner_device = Dummy.create_device(
            user=cls.device_owner_user
        )
        cls.device_owner_client = APIClient()
        cls.device_owner_client.credentials(
            HTTP_AUTHORIZATION="Token " + cls.device_owner_user.auth_token.key
        )
        cls.device_owner_client.force_login(cls.device_owner_user)

    def _assert_get_as_fp_staff_succeeds(
        self, url, expected_status=status.HTTP_200_OK
    ):
        response = self.fp_staff_client.get(url)
        self.assertEqual(response.status_code, expected_status)

    def _assert_get_without_authentication_fails(
        self, url, expected_status=status.HTTP_401_UNAUTHORIZED
    ):
        response = self.client.get(url)
        self.assertEqual(response.status_code, expected_status)

    def _assert_get_as_device_owner_fails(
        self, url, expected_status=status.HTTP_403_FORBIDDEN
    ):
        response = self.device_owner_client.get(url)
        self.assertEqual(response.status_code, expected_status)
