"""Starter: survey a practice folder and plan the filing.

Practical Workflow Automation, modules 1 and 2, on real files.

This is the safe shape the course teaches: it surveys, it plans every change
before making any of them, it refuses the whole plan if two files want the
same name, and it does nothing at all unless you pass --apply.

    py starter_organise_inbox.py --folder inbox            dry run (default)
    py starter_organise_inbox.py --folder inbox --apply    do it

Fill in the three functions marked "your code here". The completed version is
in complete_organise_inbox.py; read it after you have attempted this, not
before.

It never deletes anything. Files it sets aside are moved, not removed.
"""

import argparse
import hashlib
import os
import pathlib
import sys


def content_hash(path):
    """SHA-256 of a file's bytes, read in chunks so size does not matter."""
    digest = hashlib.sha256()
    with path.open("rb") as handle:
        for chunk in iter(lambda: handle.read(65536), b""):
            digest.update(chunk)
    return digest.hexdigest()


def filed_name(path):
    """The filed name: lowercase, spaces to hyphens, suffix lowercased."""
    return path.stem.lower().replace(" ", "-") + path.suffix.lower()


def survey(folder):
    """Return (files, folders) for one folder, sorted, files only at this level.

    Ask the filesystem what each entry is rather than inferring it from the
    name. Do not descend into subfolders. Sort, so two runs over the same
    folder produce the same answer.
    """
    # your code here
    raise NotImplementedError


def plan_renames(files):
    """Return (moves, collisions) without touching anything.

    moves is a sorted list of (source_name, target_name).
    collisions is a sorted list of target names wanted by more than one source.
    """
    # your code here
    raise NotImplementedError


def plan_duplicates(folder, files):
    """Return (keep, duplicates) by comparing contents, not names.

    Group the files by content hash, keep the first name in each group, and
    return the rest as duplicates to quarantine.
    """
    # your code here
    raise NotImplementedError


def main(argv=None):
    parser = argparse.ArgumentParser(description="Survey and file a practice inbox.")
    parser.add_argument("--folder", required=True, help="the practice folder to work in")
    parser.add_argument(
        "--apply",
        action="store_true",
        help="actually move files; without this the program only reports",
    )
    args = parser.parse_args(argv)

    folder = pathlib.Path(args.folder).resolve()
    if not folder.is_dir():
        print(f"refused: {folder} is not a directory")
        return 2

    files, folders = survey(folder)
    print(f"surveyed {folder}")
    print(f"  files: {len(files)}")
    print(f"  folders: {len(folders)}")

    keep, duplicates = plan_duplicates(folder, files)
    moves, collisions = plan_renames([folder / name for name in keep])

    for name in duplicates:
        print(f"  would quarantine {name} (same contents as a file being kept)")
    for source, target in moves:
        if source != target:
            print(f"  would rename {source} -> {target}")

    if collisions:
        for target in collisions:
            print(f"refused: more than one file wants the name {target}")
        return 2

    if not args.apply:
        print("dry run: nothing was changed. Add --apply to do it.")
        return 0

    quarantine = folder.parent / "quarantine"
    quarantine.mkdir(exist_ok=True)
    for name in duplicates:
        os.replace(folder / name, quarantine / name)
    for source, target in moves:
        if source != target:
            os.replace(folder / source, folder / target)
    print(f"applied: {len(duplicates)} quarantined, {sum(1 for s, t in moves if s != t)} renamed")
    return 0


if __name__ == "__main__":
    sys.exit(main())
