import argparse
import hashlib
import os


def dir_path(path: str) -> str:
    if os.path.isdir(path):
        return path
    raise argparse.ArgumentTypeError(f'readable_dir:{path} is not a valid path')


def sha256sum(filename: str) -> str:
    """Returns a SHA256 hash from a filename"""
    with open(filename, 'rb', buffering=0) as f:
        return hashlib.file_digest(f, 'sha256').hexdigest()


def get_confirm(question: str) -> bool:
    q = input(question)
    return q.lower() == 'y' or q.lower() == 'yes'


def main() -> None:
    parser = argparse.ArgumentParser('hash_rename')
    parser.add_argument('path', type=dir_path)

    args = parser.parse_args()
    assert isinstance(args.path, str)
    files = [f for f in os.listdir(args.path) if os.path.isfile(os.path.join(args.path, f))]
    # Filename: Hash
    rename_dict: dict[str, str] = {}

    confirm = get_confirm(f'{len(files)} files will be renamed. Confirm? (y/n): ')
    if not confirm:
        print('Exiting.')
        exit()

    print('\nCalculating hashes...')
    for f in files:
        rename_dict[f] = sha256sum(os.path.join(args.path, f))
        print(f'{f}:{rename_dict[f]}')
    print()

    confirm = get_confirm('Are you SURE to want to rename all files? (y/n): ')
    if not confirm:
        print('Exiting.')
        exit()

    for f, hash in rename_dict.items():
        ext = '' if f.count('.') == 0 else f.split('.')[-1]
        os.rename(os.path.join(args.path, f), os.path.join(args.path, f'{hash}.{ext}'))


if __name__ == '__main__':
    main()
