import re
from collections import defaultdict

from dev_tools.utility.path import ROOT

PKG_AUTHORS = {
    "aiofiles": "Tin Tvrtkovic",
    "aiohttp": "aiohttp team",
    "aiosignal": "aiohttp team",
    "altgraph": "Ronald Oussoren et al.",
    "argon2-cffi": "Hynek Schlawack",
    "argon2-cffi-bindings": "Hynek Schlawack",
    "async-timeout": "Andrew Svetlov",
    "attrdict3": "Brendan Curran-Johnson",
    "attrs": "Hynek Schlawack et al.",
    "babel": "Babel Team",
    "cachecontrol": "Eric Larson",
    "certifi": "Kenneth Reitz",
    "cffi": "Armin Rigo, Maciej Fijalkowski",
    "charset-normalizer": "Ahmed TAHRI",
    "colorama": "Jonathan Hartley",
    "commonmark": "Bibek Kafle and Roland Shoemaker",
    "concurrent-log-handler": "Preston Landers",
    "contextlib2": "Nick Coghlan",
    "coverage": "Ned Batchelder et al.",
    "cyclonedx-python-lib": "Paul Horton",
    "cx-freeze": "Marcelo Duarte",
    "cx-logging": "Anthony Tuininga",
    "dbus-python": "The D-Bus maintainers",
    "exceptiongroup": "Alex Grönholm",
    "frozenlist": "aiohttp team",
    "gcld3": "Rami Al-Rfou",
    "html5lib": "James Graham",
    "idna": "Kim Davies",
    "importlib-metadata": "Jason R. Coombs",
    "iniconfig": "Ronny Pfannschmidt, Holger Krekel",
    "lockfile": "OpenStack",
    "lxml": "lxml dev team",
    "macholib": "Ronald Oussoren",
    "packageurl-python": "the purl authors",
    "msgpack": "Inada Naoki",
    "pip-api": "Dustin Ingram",
    "pip-audit": "Alex Cameron, Dustin Ingram, William Woodruff",
    "pip-requirements-parser": "The pip authors, nexB. Inc. et al.",
    "multidict": "Andrew Svetlov",
    "pygments": "Georg Brandl",
    "pyparsing": "Paul McGuire",
    "resolvelib": "Tzu-ping Chung",
    "rich": "Will McGugan",
    "toml": "William Pearson",
    "webencodings": "Geoffrey Sneddon",
    "numpy": "Travis E. Oliphant et al.",
    "orjson": "ijl",
    "packaging": "Donald Stufft",
    "passlib": "Eli Collins",
    "pillow": "Alex Clark",
    "pluggy": "Holger Krekel",
    "portalocker": "Rick van Hattem",
    "pytest": "Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, "
    "Brianna Laugher, Florian Bruhin et al.",
    "pytest-asyncio": "Tin Tvrtković",
    "pytest-cov": "Marc Schlaich",
    "psutil": "Giampaolo Rodola",
    "pybase64": "Matthieu Darbois",
    "pycparser": "Eli Bendersky",
    "pycryptodome": "Helder Eijs",
    "pynacl": "The PyNaCl developers",
    "pyobjc-core": "Ronald Oussoren, bbum, SteveM, LeleG et al.",
    "python-mimeparse": "DB Tsai",
    "pytz": "Stuart Bishop",
    "pywin32": "Mark Hammond et al.",
    "pyzmq": "Brian E. Granger, Min Ragan-Kelley",
    "requests": "Kenneth Reitz",
    "ruamel-yaml": "Anthon van der Neut",
    "ruamel-yaml-clib": "Anthon van der Neut",
    "safe-radix32": "Nándor Mátravölgyi",
    "schema": "Vladimir Keleshev",
    "six": "Benjamin Peterson",
    "sortedcontainers": "Grant Jenks",
    "tomli": "Taneli Hukkinen",
    "tornado": "Facebook et al.",
    "ttldict2": "Nándor Mátravölgyi",
    "urllib3": "Andrey Petrov",
    "uvloop": "Yury Selivanov",
    "wait-for2": "Nándor Mátravölgyi",
    "watchdog": "Yesudeep Mangalapilly",
    "wheel": "Daniel Holth",
    "wxpython": "Robin Dunn",
    "xmldiff": "Lennart Regebro",
    "yarl": "Andrew Svetlov",
    "zipp": "Jason R. Coombs",
    "zxcvbn": "Daniel Wolf",
}

PLATFORM_ALIAS = {"windows": "win", "darwin": "mac"}

FIRST_PARTY = {"clarabot-crypto", "clarabot-testing"}


def get_frozen_python_dependencies():
    d = defaultdict(dict)
    py_req_name_re = re.compile(r"^(base|pkg|test)\.(\w+)\.txt$")
    py_req_expr_re = re.compile(r"^([\w\[\],-]+)==([\d\w.-]+)$")
    platforms = set()
    for item in (ROOT / "requirements").iterdir():
        m = py_req_name_re.match(item.name)
        if not m:
            continue
        # env = m.group(1)
        platform = m.group(2)
        platforms.add(platform)
        reqs_lines = [line.partition("#")[0].partition(";")[0].strip() for line in item.read_text().splitlines()]
        reqs_lines = [line for line in reqs_lines if line]
        for reqs_line in reqs_lines:
            if reqs_line.startswith("-r "):
                continue
            m = py_req_expr_re.match(reqs_line)
            if not m:
                raise Exception(f"REQ expr: {reqs_line}")
            pkg_name = m.group(1).partition("[")[0]
            if pkg_name in FIRST_PARTY:
                continue
            pkg_d = d[pkg_name]
            if platform in pkg_d and pkg_d[platform] != m.group(2):
                raise Exception(f"REQ {pkg_name} for {platform} version conflicts")
            pkg_d[platform] = m.group(2)
    missing_authors_for = set(d.keys()).difference(PKG_AUTHORS.keys())
    if missing_authors_for:
        print("Missing authors for")
        for x in sorted(missing_authors_for):
            print(x)
        raise Exception("Missing authors")
    lines = []
    for name in sorted(d.keys()):
        pv = d[name]
        ps = set(pv.keys())
        vs = set(pv.values())
        vcell = []
        if ps == platforms and len(vs) == 1:
            vcell.append(next(iter(vs)))
        else:
            for p in sorted(ps):
                vcell.append(f"{PLATFORM_ALIAS.get(p, p)} {pv[p]}")
        lines.append((name, ", ".join(vcell), PKG_AUTHORS[name]))
    return lines


def get_frozen_python_dependencies_tablines():
    return "\n".join(["\t".join(line) for line in get_frozen_python_dependencies()])
