"""Check a project and backend by attempting to build using PEP 517 hooks.
"""
import argparse
import logging
import os
import shutil
import sys
import tarfile
import zipfile
from os.path import isfile
from os.path import join as pjoin
from subprocess import CalledProcessError
from tempfile import mkdtemp

from ._compat import tomllib
from .colorlog import enable_colourful_output
from .envbuild import BuildEnvironment
from .wrappers import Pep517HookCaller

log = logging.getLogger(__name__)


def check_build_sdist(hooks, build_sys_requires):
    with BuildEnvironment() as env:
        try:
            env.pip_install(build_sys_requires)
            log.info('Installed static build dependencies')
        except CalledProcessError:
            log.error('Failed to install static build dependencies')
            return False

        try:
            reqs = hooks.get_requires_for_build_sdist({})
            log.info('Got build requires: %s', reqs)
        except Exception:
            log.error('Failure in get_requires_for_build_sdist', exc_info=True)
            return False

        try:
            env.pip_install(reqs)
            log.info('Installed dynamic build dependencies')
        except CalledProcessError:
            log.error('Failed to install dynamic build dependencies')
            return False

        td = mkdtemp()
        log.info('Trying to build sdist in %s', td)
        try:
            try:
                filename = hooks.build_sdist(td, {})
                log.info('build_sdist returned %r', filename)
            except Exception:
                log.info('Failure in build_sdist', exc_info=True)
                return False

            if not filename.endswith('.tar.gz'):
                log.error(
                    "Filename %s doesn't have .tar.gz extension", filename)
                return False

            path = pjoin(td, filename)
            if isfile(path):
                log.info("Output file %s exists", path)
            else:
                log.error("Output file %s does not exist", path)
                return False

            if tarfile.is_tarfile(path):
                log.info("Output file is a tar file")
            else:
                log.error("Output file is not a tar file")
                return False

        finally:
            shutil.rmtree(td)

        return True


def check_build_wheel(hooks, build_sys_requires):
    with BuildEnvironment() as env:
        try:
            env.pip_install(build_sys_requires)
            log.info('Installed static build dependencies')
        except CalledProcessError:
            log.error('Failed to install static build dependencies')
            return False

        try:
            reqs = hooks.get_requires_for_build_wheel({})
            log.info('Got build requires: %s', reqs)
        except Exception:
            log.error('Failure in get_requires_for_build_sdist', exc_info=True)
            return False

        try:
            env.pip_install(reqs)
            log.info('Installed dynamic build dependencies')
        except CalledProcessError:
            log.error('Failed to install dynamic build dependencies')
            return False

        td = mkdtemp()
        log.info('Trying to build wheel in %s', td)
        try:
            try:
                filename = hooks.build_wheel(td, {})
                log.info('build_wheel returned %r', filename)
            except Exception:
                log.info('Failure in build_wheel', exc_info=True)
                return False

            if not filename.endswith('.whl'):
                log.error("Filename %s doesn't have .whl extension", filename)
                return False

            path = pjoin(td, filename)
            if isfile(path):
                log.info("Output file %s exists", path)
            else:
                log.error("Output file %s does not exist", path)
                return False

            if zipfile.is_zipfile(path):
                log.info("Output file is a zip file")
            else:
                log.error("Output file is not a zip file")
                return False

        finally:
            shutil.rmtree(td)

        return True


def check(source_dir):
    pyproject = pjoin(source_dir, 'pyproject.toml')
    if isfile(pyproject):
        log.info('Found pyproject.toml')
    else:
        log.error('Missing pyproject.toml')
        return False

    try:
        with open(pyproject, 'rb') as f:
            pyproject_data = tomllib.load(f)
        # Ensure the mandatory data can be loaded
        buildsys = pyproject_data['build-system']
        requires = buildsys['requires']
        backend = buildsys['build-backend']
        backend_path = buildsys.get('backend-path')
        log.info('Loaded pyproject.toml')
    except (tomllib.TOMLDecodeError, KeyError):
        log.error("Invalid pyproject.toml", exc_info=True)
        return False

    hooks = Pep517HookCaller(source_dir, backend, backend_path)

    sdist_ok = check_build_sdist(hooks, requires)
    wheel_ok = check_build_wheel(hooks, requires)

    if not sdist_ok:
        log.warning('Sdist checks failed; scroll up to see')
    if not wheel_ok:
        log.warning('Wheel checks failed')

    return sdist_ok


def main(argv=None):
    log.warning('pep517.check is deprecated. '
                'Consider switching to https://pypi.org/project/build/')

    ap = argparse.ArgumentParser()
    ap.add_argument(
        'source_dir',
        help="A directory containing pyproject.toml")
    args = ap.parse_args(argv)

    enable_colourful_output()

    ok = check(args.source_dir)

    if ok:
        print(ansi('Checks passed', 'green'))
    else:
        print(ansi('Checks failed', 'red'))
        sys.exit(1)


ansi_codes = {
    'reset': '\x1b[0m',
    'bold': '\x1b[1m',
    'red': '\x1b[31m',
    'green': '\x1b[32m',
}


def ansi(s, attr):
    if os.name != 'nt' and sys.stdout.isatty():
        return ansi_codes[attr] + str(s) + ansi_codes['reset']
    else:
        return str(s)


if __name__ == '__main__':
    main()
