import os
import warnings
from json import dumps, loads
from pytest import fixture  # , raises
from pathlib import Path
from contextlib import chdir
from rougail import Rougail
from rougail.output_doc import RougailOutputDoc as RougailOutput

from rougail_tests.utils import get_structures_list, get_rougail_config, get_values_for_config


HERE = Path(__file__).parent


excludes = []
excludes = [
    '60_5family_dynamic_unknown_suffix',
    '60_5family_dynamic_variable_outside_sub_suffix',
]

test_ok = get_structures_list(excludes)
# test_ok = [HERE.parent.parent / "rougail-tests" / "structures" / "20_0multi_family_order"]
os.environ['COLUMNS'] = '80'


def idfn(fixture_value):
    return fixture_value.name


@fixture(scope="module", params=test_ok, ids=idfn)
def test_dir(request):
    return request.param


EXT = {'github': 'md', 'asciidoc': 'adoc', 'json': 'json', 'console': 'sh', 'gitlab': 'gitlab.md', "html": "html"}
#EXT = {'json': 'json'}
#EXT = {'console': 'sh'}


def gen_cases(ext_name):
#    if ext_name != "json":
#        yield [False, True, True, False]
#    return
    for without_family in [False, True]:
        for comment in [False, True]:
            for examples in [False, True]:
                if comment and not examples:
                    continue
                if examples and ext_name == "json":
                    continue
                if without_family and examples:
                    continue
                for changelog in [False, True]:
                    if changelog and examples:
                        continue
                    if not without_family and changelog:
                        continue
                    if changelog and ext_name == "json":
                        continue
                    yield without_family, comment, examples, changelog


def _test_structural_files(test_dir, namespace):
    with chdir(HERE):
        rougailconfig = get_rougail_config(test_dir, namespace, relative_to=HERE)
        if not rougailconfig:
            return
        rougailconfig['tiramisu_cache'] = 'p.py'
        ##################################
        rougailconfig['step.output'] = 'doc'
        doc = None
        for ext_name, ext in EXT.items():
            rougailconfig['doc.contents'] = []
            rougailconfig['doc.output_format'] = ext_name
            for without_family, comment, examples, changelog in gen_cases(ext_name):
#                print(f"ext_name: {ext_name}, without_family: {without_family}, comment: {comment}, examples: {examples}, changelog: {changelog}")
                if changelog:
                    rougailconfig["doc.contents"] = ["changelog"]
                    rougailconfig["doc.previous_json_file"] = str(HERE / "empty" / "out.json")
                    # FIXME
                    rougailconfig['doc.without_family'] = True
                elif examples:
                    rougailconfig['doc.contents'] = ['example']
                    if comment:
                        rougailconfig["doc.comment_examples"] = True
                    else:
                        rougailconfig["doc.comment_examples"] = False
                else:
                    rougailconfig['doc.contents'] = ['variables']
                    if ext_name != "json":
                        if without_family:
                            rougailconfig['doc.without_family'] = True
                        else:
                            rougailconfig['doc.without_family'] = False
                if doc is None:
                    with warnings.catch_warnings(record=True) as rougail_wn:
                        warnings.simplefilter("always", UserWarning)
                        rougail = Rougail(rougailconfig)
                        config = rougail.run()
                        doc = RougailOutput(config, rougailconfig=rougailconfig)
                with warnings.catch_warnings(record=True) as wn:
                    warnings.simplefilter("always", UserWarning)
                    generated_output = doc.run()[1]
                warns = [str(w.message) for w in rougail_wn]
                for w in wn:
                    m = str(w.message)
                    if m not in warns:
                        warns.append(m)
                ##################################
                dir_name = 'test'
                if namespace:
                    dir_name += '_namespace'
                elif (test_dir / 'force_namespace').is_file():
                    continue
                ##################################
                if examples:
                    dir_name += '_examples'
                if comment:
                    dir_name += '_comment'
                if without_family:
                    dir_name += '_without_family'
                test_file = test_dir.name
                if changelog:
                    test_file += ".changelog"
                ##################################
                output_file = HERE / 'results' / dir_name / (test_file + "." + ext)
#                print('====', output_file)
                if not output_file.is_file():
                    if not output_file.parent.is_dir():
                        output_file.parent.mkdir()
                    with output_file.open('w') as outfh:
                        outfh.write(generated_output)
                with output_file.open() as outfh:
                     attented_output = outfh.read()
                assert generated_output == attented_output, f'filename {output_file}'
                #
                output_file = HERE / 'results' / dir_name / ("warnings_" + test_dir.name)
                if not output_file.is_file():
                    if not output_file.parent.is_dir():
                        output_file.parent.mkdir()
                    with output_file.open('w') as outfh:
                        outfh.write(dumps(warns))
                with output_file.open() as outfh:
                     attented_output = loads(outfh.read())
                assert warns == attented_output, f'filename {output_file}'


def test_structural_files(test_dir):
    _test_structural_files(test_dir, False)


def test_no_namespace_structural_files(test_dir):
    _test_structural_files(test_dir, True)
