from django.test import TestCase
from rest_framework.test import APIRequestFactory, force_authenticate

from rest_framework.reverse import reverse
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError, FieldError

from .views import *
from .models import *

from uncloud_pay.models import BillingAddress, Order
from uncloud.models import UncloudNetwork

class UncloudNetworkTests(TestCase):
    def test_invalid_IPv4_network(self):
        with self.assertRaises(FieldError):
            UncloudNetwork.objects.create(network_address="192.168.1.0",
                                          network_mask=33)

class VPNTests(TestCase):
    def setUp(self):
        self.user = get_user_model().objects.create_user('django-test-user', 'noreply@ungleich.ch')
        self.admin_user = get_user_model().objects.create_user('django-test-adminuser',
                                                               'noreply-admin@ungleich.ch')



        self.admin_user.is_staff = True
        self.admin_user.save()

        self.pool_network = '2001:db8::'
        self.pool_network2 = '2001:db8:1::'
        self.pool_network_size = '48'
        self.pool_subnetwork_size = '64'
        self.pool_vpn_hostname = 'vpn.example.org'
        self.pool_wireguard_private_key = 'MOz8kk0m4jhNtAXlge0qzexZh1MipIhu4HJwtdvZ2EY='

        self.vpn_wireguard_public_key = 'B2b78eWBIXPMM1x4DDjkCDZepS0qDgcLN3T3PjcgXkY='

        self.vpnpool = VPNPool.objects.get_or_create(network=self.pool_network,
                                                     network_size=self.pool_network_size,
                                                     subnetwork_size=self.pool_subnetwork_size,
                                                     vpn_hostname=self.pool_vpn_hostname,
                                                     wireguard_private_key=self.pool_wireguard_private_key
        )

        self.factory = APIRequestFactory()


    def test_create_vpnpool(self):
        url = reverse("vpnpool-list")
        view = VPNPoolViewSet.as_view({'post': 'create'})
        request = self.factory.post(url, { 'network': self.pool_network2,
                                           'network_size': self.pool_network_size,
                                           'subnetwork_size': self.pool_subnetwork_size,
                                           'vpn_hostname': self.pool_vpn_hostname,
                                           'wireguard_private_key': self.pool_wireguard_private_key

        })
        force_authenticate(request, user=self.admin_user)
        response = view(request)

        # This raises an exception if the request was not successful
        # No assert needed
        pool = VPNPool.objects.get(network=self.pool_network2)

    # def test_create_vpn(self):
    #     url = reverse("vpnnetwork-list")
    #     view = VPNNetworkViewSet.as_view({'post': 'create'})
    #     request = self.factory.post(url, { 'network_size': self.pool_subnetwork_size,
    #                                        'wireguard_public_key': self.vpn_wireguard_public_key

    #     })
    #     force_authenticate(request, user=self.user)


    #     # we don't have a billing address -> should raise an error
    #     # with self.assertRaises(ValidationError):
    #     #     response = view(request)

    #     addr = BillingAddress.objects.get_or_create(
    #         owner=self.user,
    #         active=True,
    #         defaults={'organization': 'ungleich',
    #                   'name': 'Nico Schottelius',
    #                   'street': 'Hauptstrasse 14',
    #                   'city': 'Luchsingen',
    #                   'postal_code': '8775',
    #                   'country': 'CH' }
    #     )

    #     # This should work now
    #     response = view(request)

    #     # Verify that an order was created successfully - there should only be one order at
    #     # this point in time
    #     order = Order.objects.get(owner=self.user)


    def tearDown(self):
        self.user.delete()
        self.admin_user.delete()