# (c) cavaliba.com - tests / pipeline

import yaml
from django.core.cache import cache as cache_django
from django.test import TestCase

import app_home.cache as cache
from app_data.loader import load_broker
from app_data.pipeline import Pipeline
from tests import helper


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

    def test_list_pipelines(self):

        count1 = len(Pipeline.list())
        pipelines = Pipeline.list()
        self.assertGreaterEqual(len(pipelines), 5)

    def test_create_pipeline(self):

        count1 = len(Pipeline.list())
        helper.add_pipeline_noop()
        count2 = len(Pipeline.list())
        self.assertEqual(count1 + 1, count2)

    def test_pipeline_from_name(self):

        helper.add_pipeline_noop()
        pipeline = Pipeline.from_name("pipeline_noop")
        self.assertIsNotNone(pipeline)
        self.assertEqual(pipeline.keyname, "pipeline_noop")
        self.assertEqual(pipeline.tasks, ["field_noop"])

    def test_pipeline_not_found(self):

        pipeline = Pipeline.from_name("does_not_exist")
        self.assertIsNone(pipeline)

    def test_create_pipeline_disabled(self):

        pipelines = Pipeline.list(is_enabled=True)
        self.assertGreaterEqual(len(pipelines), 5)

        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 = Pipeline.list(is_enabled=False)
        self.assertEqual(len(pipelines), 1)

        pipelines = Pipeline.list(is_enabled=True)
        self.assertGreaterEqual(len(pipelines), 6)

    # 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)

        pipeline = Pipeline.from_name("unittest")
        datalist = [
            {"a": 5, "b": 6},
            {"a": "unit", "b": "test"},
        ]
        kept = [d for d in datalist if pipeline.apply(d) != "discard"]
        self.assertEqual(len(kept), 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)

        pipeline = Pipeline.from_name("unittest")
        datadict = {"a": "test"}
        pipeline.apply(datadict)
        self.assertIn("a", datadict)
        self.assertIn("b", datadict)
        self.assertEqual(datadict["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)

        pipeline = Pipeline.from_name("unittest")
        datadict = {"a": "unit"}
        pipeline.apply(datadict)
        self.assertIn("a", datadict)
        self.assertIn("b", datadict)
        self.assertEqual(datadict["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)

        pipeline = Pipeline.from_name("unittest")
        # a='yes' sets COND true, b='no' resets COND to false => field_set must not run
        datadict = {"a": "yes", "b": "no"}
        pipeline.apply(datadict)
        self.assertNotIn("c", datadict)

    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)

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