#!/usr/bin/env python3
"""Copy a UF2 artifact to a detected RP2040 mass-storage mount."""

from __future__ import annotations

import argparse
import os
import shutil
import sys
import time
from pathlib import Path

INFO_FILE = "INFO_UF2.TXT"


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--source", type=Path, required=True, help="Path to the UF2 file to copy")
    parser.add_argument("--timeout", type=float, default=10.0, help="Seconds to wait for the mount")
    parser.add_argument(
        "--mount",
        type=str,
        default=os.environ.get("MOUNT", ""),
        help="Explicit mount point (default: auto-detect)",
    )
    return parser.parse_args()


def candidate_paths(explicit: str, user: str) -> list[Path]:
    paths: list[Path] = []
    if explicit:
        paths.append(Path(explicit))
    roots = [
        Path("/Volumes"),
        Path("/media"),
        Path(f"/media/{user}"),
        Path("/run/media"),
        Path(f"/run/media/{user}"),
    ]
    for root in roots:
        if not root.exists() or not root.is_dir():
            continue
        for child in root.iterdir():
            if child.is_dir():
                paths.append(child)
    return paths


def choose_mount(explicit: str, user: str) -> Path | None:
    candidates = candidate_paths(explicit, user)
    if explicit:
        path = Path(explicit)
        return path if path.exists() and path.is_dir() else None
    info_candidates = [path for path in candidates if (path / INFO_FILE).exists()]
    if info_candidates:
        return info_candidates[0]
    for path in candidates:
        if path.exists() and path.is_dir():
            return path
    return None


def main() -> int:
    args = parse_args()
    source = args.source
    if not source.exists():
        print(f"UF2 source file not found: {source}", file=sys.stderr)
        return 1

    explicit_mount = args.mount.strip()
    user = os.environ.get("USER", "")
    deadline = time.time() + float(args.timeout)

    while time.time() <= deadline:
        mount = choose_mount(explicit_mount, user)
        if mount is not None:
            if not mount.exists() or not mount.is_dir():
                time.sleep(1)
                continue
            destination = mount / source.name
            try:
                shutil.copy2(source, destination)
                try:
                    if hasattr(os, "sync"):
                        os.sync()
                except Exception:
                    pass
                time.sleep(0.5)
            except Exception as exc:  # noqa: BLE001
                print(f"Failed to copy UF2 to {destination}: {exc}", file=sys.stderr)
                return 1
            print(f"Copied {source} to {destination}")
            return 0
        time.sleep(1)

    if explicit_mount:
        print(
            f"Mount point '{explicit_mount}' not found within {args.timeout} seconds",
            file=sys.stderr,
        )
    else:
        print(
            "Unable to detect RP2040 UF2 mount. Pass one via mount=/path",
            file=sys.stderr,
        )
    return 1


if __name__ == "__main__":  # pragma: no cover
    sys.exit(main())
