import os
import shlex
from pathlib import Path

import nox


def run_hook(name, *args, **kwargs):
    for file in [Path(__name__).parent / '.nox-hooks.py', Path('~/.config/nox/eo-hooks.py').expanduser()]:
        if not file.exists():
            continue

        globals_ = {}
        exec(file.read_text(), globals_)
        hook = globals_.get(name, None)
        if hook:
            hook(*args, **kwargs)


def setup_venv(session, *packages):
    packages = [
        'coverage',
        'pytest',
        'pytest-cov',
        'pytest-freezer',
        'mock<4',
        'httmock',
        'lxml',
        'responses',
        *packages,
    ]
    run_hook('setup_venv', session, packages)
    session.install('-e', '.', *packages, silent=False)


def hookable_run(session, *args, **kwargs):
    args = list(args)
    run_hook('run', session, args, kwargs)
    session.run(*args, **kwargs)


@nox.session()
def tests(session):
    setup_venv(session)

    args = ['py.test']
    if '--coverage' in session.posargs or not session.interactive:
        session.notify('coverage_report', ['--coverage'])
        while '--coverage' in session.posargs:
            session.posargs.remove('--coverage')
        args += [
            '--junitxml=junit-coverage.xml',
            '--cov=eopayment/',
            '--cov-report=term-missing',
            '--cov-context=test',
        ]

    if not session.interactive:
        args += ['-v']

    if not session.posargs:
        args += ['tests/']
    else:
        args += session.posargs

    hookable_run(
        session,
        *args,
    )


@nox.session
def coverage_report(session):
    if session.interactive and '--coverage' not in session.posargs:
        return

    session.install('coverage', 'diff-cover')
    session.run('python3', '-m', 'coverage', 'html', '-d', 'htmlcov', '--show-contexts')
    session.run('python3', '-m', 'coverage', 'xml')

    if not os.path.isdir('diff-cover'):
        os.mkdir('diff-cover')

    diff_cover_cmd = shlex.join(
        [
            'diff-cover',
            'coverage.xml',
            '--format',
            'html:diff-cover/diff-cover.html',
            '--external-css-file',
            'diff-cover/diff-cover.css',
            '--fail-under',
            '100',
        ],
    )
    diff_cover_status_json = 'diff_cover_status.json'

    session.run(
        '/bin/sh',
        '-c',
        '{ %s && echo -n 0 >&3 || { echo -n 1 >&3; false; }; } 3> %s'
        % (diff_cover_cmd, diff_cover_status_json),
        external=True,
    )


@nox.session
def codestyle(session):
    session.install('pre-commit')
    session.run('pre-commit', 'run', '--all-files', '--show-diff-on-failure')


@nox.session
def check_manifest(session):
    # django is only required to compile messages
    session.install('django', 'check-manifest')
    # compile messages and css
    ignores = [
        'VERSION',
    ]
    session.run('check-manifest', '--ignore', ','.join(ignores))
