import os
import mock
import unittest

from dbt.node_types import NodeType
from dbt.parser import docs
from dbt.contracts.graph.unparsed import UnparsedDocumentationFile

from .utils import config_from_parts_or_dicts


SNOWPLOW_SESSIONS_DOCS = r'''
This table contains one record for every session recorded by Snowplow.
A session is itself comprised of pageviews that all occur within 30 minutes
of each other. If more than 30 minutes elapse between pageviews, then a
new session is created. Given the following pageviews:

| session_id | page_view_id | page_title |
| ---------- | ------------ | ---------- |
| abc        | 123          | Home       |
| abc        | 456          | About      |
| abc        | 789          | Home       |

The following sessions will be created:

| session_id | first_page_title | count_pageviews |
| ---------- | ---------------- | --------------- |
| abc        | 123              | 2               |
| abc        | 789              | 1               |
'''

SNOWPLOW_SESSIONS_SESSION_ID_DOCS = r'''
This column is the unique identifier for a Snowplow session. It is generated by
a cookie then expires after 30 minutes of inactivity.
'''


TEST_DOCUMENTATION_FILE = r'''
{{% docs snowplow_sessions %}}
{snowplow_sessions_docs}
{{% enddocs %}}

{{% docs snowplow_sessions__session_id %}}
{snowplow_sessions_session_id_docs}
{{% enddocs %}}
'''.format(
    snowplow_sessions_docs=SNOWPLOW_SESSIONS_DOCS,
    snowplow_sessions_session_id_docs=SNOWPLOW_SESSIONS_SESSION_ID_DOCS
)


class DocumentationParserTest(unittest.TestCase):
    def setUp(self):
        if os.name == 'nt':
            self.root_path = 'C:\\test_root'
            self.subdir_path = 'C:\\test_root\\test_subdir'
            self.testfile_path = 'C:\\test_root\\test_subdir\\test_file.md'
        else:
            self.root_path = '/test_root'
            self.subdir_path = '/test_root/test_subdir'
            self.testfile_path = '/test_root/test_subdir/test_file.md'

        profile_data = {
            'outputs': {
                'test': {
                    'type': 'postgres',
                    'host': 'localhost',
                    'schema': 'analytics',
                    'user': 'test',
                    'pass': 'test',
                    'dbname': 'test',
                    'port': 1,
                }
            },
            'target': 'test',
        }
        root_project = {
            'name': 'root',
            'version': '0.1',
            'profile': 'test',
            'project-root': self.root_path,
        }

        subdir_project = {
            'name': 'some_package',
            'version': '0.1',
            'profile': 'test',
            'project-root': self.subdir_path,
            'quoting': {},
        }
        self.root_project_config = config_from_parts_or_dicts(
            project=root_project, profile=profile_data
        )
        self.subdir_project_config = config_from_parts_or_dicts(
            project=subdir_project, profile=profile_data
        )

    @mock.patch('dbt.parser.docs.system')
    def test_load_file(self, system):
        system.load_file_contents.return_value = TEST_DOCUMENTATION_FILE
        system.find_matching.return_value = [{
            'relative_path': 'test_file.md',
            'absolute_path': self.testfile_path,
            'searched_path': self.subdir_path,
        }]
        results = list(docs.DocumentationParser.load_file(
            'some_package', self.root_path, ['test_subdir'])
        )
        self.assertEqual(len(results), 1)
        result = results[0]
        self.assertEqual(result.package_name, 'some_package')
        self.assertEqual(result.file_contents, TEST_DOCUMENTATION_FILE)
        self.assertEqual(result.original_file_path,
                         self.testfile_path)
        self.assertEqual(result.root_path, self.root_path)
        self.assertEqual(result.resource_type, NodeType.Documentation)
        self.assertEqual(result.path, 'test_file.md')

    def test_parse(self):
        docfile = UnparsedDocumentationFile(
            root_path=self.root_path,
            resource_type=NodeType.Documentation,
            path='test_file.md',
            original_file_path=self.testfile_path,
            package_name='some_package',
            file_contents=TEST_DOCUMENTATION_FILE
        )
        all_projects = {
            'root': self.root_project_config,
            'some_package': self.subdir_project_config
        }
        parser = docs.DocumentationParser(self.root_project_config, all_projects)
        parsed = list(parser.parse(docfile))
        parsed.sort(key=lambda x: x.name)

        self.assertEqual(len(parsed), 2)
        table = parsed[0]
        column = parsed[1]
        self.assertEqual(table.name, 'snowplow_sessions')
        self.assertEqual(table.unique_id,
                         'some_package.snowplow_sessions')
        self.assertEqual(table.block_contents, SNOWPLOW_SESSIONS_DOCS.strip())

        self.assertEqual(column.name, 'snowplow_sessions__session_id')
        self.assertEqual(column.unique_id,
                         'some_package.snowplow_sessions__session_id')
        self.assertEqual(
            column.block_contents,
            SNOWPLOW_SESSIONS_SESSION_ID_DOCS.strip()
        )

