from django.contrib.auth.models import User
from django.test import tag
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase

from ..models import CtClient


class TestCoreApi(APITestCase):
    """Unit tests for useradm API."""
    User1_name = 'Nick Fury'
    User2_name = 'Phil Coulson'
    # Random IBANs generated by http://randomiban.com/
    Client1 = {'first_name': 'Steve', 'last_name': 'Rogers', 'iban': 'KZ568298821363634358'}
    Client2 = {'first_name': 'Bruce', 'last_name': 'Banner', 'iban': 'BG89IORT80946945979686'}
    Client3 = {'first_name': 'Tony', 'last_name': 'Stark', 'iban': 'NL35ABNA7925653426'}

    another_iban = 'MU29WTGN1677322935321967385FOT'

    def _url_pk(self, pk):
        """Mount an url from pk
        Args:
            pk (int): primary key.
        Return:
            str: API endpoint, example  31416 = /api/v1/useradm/31416/
        """
        return "{url}{pk}/".format(url=self.url, pk=pk)

    def setUp(self):
        # Running before every test
        self.url = reverse('ctclient-list')
        self.user = User.objects.create(username=self.User1_name)
        self.client.force_authenticate(self.user)

    @tag('unit')
    def test_api_client_post(self):
        """Tests API POST method"""
        data = self.Client1

        response = self.client.post(self.url, data, format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(CtClient.objects.count(), 1)
        self.assertEqual(CtClient.objects.get().first_name, self.Client1['first_name'].lower())
        self.assertEqual(CtClient.objects.get().last_name, self.Client1['last_name'].lower())
        self.assertEqual(CtClient.objects.get().iban,  self.Client1['iban'])
        self.assertEqual(CtClient.objects.get().owner, self.user)

    @tag('unit')
    def test_api_client_get(self):
        """Tests API GET method"""
        client_1 = CtClient.objects.create(
            first_name=self.Client1['first_name'], last_name=self.Client1['last_name'], iban=self.Client1['iban'],
            owner=self.user)
        client_2 = CtClient.objects.create(
            first_name=self.Client2['first_name'], last_name=self.Client2['last_name'], iban=self.Client2['iban'],
            owner=self.user)

        response = self.client.get(self.url)
        self.assertEqual(CtClient.objects.count(), 2)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).first_name, self.Client1['first_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).last_name, self.Client1['last_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).iban, self.Client1['iban'])
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).owner, self.user)
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).first_name, self.Client2['first_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).last_name, self.Client2['last_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).iban, self.Client2['iban'])
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).owner, self.user)

    @tag('unit')
    def test_api_client_put(self):
        """Tests API PUT method"""
        user = User.objects.create(username=self.User2_name)
        client_1 = CtClient.objects.create(
            first_name=self.Client1['first_name'], last_name=self.Client1['last_name'], iban=self.Client1['iban'],
            owner=self.user)
        client_2 = CtClient.objects.create(
            first_name=self.Client2['first_name'], last_name=self.Client2['last_name'], iban=self.Client2['iban'],
            owner=user)

        self.assertEqual(CtClient.objects.get(pk=client_1.pk).first_name, self.Client1['first_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).last_name, self.Client1['last_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).iban, self.Client1['iban'])
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).owner, self.user)

        self.assertEqual(CtClient.objects.get(pk=client_2.pk).first_name, self.Client2['first_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).last_name, self.Client2['last_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).iban, self.Client2['iban'])
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).owner, user)

        data = self.Client3

        response = self.client.put(self._url_pk(client_2.pk), data, format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

        response = self.client.put(self._url_pk(client_1.pk), data, format='json')
        self.assertEqual(CtClient.objects.count(), 2)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).first_name, self.Client3['first_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).last_name,  self.Client3['last_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).iban,  self.Client3['iban'])
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).owner, self.user)

    @tag('unit')
    def test_api_client_patch(self):
        """Tests API PATCH method"""
        user = User.objects.create(username=self.User2_name)
        client_1 = CtClient.objects.create(
            first_name=self.Client1['first_name'], last_name=self.Client1['last_name'], iban=self.Client1['iban'],
            owner=self.user)
        client_2 = CtClient.objects.create(
            first_name=self.Client2['first_name'], last_name=self.Client2['last_name'], iban=self.Client2['iban'],
            owner=user)

        self.assertEqual(CtClient.objects.get(pk=client_1.pk).first_name, self.Client1['first_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).last_name, self.Client1['last_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).iban, self.Client1['iban'])
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).owner, self.user)

        self.assertEqual(CtClient.objects.get(pk=client_2.pk).first_name, self.Client2['first_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).last_name, self.Client2['last_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).iban, self.Client2['iban'])
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).owner, user)

        data = {
            'iban': self.another_iban
        }

        response = self.client.patch(self._url_pk(client_2.pk), data, format='json')
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

        response = self.client.patch(self._url_pk(client_1.pk), data, format='json')
        self.assertEqual(CtClient.objects.count(), 2)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).first_name, self.Client1['first_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).last_name, self.Client1['last_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).iban, self.another_iban)
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).owner, self.user)

    @tag('unit')
    def test_api_client_delete(self):
        """Tests API DELETE method"""
        user = User.objects.create(username=self.User2_name)
        client_1 = CtClient.objects.create(
            first_name=self.Client1['first_name'], last_name=self.Client1['last_name'], iban=self.Client1['iban'],
            owner=self.user)
        client_2 = CtClient.objects.create(
            first_name=self.Client2['first_name'], last_name=self.Client2['last_name'], iban=self.Client2['iban'],
            owner=user)

        self.assertEqual(CtClient.objects.count(), 2)

        self.assertEqual(CtClient.objects.get(pk=client_1.pk).first_name, self.Client1['first_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).last_name, self.Client1['last_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).iban, self.Client1['iban'])
        self.assertEqual(CtClient.objects.get(pk=client_1.pk).owner, self.user)

        self.assertEqual(CtClient.objects.get(pk=client_2.pk).first_name, self.Client2['first_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).last_name, self.Client2['last_name'].lower())
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).iban, self.Client2['iban'])
        self.assertEqual(CtClient.objects.get(pk=client_2.pk).owner, user)

        response = self.client.delete(self._url_pk(client_2.pk))
        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

        response = self.client.delete(self._url_pk(client_1.pk))
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
        self.assertEqual(CtClient.objects.count(), 1)

