# (c) cavaliba.com - tests / pipeline

import yaml 
from io import StringIO

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 tests import helper

import app_home.cache as cache

from app_data.loader import load_broker

from app_data.pipeline import list_pipelines
from app_data.pipeline import get_pipeline
from app_data.pipeline import apply_pipeline


class PipelineCRUD(TestCase):

    fixtures = ["init"]

    def setUp(self):
        helper.add_admin_user(login="unittest")
        cache.clear()
        cache_django.clear()



    def test_list_pipelines(self):

        pipelines = list_pipelines()
        self.assertEqual(len(pipelines), 0)


    def test_create_pipeline(self):

        helper.add_pipeline_noop()    
        pipelines = list_pipelines()
        self.assertEqual(len(pipelines), 1)


    def test_get_pipeline(self):

        helper.add_pipeline_noop()
        pipeline_data = get_pipeline("pipeline_noop")
        self.assertEqual(pipeline_data["tasks"],["field_noop"])


    def test_create_pipeline_disabled(self):

        helper.add_pipeline_noop() 

        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest2
              displayname: unittest_pipeline
              description: unittest pipeline
              is_enabled: False
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks: 
                  - field_noop                                                   
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        pipelines = list_pipelines(is_enabled=True)
        self.assertEqual ( len(pipelines), 1)

        pipelines = list_pipelines(is_enabled=False)
        self.assertEqual ( len(pipelines), 2)


    # primitives with schema

    def test_pipeline_discard(self):

        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest
              displayname: unittest_pipeline
              description: unittest pipeline
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks: 
                  - discard: ['']
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        datalist = [
            {'a':5, 'b':6},
            {'a':'unit', 'b':'test'},
        ]
        datalist = apply_pipeline(pipeline="unittest", datalist = datalist)
        self.assertEqual( len(datalist), 0)



    def test_pipeline_condition(self):

        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest
              displayname: unittest_pipeline
              description: unittest pipeline
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks: 
                  - set_condition: ['CONDITION_TEST', field_match, a, 'test']
                  - field_set: ['CONDITION_TEST', b, 'testok']
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        datalist = [
            {'a':'test'},
        ]
        datalist = apply_pipeline(pipeline="unittest", datalist = datalist)
        self.assertIn('a',datalist[0])
        self.assertIn('b',datalist[0])
        self.assertEqual( datalist[0]['b'], 'testok')


    def test_pipeline_condition_negate(self):

        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest
              displayname: unittest_pipeline
              description: unittest pipeline
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks: 
                  - set_condition: [CONDITION_TEST, field_match, a, 'test']
                  - field_set: ['!CONDITION_TEST', b, 'testok']
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        datalist = [
            {'a':'unit'},
        ]
        datalist = apply_pipeline(pipeline="unittest", datalist = datalist)
        self.assertIn('a',datalist[0])
        self.assertIn('b',datalist[0])
        self.assertEqual( datalist[0]['b'], 'testok')


    def test_pipeline_condition_reset_to_false(self):
        # set_condition should reset to false when condition no longer matches
        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest
              displayname: unittest_pipeline
              description: unittest pipeline
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks:
                  - set_condition: [COND, field_match, a, 'yes']
                  - set_condition: [COND, field_match, b, 'yes']
                  - field_set: [COND, c, 'shouldnotbeset']
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        # a='yes' sets COND true, b='no' resets COND to false => field_set must not run
        datalist = [
            {'a': 'yes', 'b': 'no'},
        ]
        datalist = apply_pipeline(pipeline="unittest", datalist=datalist)
        self.assertNotIn('c', datalist[0])

    def test_pipeline_condition_set_then_true(self):
        # set_condition evaluates false first, then true => task must run
        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest
              displayname: unittest_pipeline
              description: unittest pipeline
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks:
                  - set_condition: [COND, field_match, a, 'yes']
                  - set_condition: [COND, field_match, b, 'yes']
                  - field_set: [COND, c, 'shouldbeset']
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        # a='no' keeps COND false, b='yes' sets COND true => field_set must run
        datalist = [
            {'a': 'no', 'b': 'yes'},
        ]
        datalist = apply_pipeline(pipeline="unittest", datalist=datalist)
        self.assertIn('c', datalist[0])
        self.assertEqual(datalist[0]['c'], 'shouldbeset')


