"""A wrapper for the `rsync` command."""

import json
import os
import pathlib
import sys

from . import util


def check_path(path: pathlib.Path, base: pathlib.Path) -> None:
    """Validate a source or destination path."""
    print(f"Validating {path} under {base}")
    if not path.is_absolute():
        sys.exit(f"rsync wrapper invoked with non-absolute path {path}")
    if (path.exists() or path.is_symlink()) and not path.is_dir():
        sys.exit(f"rsync wrapper invoked with bad path {path}")

    try:
        path.relative_to(base)
    except ValueError:
        sys.exit(f"rsync wrapper invoked with path {path} not under {base}")


def main() -> None:
    """Wrap the `rsync` command, check for some things before and after."""
    print("rsync wrapper invoked as " + util.cmdstr(sys.argv))
    state_file = pathlib.Path(os.environ["REPOPUSH_TEST_STATE"])
    state_data = json.loads(state_file.read_text(encoding="UTF-8"))

    state_data["steps"] += 1
    state_file.write_text(json.dumps(state_data), encoding="UTF-8")

    if state_data["noop"]:
        if "-n" not in sys.argv:
            sys.exit("rsync wrapper invoked without `-n`")
    else:
        if "-n" in sys.argv:
            sys.exit("rsync wrapper invoked with `-n")

    if "-az" not in sys.argv:
        sys.exit("rsync wrapper invoked without `-az`")

    if len(sys.argv) < 5:
        sys.exit("rsync wrapper invoked with too few arguments")

    if sys.argv[-3] != "--":
        sys.exit("rsync wrapper invoked without `-- path path`")

    src_path = pathlib.Path(sys.argv[-2])
    dst_path = pathlib.Path(sys.argv[-1])
    check_path(src_path, state_data["src"])
    check_path(dst_path, state_data["dst"])

    expected_steps = util.expected_steps(pathlib.Path(state_data["src"]))
    step = state_data["steps"]
    print(f"Step {step} of {expected_steps}")
    if step > expected_steps:
        sys.exit(
            f"rsync wrapper invoked for step {step}, "
            f"only expected {expected_steps}"
        )
    if step == expected_steps:
        if "--delete" not in sys.argv:
            sys.exit(
                "rsync wrapper invoked without `--delete` on the last step"
            )
    else:
        if "--delete" in sys.argv:
            sys.exit(
                "rsync wrapper invoked with `--delete` before the last step"
            )

    rsync = os.environ["REPOPUSH_TEST_RSYNC"]
    os.execv(rsync, [rsync] + sys.argv[1:])


if __name__ == "__main__":
    main()
