# (c) cavaliba.com - test_data

import yaml

from django.test import override_settings
from django.test import TestCase
from django.test import TransactionTestCase
from django.urls import reverse
from django.core.cache import cache as cache_django
from django.core.management import call_command

from tests import helper

import app_home.cache as cache

from app_data.models import DataClass
from app_data.models import DataSchema
from app_data.models import DataInstance

from app_data.data import Instance
from app_data.loader import load_broker


class TestDataClass(TestCase):

    fixtures = ["test"]

    def setUp(self):
        cache.clear()

    def test_has_apikey(self):
        classobj = DataClass.objects.get(keyname='_apikey')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    def test_has_enumerate(self):
        classobj = DataClass.objects.get(keyname='_enumerate')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    def test_has_pipeline(self):
        classobj = DataClass.objects.get(keyname='_pipeline')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    def test_has_dataview(self):
        classobj = DataClass.objects.get(keyname='_dataview')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    def test_has_site(self):
        classobj = DataClass.objects.get(keyname='site')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    def test_has_app(self):
        classobj = DataClass.objects.get(keyname='app')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    def test_has_sitegroup(self):
        classobj = DataClass.objects.get(keyname='sitegroup')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    def test_has_sirene(self):
        classobj = DataClass.objects.get(keyname='sirene_template')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)
        classobj = DataClass.objects.get(keyname='sirene_public')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)
        classobj = DataClass.objects.get(keyname='sirene_message')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    def test_has_schema_test1(self):
        classobj = DataClass.objects.get(keyname='test1')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    def test_has_schema_test2(self):
        classobj = DataClass.objects.get(keyname='test2')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    def test_has_schema_test3(self):
        classobj = DataClass.objects.get(keyname='test3')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    def test_has_schema_test4(self):
        classobj = DataClass.objects.get(keyname='test4')
        self.assertIsNotNone(classobj)
        self.assertEqual(classobj.is_enabled, True)

    # def test_schema_count(self):

    #     DEFAULT = {
    #         'app': 3,
    #         'site': 4,
    #         'sitegroup': 4,
    #         'test1': 33,
    #         'test2': 1,
    #         'test3': 2,
    #         'test4': 2,
    #         '_apikey': 13,
    #         '_enumerate': 2,
    #         '_dataview': 3,
    #         '_pipeline': 2,

    #     }

    #     for classname, schemacount in DEFAULT.items():
    #         classobj = DataClass.objects.get(keyname=classname)
    #         count = DataSchema.objects.filter(classname=classname).count()
    #         # print(classname)
    #         self.assertEqual(count, schemacount)

    def test_schema_delete_allowed(self):
        datalist = yaml.safe_load('''
            - classname: _schema
              keyname: test1
              _action: delete
            ''')
        aaa = {'perms': ['p_schema_write']}
        _ = load_broker(datalist=datalist, aaa=aaa)

        classobj = DataClass.objects.filter(keyname='test1').first()
        self.assertIsNone(classobj)



    def test_schema_delete_not_allowed(self):
        datalist = yaml.safe_load('''
            - classname: _schema
              keyname: test1
              _action: delete
            ''')
        aaa = {'perms': ['p_unknown_permission']}
        _ = load_broker(datalist=datalist, aaa=aaa)

        classobj = DataClass.objects.filter(keyname='test1').first()
        self.assertIsNotNone(classobj)

#   --

    def test_schema_disable_enable_allowed(self):
        datalist = yaml.safe_load('''
            - classname: _schema
              keyname: test1
              _action: disable
            ''')
        aaa = {'perms': ['p_schema_write']}

        load_broker(datalist=datalist, aaa=aaa)
        classobj = DataClass.objects.filter(keyname='test1').first()
        self.assertEqual(classobj.is_enabled, False)

        datalist = yaml.safe_load('''
            - classname: _schema
              keyname: test1
              _action: enable
            ''')
        load_broker(datalist=datalist, aaa=aaa)
        classobj = DataClass.objects.filter(keyname='test1').first()
        self.assertEqual(classobj.is_enabled, True)

    def test_schema_disable_enable_not_allowed(self):
        datalist = yaml.safe_load('''
            - classname: _schema
              keyname: test1
              _action: disable
            ''')
        aaa = {'perms': ['p_schema_read']}
        load_broker(datalist=datalist, aaa=aaa)

        classobj = DataClass.objects.filter(keyname='test1').first()
        self.assertEqual(classobj.is_enabled, True)

#   schema field

    def test_schemafield_delete_allowed(self):
        datalist = yaml.safe_load('''
            - classname: _schema
              keyname: test0
              mystring:
                  _action: delete
            ''')
        aaa = {'perms': ['p_schema_write']}
        _ = load_broker(datalist=datalist, aaa=aaa)

        obj = DataSchema.objects.filter(
            classname='test0', keyname='mystring').first()
        self.assertIsNone(obj)

        instance = Instance(classname="test0")
        self.assertNotIn('mystring', instance.fields)

    def test_schemafield_delete_not_allowed(self):
        datalist = yaml.safe_load('''
            - classname: _schema
              keyname: test0
              mystring:
                  _action: delete
            ''')
        aaa = {'perms': ['p_unknown_permission']}
        _ = load_broker(datalist=datalist, aaa=aaa)

        instance = Instance.from_keyname(
            classname="test0", keyname="test0-01")
        self.assertIn('mystring', instance.fields)


