import shlex
from pathlib import Path

import nox

nox.options.reuse_venv = 'yes'


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_)  # pylint: disable=exec-used
        hook = globals_.get(name, None)
        if hook:
            hook(*args, **kwargs)


def setup_venv(session, *packages, django_version='>=4.2,<4.3'):
    packages = [
        f'django{django_version}',
        'psycopg2-binary',
        'django-mellon',
        'WebTest',
        'django-webtest',
        'httmock',
        'pytest',
        'responses',
        'python-redmine',
        *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()
@nox.parametrize('django', ['>=4.2,<4.3', '>=5.2,<5.3'])
def tests(session, django):
    setup_venv(
        session,
        'pytest-cov',
        'pytest-django<4.13' if '4.2' in django else 'pytest-django',
        'psycopg2-binary',
        'pyquery',
        'GitPython',
        django_version=django,
    )

    args = ['py.test']
    if '--coverage' in session.posargs or not session.interactive:
        while '--coverage' in session.posargs:
            session.posargs.remove('--coverage')
        args += [
            '--cov-report',
            'xml',
            '--cov-report',
            'html',
            '--cov-context',
            'test',
            '--cov=scrutiny/',
            '--cov-config',
            '.coveragerc',
            '-v',
            f'--junitxml=junit-coverage.django-{django}.xml',
        ]

    args += session.posargs + ['tests/']

    hookable_run(
        session,
        *args,
        env={
            'DJANGO_SETTINGS_MODULE': 'scrutiny.settings',
            'SCRUTINY_SETTINGS_FILE': 'tests/settings.py',
            'DB_ENGINE': 'django.db.backends.postgresql_psycopg2',
        },
    )


@nox.session(tags=['jenkins'])
def pylint(session):
    setup_venv(session, 'pylint<3', 'astroid<3', 'pylint-django', 'nox')

    pylint_command = [
        'pylint',
        '-f',
        'parseable',
        '--load-plugins',
        'pylint_django',
        '--django-settings-module',
        'scrutiny.settings',
        '--rcfile',
        str(Path(__name__).parent / 'pylint.rc'),
    ]

    if not session.posargs:
        pylint_command += ['scrutiny', 'noxfile.py']
    else:
        pylint_command += session.posargs

    if not session.interactive:
        session.run(
            'bash',
            '-c',
            f'{shlex.join(pylint_command)} | tee pylint.out ; test $PIPESTATUS -eq 0',
            external=True,
        )
    else:
        session.run(*pylint_command)


@nox.session(tags=['jenkins'])
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',
        'scrutiny/static/css/style.css',
    ]
    session.run('check-manifest', '--ignore', ','.join(ignores))
