"""Compare the dist file created by a migrated package to one created by the original."""
import argparse
import glob
import logging
import os
import shutil
import subprocess
import sys
import tarfile
import zipfile
from typing import Optional


def build_file(dirname, dist_name):
    """Build a dist file in a directory."""
    orig_dir = os.getcwd()
    os.chdir(dirname)
    if os.path.exists("dist"):
        shutil.rmtree("dist")
    subprocess.check_call([sys.executable, "-m", "build", f"--{dist_name}"])
    os.chdir(orig_dir)


def get_tar_names(dirname):
    """Get the tarball names in a directory."""
    dist_file = glob.glob(f"{dirname}/dist/*.tar.gz")[0]
    tarf = tarfile.open(dist_file, "r:gz")
    return set(tarf.getnames())


def get_zip_names(dirname):
    """Get the zip (wheel) file names in a directory."""
    wheel_file = glob.glob(f"{dirname}/dist/*.whl")[0]
    with zipfile.ZipFile(wheel_file, "r") as f:
        return set(f.namelist())


def filter_file(path):
    """Filter a file path for interesting files."""
    if "egg-info" in path:
        return True
    _, ext = os.path.splitext(path)
    if not ext:
        return True
    if os.path.basename(path) in [path, "setup.py", "setup.cfg", "MANIFEST.in"]:
        return True
    return False


def main(source_dir, target_dir, dist_name):
    """The main script."""
    subprocess.check_call([sys.executable, "-m", "pip", "install", "build"])

    logger = logging.getLogger(__name__)
    logging.basicConfig()

    build_file(source_dir, dist_name)
    build_file(target_dir, dist_name)

    if dist_name == "sdist":
        source_names = get_tar_names(source_dir)
        target_names = get_tar_names(target_dir)
    else:
        source_names = get_zip_names(source_dir)
        target_names = get_zip_names(target_dir)

    removed = source_names - target_names
    removed = [r for r in removed if not filter_file(r)]
    if removed:
        logger.info("\nRemoved_files:")
        [logger.info(f) for f in removed]  # type:ignore

    added = target_names - source_names
    added = [a for a in added if not filter_file(a)]
    if added:
        logger.info("\nAdded files:")
        [logger.info(f) for f in added]  # type:ignore

    logger.info("")

    return {"added": added, "removed": removed}


def make_parser(
    parser: Optional[argparse.ArgumentParser] = None, prog: Optional[str] = None
) -> argparse.ArgumentParser:
    """Make an arg parser."""
    if parser is None:
        parser = argparse.ArgumentParser(prog=prog)
    parser.add_argument(dest="source_dir", help="Source Directory")
    parser.add_argument(dest="target_dir", help="Target Directory")
    parser.add_argument(dest="dist_name", help="Dist name")
    return parser


def run(args: Optional[argparse.Namespace] = None) -> None:
    """Run the cli."""
    if args is None:
        parser = make_parser(prog=f"{sys.executable} -m hatch_jupyter_builder.compare_migrated")
        args = parser.parse_args()
    main(args.source_dir, args.target_dir, args.dist_name)
