"""
Run as ``python -m fiwi.fiwi_relay`` — builds :class:`~.host.FiWiRelay` from config and calls :meth:`~.host.FiWiRelay.setup`.
"""

from __future__ import annotations

import argparse
import os
import sys

_ROOT = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", ".."))
if _ROOT not in sys.path:
    sys.path.insert(0, _ROOT)


def main() -> int:
    p = argparse.ArgumentParser(
        description="Fi-Wi hub relay: FiWiRelay.setup() over SSH or locally (auto when user@host is this machine).",
    )
    p.add_argument(
        "-c",
        "--config",
        metavar="PROFILE_OR_INI",
        help="INI profile or path (sets FIWI_CONFIG before loading config)",
    )
    p.add_argument(
        "--ssh",
        metavar="USER@HOST",
        help="Override SSH target (default: first host from merged [remote_hubs] / env); ignored with --local",
    )
    p.add_argument(
        "-n",
        "--name",
        metavar="LABEL",
        help="Override hub label (default: [remote_hubs] label or derived from host)",
    )
    p.add_argument(
        "--all",
        action="store_true",
        help="Run setup() on every configured remote host (local vs ssh auto per host)",
    )
    p.add_argument(
        "--timeout",
        type=float,
        default=600.0,
        metavar="SEC",
        help="SSH session timeout (default: 600)",
    )
    p.add_argument(
        "--dry-run",
        action="store_true",
        help="Print what would run; do not SSH / do not run bash",
    )
    p.add_argument(
        "--local",
        action="store_true",
        help="Force local execution (this machine); also used if from_config fails and no [remote_hubs]",
    )
    p.add_argument(
        "--remote",
        action="store_true",
        help="Force SSH even if this machine matches the configured user@host",
    )
    args = p.parse_args()
    if args.config:
        os.environ["FIWI_CONFIG"] = args.config.strip()
    if args.local and args.remote:
        print("FAIL: use only one of --local and --remote.", file=sys.stderr)
        return 2

    try:
        os.chdir(_ROOT)
    except OSError as exc:
        print(f"FAIL: cannot chdir to repo root {_ROOT!r}: {exc}", file=sys.stderr)
        return 1

    from fiwi.fiwi_relay.host import FiWiRelay

    try:
        if args.local and args.all:
            print("FAIL: --local does not support --all (would run local bootstrap for every listed host).", file=sys.stderr)
            return 2

        if args.all:
            hosts = FiWiRelay.each_from_config(_ROOT)
            if not hosts:
                print(
                    "No remote hosts in config. Set [remote_hubs] hosts or FIWI_REMOTE_HUBS.",
                    file=sys.stderr,
                )
                return 2
            rc = 0
            for h in hosts:
                use_local = not args.remote and FiWiRelay.ssh_target_points_here(h.ssh_target)
                mode = "local" if use_local else "ssh"
                print(f"\n--- {h.name} ({h.ssh_target}) [{mode}] ---\n", flush=True)
                code = h.setup(timeout=args.timeout, dry_run=args.dry_run, local=use_local)
                if code != 0:
                    rc = code
            return rc

        if args.local:
            try:
                host = FiWiRelay.from_config(_ROOT, ssh_target=args.ssh, name=args.name)
            except ValueError:
                host = FiWiRelay.for_local_machine(_ROOT, name=args.name)
            print(
                f"FiWiRelay(name={host.name!r}, ssh_target={host.ssh_target!r}, local=True) [forced --local]",
                flush=True,
            )
            return host.setup(timeout=args.timeout, dry_run=args.dry_run, local=True)

        host = FiWiRelay.from_config(_ROOT, ssh_target=args.ssh, name=args.name)
        use_local = not args.remote and FiWiRelay.ssh_target_points_here(host.ssh_target)
        if use_local:
            tag = " [auto local]"
        elif args.remote:
            tag = " [forced ssh]"
        else:
            tag = " [ssh]"
        print(f"FiWiRelay(name={host.name!r}, ssh_target={host.ssh_target!r}){tag}", flush=True)
        return host.setup(timeout=args.timeout, dry_run=args.dry_run, local=use_local)
    except ValueError as exc:
        print(f"FAIL: {exc}", file=sys.stderr)
        return 2


if __name__ == "__main__":
    raise SystemExit(main())
