"""Generate junit test reports"""
import random
import xml.etree.ElementTree as ET
from io import BytesIO
from typing import List
from pathlib import Path
from argparse import ArgumentParser
from junit2htmlreport.parser import Suite, Class, Case
from junit2htmlreport.textutils import unicode_str

parser = ArgumentParser(description=__doc__)
parser.add_argument("NAME", type=Path,
                    help="Filename to write junit xml to")
parser.add_argument("--suites", type=int, default=5,
                    help="number of test suites")
parser.add_argument("--size", type=int, default=50,
                    help="number of tests in each suite")

NAMES = [
    "apple",
    "orange",
    "toast",
    "cat",
    "bat",
    "potato",
    "nemesis",
    "vulcan",
    "hytac",
    "duessa",
    "odracir",
    "baccus",
    "terminus",
    "sodor",
    "tokamak",
    "charissa",
    "genetix",
    "socrates",
    "magma",
    "igneous",
    "elwood",
    "avernus",
    "acheron",
    "beacon",
    "storm",
    "isolus",
    "vattland",
    "granite",
    "manta",
    "walrus",
    "albatross",
    "seal",
    "bear",
    "petrel",
    "razorbill",
    "mule",
    "swordfish",
    "needlefish",
    "butterfly",
    "corgette",
    "teapot",
    "moose",
    "acetone",
    "yorkshire tea",
    "smartcard",
    "bobble",
    "grno",
    "null",
    "panther",
    "courier",
    "alamo",
    "martham",
    "winterton",
]

class NameGenerator:
    def __init__(self):
        self.used_suites = set()

    def get_namespace_name(self) -> str:
        words = random.randrange(1, 6)
        parts = [random.choice(NAMES) for _ in range(words)]
        name = ".".join(parts)
        return name

    def get_suite_name(self) -> str:
        while True:
            name = self.get_namespace_name()
            if name not in self.used_suites:
                self.used_suites.add(name)
                return name

    def get_test_name(self) -> str:
        return f"test_{random.choice(NAMES)}_{random.randint(1, 4)}"



NAMER = NameGenerator()


def generate_random_suites(n_suites: int, suite_tests: int) -> List[Suite]:
    suites = []

    for i in range(n_suites):
        s = Suite()
        s.name = NAMER.get_suite_name()
        while len(s.all()) < suite_tests:
            classname = NAMER.get_namespace_name()
            testclass = Class()
            testclass.name = classname
            s.classes[classname] = testclass
            newtests = random.randrange(1,6)
            for n in range(newtests):
                case = Case()
                case.name = NAMER.get_test_name()
                case.testclass = testclass
                testclass.cases.append(case)
                duration = random.randrange(1, 300)
                if duration > 200:
                    duration *= random.randrange(10, 140)
                case.duration = duration

                if random.randint(1, 5) % 2 == 0:
                    case.failure = f"Failed {random.choice(NAMES)}"
                elif random.randint(0, 14) % 2 == 0:
                    case.skipped = "Skipped"
                    case.skipped_msg = f"Skipped because {NAMER.get_namespace_name()}"

        suites.append(s)

    return suites


def main():
    args = parser.parse_args()
    suites = generate_random_suites(args.suites, args.size)
    duration = 0
    for suite in suites:
        for testcase in suite.all():
            duration += testcase.duration

    suite_list = ET.Element("testsuites")
    suite_list.set(u"duration", unicode_str(str(duration)))
    for suite in suites:
        suite_list.append(suite.tojunit())

    tree = ET.ElementTree(suite_list)
    ET.indent(tree, space=" ", level=0)
    buf = BytesIO()
    tree.write(buf)
    with args.NAME.open("wb") as out:
        out.write(b'<?xml version="1.0" encoding="utf-8"?>')
        out.write(b"\n")
        out.write(buf.getvalue())



if __name__ == "__main__":
    main()