import argparse
import json
from pathlib import Path
import dateutil.parser


def init_parser() -> argparse.Namespace:
    parser = argparse.ArgumentParser()
    parser.add_argument("json_file", help="JSON file")
    parser.add_argument("section1", help="txt file with section1")
    parser.add_argument("section2", help="txt file with section2")
    return parser.parse_args()


def main(json_file: str, section1: str, section2: str):
    with open(json_file) as jf:
        json_parsed = json.load(jf)
    write_section1(section1, json_parsed)
    write_section2(section2, json_parsed)


def write_section1(section1, json_parsed):
    """ Summary section (1) """
    summary_results = get_summary_stats(json_parsed['results'], json_parsed["info"]["tool_name"])
    summary_results['dataset_types'] = get_dataset_types(json_parsed['results'])
    summary_results['generation_time'] = dateutil.parser.isoparse(
        json_parsed["info"]["check_run_time"]).strftime('%Y-%m-%d')
    cdm_section1_template = Path(__file__).parent.joinpath('cdm_section1_template.txt')
    with open(cdm_section1_template) as f:
        template = f.read()
    filled_template = template.format(**summary_results)
    with open(section1, 'w') as s:
        s.write(filled_template)


def write_section2(section2, json_parsed):
    """ Extended results section (2) """
    cdm_section2_template = Path(__file__).parent.joinpath('cdm_section2_template.txt')
    cdm_results = json_parsed['results']
    with open(cdm_section2_template) as f:
        template = f.read()
    full_section = []
    for i, result in enumerate(cdm_results):
        to_format = dict()
        to_format['num'] = i
        to_format['dataset_name'] = result['input'][0]
        to_format['params'] = json.dumps(result['input'][1], indent=4)
        to_format['has_passed'] = passed_condition(result['output'])
        if 'error' in result['output']:
            to_format['has_passed'] = False
            compliance_output = "The integration test failed to execute. No output produced"
        else:
            compliance_output = format_compliance_output(result['output'])
        to_format['output'] = json.dumps(compliance_output, indent=4)
        full_section.append(template.format(**to_format))
    filled_template = "".join(full_section)
    with open(section2, 'w') as s:
        s.write(filled_template)


def get_summary_stats(cdm_results, tool_name):
    result = dict()
    outputs = list(map(lambda r: r['output'], cdm_results))
    errors = sum('error' in o.keys() for o in outputs)
    warnings = sum('WARN' in o.keys() for o in outputs)
    passed = len(outputs) - errors - warnings
    result['perc_failed'] = 100 * errors // len(outputs)
    result['perc_warn'] = 100 * warnings // len(outputs)
    result['perc_passed'] = 100 * passed // len(outputs)
    result['msg'] = f"The tool " + tool_name + (
        " has " if (result['perc_failed'] == 0) else " hasn't ") + "passed all the CDM compliance checks"
    result['num_tests'] = len(outputs)
    return result


def get_dataset_types(cdm_results):
    extended_dataset_type_names = {"projections": "climate projections",
                                   "seasonal": "seasonal forecasts",
                                   "satellite": "satellite observations"}
    ds_names = map(lambda r: r['input'][0].split("-")[0], cdm_results)
    names = [extended_dataset_type_names[name] for name in ds_names if name in extended_dataset_type_names.keys()]
    unknown = list(filter(lambda n: n not in extended_dataset_type_names.keys(), ds_names))
    names.extend(unknown)
    all_names = list(set(names))
    return ", ".join(all_names)


def format_compliance_output(cdm_result):
    """ format '\n' texts inside strings in json"""
    for k, v in cdm_result.items():
        if isinstance(v, dict):
            format_compliance_output(cdm_result[k])
        elif isinstance(v, str):
            cdm_result[k] = v.split("\n")
        return cdm_result


def passed_condition(cdm_result):
    result = str(cdm_result)
    if 'WARN' in result:
        return "With warnings"
    elif 'ERROR' in result:
        return False
    else:
        return True


if __name__ == "__main__":
    args = init_parser()
    main(args.json_file, args.section1, args.section2)
    # # main("/tmp/fldmean_integration_test.json", "/tmp/section1.txt", "/tmp/section2.txt")
