"""
Main.
TODO list:
    main
        option to reset DB
    check/upgrade:
        remove plus suffixes in get_installed
    download:
        add option to keep existing files in wheelhouse
"""
__version__ = "1.1.3"
__dev_mode__ = False


import subprocess, argparse
try:
    from pip_dater.download import download
    from pip_dater.check import get_installed, check, check_outdated, probably_good_db
except:
    from download import download
    from check import get_installed, check, check_outdated, probably_good_db


def main(dev_stdout='', cmdline='', skip_download=False):
    parser = argparse.ArgumentParser(prog="pip-dater",
        description="A maintenance tool for the python packages.",
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("cmd", choices=["check", "upgrade", "download"],
                         help="check: perform integrity check on installed packages.\n"
                                "upgrade: upgrade the packages.\n"
                                "download: download the wheels for offline installation.")
    parser.add_argument("-v", "--version", action="version", version=__version__)
    parser.add_argument("-e", "--exclude", nargs="+", help="[upgrade] Exclude packages you don't want to upgrade")
    parser.add_argument("-y", "--yes", action="store_true", help="Automatically execute (no user prompt))")
    parser.add_argument("-n", "--no", action="store_true", help="Don't execute (no user prompt))")
    parser.add_argument("--archive", action="store_true", help="[download] Compress the wheelhouse")
    parser.add_argument("-i", "--include-dir", nargs=1, help="[download] Add all the files from the specified folder.")
    if cmdline:
        args = parser.parse_args(cmdline.split())
    else:
        args = parser.parse_args()

    # Common step: get installed packages/requirements
    req_installed = get_installed()
    print(f"Installed packages: {len(req_installed.splitlines())}")

    if args.cmd == 'check':
        print("Performing integrity test on installed packages")
        err, out = check(req_installed)
        if err:
            print('   Check failed! Log:\n', out)
        else:
            print('   Check passed.')
        return
    elif args.cmd == 'download':
        download(yes=args.yes, archive=args.archive, skip_download=skip_download,
                 include=args.include_dir[0] if args.include_dir else None)
        return
    elif args.cmd not in ('upgrade'):
        raise Exception('Unknown command!')


    ### CMD = UPGRADE (from here to end)
    print("Getting outdated packages")
    if dev_stdout:
        text = dev_stdout
    else:
        text = subprocess.run(['pip', 'list', '--outdated'],
                              capture_output=True, text=True).stdout
    outdated = [l.split()[:3] for l in text.splitlines()[2:]]  # skip header
    print(f"   Found {len(outdated)} outdated packages")
    print(f"   {[x[0] for x in outdated]}")
    excluded = args.exclude or []  # replace None
    print('Excluded from upgrade:', excluded)
    candidate = [x for x in outdated if x[0] not in excluded]
    print("Finding 'probably good' upgrades.")
    probably_good = probably_good_db(candidate, req_installed, verbose=True)
    print("Testing upgradable packages")
    good_candidate = check_outdated(req_installed, candidate, probably_good=probably_good)
    print(f"Upgradable packages: {len(good_candidate)}")
    if not good_candidate:
        print('Nothing to upgrade. DONE.')
        return

    print('To be upgraded:', good_candidate)
    if args.no:
        ans = 'n'
        print('   Upgrade skipped (--no flag in command line)')
    elif args.yes:
        ans = 'y'
        print('   Upgrade forced (--yes flag in command line)')
    else:
        ans = input('  Proceed with upgrade? (y/n) ')
    if ans.lower() in ('y', 'yes'):
        subprocess.run(['python', '-m', 'pip', 'install', '--upgrade'] + good_candidate)


############
if __name__ == "__main__":
    if not __dev_mode__:
        main()
    else:
        # DEVELOPMENT (remember to set __dev_mode__)
        # main(cmdline='-h')
        # main(cmdline='download -y --archive --include-dir test_include', skip_download=True)
        # main(cmdline='check')
        main(cmdline='upgrade -n -e pyinstaller selenium',
             dev_stdout="""Package     Version Latest Type
            ----------- ------- ------ -----
            astroid     4.0.3   4.1.1  wheel
            autopep8    2.0.4   2.3.2  wheel
            flake8      7.1.2   7.3.0  wheel
            ipykernel   6.31.0  7.2.0  wheel
            pycodestyle 2.12.1  2.14.0 wheel
            pyflakes    3.2.0   3.4.0  wheel
            tinycss2    1.4.0   1.5.1  wheel""")
