#!/usr/bin/env python
# pylint: disable=bare-except

import sys
from glob import glob as _glob
from pathlib import Path
import re
from subprocess import run
import os
import logging

from rich.panel import Panel
from rich.padding import Padding
from rich.console import Console

try:
    from clavier import log as logging
    from clavier.io import OUT
except ImportError:
    import logging
    from rich.console import Console
    OUT = Console(file=sys.stdout)

LOG = logging.getLogger("stats.doctest")

REPO_ROOT = Path(__file__).parents[2]
PKG_ROOT = REPO_ROOT / 'cli'

ARGS = sys.argv[1:]

def glob(path):
    return _glob(str(path), recursive=True)

def rel(path):
    try:
        return f"./{Path(path).relative_to(Path.cwd())}"
    except:
        return str(path)

def is_doctest(path):
    with open(path, 'r') as f:
        for line in f:
            # if re.match(r'\s*\>\>\>', line):
            if re.match(r'\s*doctest(?:ing)?\.testmod\(.*\)', line):
                return True
    return False

def module_for(path):
    return ".".join(
        str(Path(path).relative_to(PKG_ROOT))[:-3].split('/')
    )

def module_roots(pkg_root: Path=PKG_ROOT):
    for path_s in glob(pkg_root / "*" / "__init__.py"):
        path = Path(path_s).parents[0]
        yield path

def pkg_modules(pkg_root: Path=PKG_ROOT):
    for module_root in module_roots(pkg_root):
        for path_s in glob(module_root / "**" / "*.py"):
            path = Path(path_s)
            if is_doctest(path):
                yield (module_for(path), path)

def env():
    return {**os.environ, "DOCTESTING": "yup"}

def test(name, cmd):
    r = run(cmd, capture_output=True, encoding='utf8', env=env(), check=False)
    if r.returncode == 0 and len(r.stdout) == 0:
        OUT.print(":white_check_mark:", name)
        return True
    else:
        if r.stdout:
            OUT.print(Panel(Padding(r.stdout, 1), title=f"STDOUT {name}"))
        if r.stderr:
            OUT.print(Panel(Padding(r.stderr, 1), title=f"STDERR {name}"))
        OUT.print(":x:", name)
        return False

def test_module(module):
    return test(module, ['python', '-m', module])

def test_file(path):
    return test(rel(path), ['python', '-m', 'doctest', path])

def is_pkg_module(path):
    try:
        Path(path).relative_to(PKG_ROOT / 'stats')
    except:
        return False
    return True


def main():
    if hasattr(logging, "setup"):
        logging.setup("stats.doctest", level=logging.DEBUG)
    else:
        logging.basicConfig(level=logging.DEBUG)

    ok = True

    if len(ARGS) == 0:
        for module, path in pkg_modules():
            ok = ok and test_module(module)
    else:
        for arg in ARGS:
            if is_pkg_module(arg):
                ok = ok and test_module(module_for(arg))
            else:
                ok = ok and test_file(arg)

    if not ok:
        sys.exit(1)

if __name__ == '__main__':
    main()