# Instances

    # export/import
    # read

    def test_instance_read_allowed_class(self):
        instance = Instance.from_keyname(
            classname="test1", keyname="test1-01")
        aaa = {'perms': ['p_test1_read']}
        r = instance.has_read_permission(aaa=aaa)
        self.assertTrue(r)

    def test_instance_read_allowed_allclass(self):
        instance = Instance.from_keyname(
            classname="test0", keyname="test0-01")
        # instance.print()
        self.assertEqual(instance.displayname, "test0-01")
        aaa = {'perms': ['p_data_read']}
        r = instance.has_read_permission(aaa=aaa)
        self.assertTrue(r)

    def test_instance_read_allowed_admin(self):
        instance = Instance.from_keyname(
            classname="test1", keyname="test1-01")
        aaa = {'perms': ['p_data_admin']}
        r = instance.has_read_permission(aaa=aaa)
        self.assertTrue(r)

    def test_instance_read_not_allowed(self):
        instance = Instance.from_keyname(
            classname="test1", keyname="test1-01")
        aaa = {'perms': ['p_test1_read2']}
        r = instance.has_read_permission(aaa=aaa)
        self.assertFalse(r)

    # delete

    def test_instance_delete_allowed(self):
        datalist = yaml.safe_load('''
            - classname: test1
              keyname: 'test1-01'
              _action: delete
            ''')
        aaa = {'perms': ['p_test1_delete']}
        load_broker(datalist=datalist, aaa=aaa)

        # removed from DB
        classobj = DataClass.objects.filter(keyname='test1').first()
        iobj = DataInstance.objects.filter(
            classname=classobj.keyname, keyname="test1-01").first()
        self.assertIsNone(iobj)

        # removed from Instance() cache
        instance = Instance.from_keyname(
            classname="test1", keyname="test1-01")
        # instance.print()
        # self.assertFalse(instance.is_bound)
        self.assertIsNone(instance)

    def test_instance_delete_not_allowed(self):
        datalist = yaml.safe_load('''
            - classname: test1
              keyname: 'test1-01'
              _action: delete
            ''')
        aaa = {'perms': ['p_test1_delete2']}
        load_broker(datalist=datalist, aaa=aaa)

        # not removed from DB
        classobj = DataClass.objects.filter(keyname='test1').first()
        iobj = DataInstance.objects.filter(
            classname=classobj.keyname, keyname="test1-01").first()
        self.assertIsNotNone(iobj)

        # not removed from Instance() cache
        instance = Instance.from_keyname(
            classname="test1", keyname="test1-01")
        self.assertTrue(instance.is_bound)

    # enable / diable

    def test_instance_enable_allowed(self):

        datalist = yaml.safe_load('''
            - classname: test1
              keyname: 'test1-01'
              _action: disable
            ''')
        aaa = {'perms': ['p_test1_update']}
        load_broker(datalist=datalist, aaa=aaa)
        instance = Instance.from_keyname(
            classname="test1", keyname="test1-01")
        self.assertFalse(instance.is_enabled)

        datalist = yaml.safe_load('''
            - classname: test1
              keyname: 'test1-01'
              _action: enable
            ''')

        aaa = {'perms': ['p_test1_update']}
        load_broker(datalist=datalist, aaa=aaa)
        instance = Instance.from_keyname(
            classname="test1", keyname="test1-01")
        self.assertTrue(instance.is_enabled)

    def test_instance_enable_not_allowed(self):
        datalist = yaml.safe_load('''
            - classname: test1
              keyname: 'test1-01'
              _action: disable
            ''')
        aaa = {'perms': ['p_test1_update']}
        load_broker(datalist=datalist, aaa=aaa)
        instance = Instance.from_keyname(
            classname="test1", keyname="test1-01")
        self.assertFalse(instance.is_enabled)

        datalist = yaml.safe_load('''
            - classname: test1
              keyname: 'test1-01'
              _action: enable
            ''')
        aaa = {'perms': ['p_test1_update2']}
        load_broker(datalist=datalist, aaa=aaa)
        instance = Instance.from_keyname(
            classname="test1", keyname="test1-01")
        self.assertFalse(instance.is_enabled)

    def test_instance_disable_not_allowed(self):
        datalist = yaml.safe_load('''
            - classname: test1
              keyname: 'test1-01'
              _action: disable
            ''')
        aaa = {'perms': ['p_test1_update2']}
        load_broker(datalist=datalist, aaa=aaa)

        instance = Instance.from_keyname(
            classname="test1", keyname="test1-01")
        self.assertTrue(instance.is_enabled)


# Registry
