from django.test import TestCase

from django.contrib.auth.models import User
from apps.accounts.models import Site
from apps.notebooks.models import Notebook
from apps.workers.models import Machine, WorkerSession
from apps.workers.constants import WorkerSessionState
from apps.workers.utils import get_running_machines, shuffle_machines


from datetime import datetime

from allauth.account.admin import EmailAddress
from django.contrib.auth.models import User
from django.utils.timezone import make_aware


from apps.accounts.models import Site
from apps.notebooks.models import Notebook
from apps.workers.models import Worker

# Create your tests here.
# python manage.py test apps.workers -v 2

# python manage.py test apps.workers.tests.AnalyticsTestCase
class AnalyticsTestCase(TestCase):

    login_url = "/api/v1/auth/login/"

    def setUp(self):
        self.user = User.objects.create_user(
            username="developer",
            email="developer@example.com",
            password="developer",
        )
        EmailAddress.objects.create(
            user=self.user, email=self.user.email, verified=True, primary=True
        )
        self.site = Site.objects.create(
            title="Mercury",
            slug="single-site",
            share=Site.PUBLIC,
            created_by=self.user,
        )

        self.nb = Notebook.objects.create(
            title="some",
            slug="some",
            path="some",
            created_by=self.user,
            hosted_on=self.site,
            file_updated_at=make_aware(datetime.now()),
        )
        self.nb2 = Notebook.objects.create(
            title="some2",
            slug="some2",
            path="some2",
            created_by=self.user,
            hosted_on=self.site,
            file_updated_at=make_aware(datetime.now()),
        )

        self.user2 = User.objects.create_user(
            username="developer2",
            email="developer2@example.com",
            password="developer2",
        )
        EmailAddress.objects.create(
            user=self.user2, email=self.user2.email, verified=True, primary=True
        )

    def test_get_analytics_data(self):
        login_params = {"email": self.user.email, "password":  "developer"}
        response = self.client.post(self.login_url, login_params)
        token = response.json()["key"]
        headers = {"HTTP_AUTHORIZATION": "Token " + token}
        
        for i in range(10): 
            WorkerSession.objects.create(
                ipv4="0.0.0.0",
                state=WorkerSessionState.Running,
                owned_by=self.user,
                site=self.site,
                notebook=self.nb,
            )
            WorkerSession.objects.create(
                ipv4="0.0.0.0",
                state=WorkerSessionState.Running,
                owned_by=self.user,
                site=self.site,
                notebook=self.nb2,
            )
            WorkerSession.objects.create(
                ipv4="0.0.0.0",
                state=WorkerSessionState.Running,
                owned_by=self.user,
                site=self.site,
                notebook=self.nb2,
                run_by=self.user2
            )

        analytics_url = f"/api/v1/{self.site.id}/analytics"
        response = self.client.get(analytics_url, **headers)
        
        self.assertTrue("usage_data" in response.json())
        self.assertTrue("users_data" in response.json())


class ManageMachinesTestCase(TestCase):
    def test_get_running_machines(self):
        ms = get_running_machines()
        self.assertEqual(len(ms), 0)

        Machine.objects.create(ipv4="0.0.0.0", state="Running")
        ms = get_running_machines()
        self.assertEqual(len(ms), 1)

    def test_shuffle_machines(self):
        Machine.objects.create(ipv4="0.0.0.0", state="Running")
        Machine.objects.create(ipv4="0.0.0.0", state="Running")

        ms = get_running_machines()
        self.assertEqual(len(ms), 2)
        ms = shuffle_machines(ms)
        self.assertEqual(len(ms), 2)


class WorkerSessionTestCase(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(
            username="developer",
            email="developer@example.com",
            password="developer",
        )
        EmailAddress.objects.create(
            user=self.user, email=self.user.email, verified=True, primary=True
        )
        self.site = Site.objects.create(
            title="Mercury",
            slug="single-site",
            share=Site.PUBLIC,
            created_by=self.user,
        )

        self.nb = Notebook.objects.create(
            title="some",
            slug="some",
            path="some",
            created_by=self.user,
            hosted_on=self.site,
            file_updated_at=make_aware(datetime.now()),
        )
        self.user2 = User.objects.create_user(
            username="developer2",
            email="developer2@example.com",
            password="developer2",
        )
        EmailAddress.objects.create(
            user=self.user2, email=self.user2.email, verified=True, primary=True
        )

    def test_create(self):
        WorkerSession.objects.create(
            ipv4="0.0.0.0",
            state=WorkerSessionState.Running,
            owned_by=self.user,
            site=self.site,
            notebook=self.nb,
        )
        self.assertEqual(len(WorkerSession.objects.all()), 1)

        WorkerSession.objects.create(
            ipv4="0.0.0.0",
            state=WorkerSessionState.Running,
            owned_by=self.user,
            run_by=self.user2,
            site=self.site,
            notebook=self.nb,
        )
        self.assertEqual(len(WorkerSession.objects.all()), 2)

    def test_update(self):
        WorkerSession.objects.create(
            ipv4="0.0.0.0",
            state=WorkerSessionState.Running,
            owned_by=self.user,
            site=self.site,
            notebook=self.nb,
        )
        self.assertEqual(len(WorkerSession.objects.all()), 1)

        ws = WorkerSession.objects.get(pk=1)
        prev_created_at, prev_updated_at = ws.created_at, ws.updated_at
        ws.save()

        self.assertEqual(prev_created_at, ws.created_at)
        self.assertNotEqual(prev_updated_at, ws.updated_at)


# python manage.py test apps.workers.tests.WorkerGetUserInfoTestCase -v 2
class WorkerGetUserInfoTestCase(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(
            username="developer",
            email="developer@example.com",
            password="developer",
        )
        EmailAddress.objects.create(
            user=self.user, email=self.user.email, verified=True, primary=True
        )
        self.site = Site.objects.create(
            title="Mercury",
            slug="single-site",
            share=Site.PUBLIC,
            created_by=self.user,
        )

        self.nb = Notebook.objects.create(
            title="some",
            slug="some",
            path="some",
            created_by=self.user,
            hosted_on=self.site,
            file_updated_at=make_aware(datetime.now()),
        )

        self.user2 = User.objects.create_user(
            username="developer2",
            email="developer2@example.com",
            password="developer2",
        )
        EmailAddress.objects.create(
            user=self.user2, email=self.user2.email, verified=True, primary=True
        )

    def test_get_owner(self):
        wrk = Worker.objects.create(
            machine_id="some-id", session_id="session-some-id", notebook=self.nb
        )
        url = f"/api/v1/worker/{wrk.session_id}/{wrk.id}/{self.nb.id}/owner-and-user"
        response = self.client.get(url)

        self.assertTrue("owner" in response.data)
        self.assertTrue("username" in response.data["owner"])
        self.assertTrue("email" in response.data["owner"])
        self.assertTrue("plan" in response.data["owner"])
        # there should be user information but it should be empty dict
        self.assertTrue("user" in response.data)
        self.assertTrue(not response.data["user"])  # empty dict = user not logged

    def test_get_user(self):
        wrk = Worker.objects.create(
            machine_id="some-id",
            session_id="session-some-id",
            notebook=self.nb,
            run_by=self.user2,
        )
        url = f"/api/v1/worker/{wrk.session_id}/{wrk.id}/{self.nb.id}/owner-and-user"
        response = self.client.get(url)

        self.assertTrue("user" in response.data)
        self.assertTrue("username" in response.data["user"])
        self.assertTrue("email" in response.data["user"])
