from dbt.contracts.graph.manifest import Manifest
import os
from test.integration.base import DBTIntegrationTest, use_profile


def get_manifest():
    path = './target/partial_parse.msgpack'
    if os.path.exists(path):
        with open(path, 'rb') as fp:
            manifest_mp = fp.read()
        manifest: Manifest = Manifest.from_msgpack(manifest_mp)
        return manifest
    else:
        return None


class TestBasicExperimentalParser(DBTIntegrationTest):
    @property
    def schema(self):
        return "072_basic"

    @property
    def models(self):
        return "basic"

    @use_profile('postgres')
    def test_postgres_env_use_experimental_parser(self):
        def cleanup():
            del os.environ['DBT_USE_EXPERIMENTAL_PARSER']
            
        self.addCleanup(cleanup)
        os.environ['DBT_USE_EXPERIMENTAL_PARSER'] = 'true'
        _, log_output = self.run_dbt_and_capture(['--debug', 'parse'])

        # successful stable static parsing
        self.assertFalse("1699: " in log_output)
        # successful experimental static parsing
        self.assertTrue("1698: " in log_output)
        # experimental parser failed
        self.assertFalse("1604: " in log_output)
        # static parser failed
        self.assertFalse("1603: " in log_output)
        # jinja rendering
        self.assertFalse("1602: " in log_output)

    @use_profile('postgres')
    def test_postgres_env_static_parser(self):
        def cleanup():
            del os.environ['DBT_STATIC_PARSER']
            
        self.addCleanup(cleanup)
        os.environ['DBT_STATIC_PARSER'] = 'false'
        _, log_output = self.run_dbt_and_capture(['--debug', 'parse'])

        print(log_output)

        # jinja rendering because of --no-static-parser
        self.assertTrue("1605: " in log_output)
        # successful stable static parsing
        self.assertFalse("1699: " in log_output)
        # successful experimental static parsing
        self.assertFalse("1698: " in log_output)
        # experimental parser failed
        self.assertFalse("1604: " in log_output)
        # static parser failed
        self.assertFalse("1603: " in log_output)
        # fallback jinja rendering
        self.assertFalse("1602: " in log_output)

    # test that the experimental parser extracts some basic ref, source, and config calls.
    @use_profile('postgres')
    def test_postgres_experimental_parser_basic(self):
        results = self.run_dbt(['--use-experimental-parser', 'parse'])
        manifest = get_manifest()
        node = manifest.nodes['model.test.model_a']
        self.assertEqual(node.refs, [['model_a']])
        self.assertEqual(node.sources, [['my_src', 'my_tbl']])
        self.assertEqual(node.config._extra, {'x': True})
        self.assertEqual(node.config.tags, ['hello', 'world'])

    # test that the static parser extracts some basic ref, source, and config calls by default
    # without the experimental flag and without rendering jinja
    @use_profile('postgres')
    def test_postgres_static_parser_basic(self):
        _, log_output = self.run_dbt_and_capture(['--debug', 'parse'])

        # successful stable static parsing
        self.assertTrue("1699: " in log_output)
        # successful experimental static parsing
        self.assertFalse("1698: " in log_output)
        # experimental parser failed
        self.assertFalse("1604: " in log_output)
        # static parser failed
        self.assertFalse("1603: " in log_output)
        # jinja rendering
        self.assertFalse("1602: " in log_output)

        manifest = get_manifest()
        node = manifest.nodes['model.test.model_a']
        self.assertEqual(node.refs, [['model_a']])
        self.assertEqual(node.sources, [['my_src', 'my_tbl']])
        self.assertEqual(node.config._extra, {'x': True})
        self.assertEqual(node.config.tags, ['hello', 'world'])

    # test that the static parser doesn't run when the flag is set
    @use_profile('postgres')
    def test_postgres_static_parser_is_disabled(self):
        _, log_output = self.run_dbt_and_capture(['--debug', '--no-static-parser', 'parse'])