"""Install a stable ~/.local/bin/axi shim that execs the venv axi binary.

Motivation
----------
`axi` is normally installed into a project-local venv (e.g.
`~/Projects/FOO/.venv/bin/axi`).  That path is not on PATH for non-interactive
SSH sessions, which breaks the federation discovery SSH runner.  A tiny shim
dropped at `~/.local/bin/axi` (a conventional user-local PATH location) gives
remote peers a stable location to invoke without filesystem-walking.

Design
------
- Idempotent: if the shim already points at the same target, do nothing.
- Conflict-aware: if the shim points at a DIFFERENT target, we print a loud
  warning and refuse to overwrite unless ``force=True``.  Two venvs competing
  for a single shim is a real smell — the operator should pick one.
- Testable: ``write_shim`` accepts ``home_override`` so tests don't touch the
  real ``~/.local/bin``.
"""

from __future__ import annotations

import os
import shutil
import sys
from dataclasses import dataclass
from pathlib import Path


SHIM_TEMPLATE = """#!/usr/bin/env bash
# Auto-generated by `axi install-shim`.  Do not edit by hand.
# Re-run `axi install-shim` to regenerate or repoint this shim.
exec "{target}" "$@"
"""


@dataclass
class ShimResult:
    path: Path
    written: bool
    conflict: bool
    previous_target: Path | None = None


def resolve_current_axi() -> Path | None:
    """Locate the currently-running (or PATH-resolvable) axi binary.

    Preference:
      1. sys.argv[0] if it resolves to a real executable named 'axi'.
      2. shutil.which('axi').
    Returns None if neither works.
    """
    argv0 = sys.argv[0] if sys.argv else ""
    if argv0:
        p = Path(argv0).resolve()
        if p.is_file() and os.access(p, os.X_OK) and p.name == "axi":
            return p
    which = shutil.which("axi")
    if which:
        return Path(which).resolve()
    return None


def _parse_exec_target(shim_text: str) -> Path | None:
    """Extract the target path from an existing shim script, if present."""
    for line in shim_text.splitlines():
        line = line.strip()
        if line.startswith("exec "):
            # Expecting:   exec "<path>" "$@"
            rest = line[len("exec ") :].strip()
            if rest.startswith('"'):
                end = rest.find('"', 1)
                if end > 0:
                    return Path(rest[1:end])
    return None


def write_shim(
    target_axi: Path,
    home_override: Path | None = None,
    force: bool = False,
) -> ShimResult:
    """Write (or refresh) ~/.local/bin/axi to exec ``target_axi``.

    Parameters
    ----------
    target_axi:
        Absolute path to the venv-installed axi binary this shim should exec.
    home_override:
        Optional alternate HOME root (for tests).  If None, uses ``Path.home()``.
    force:
        When True, overwrite even if an existing shim points at a different
        target.  When False (default), a conflicting shim is left in place and
        a ShimResult with ``conflict=True`` is returned.
    """
    target_axi = Path(target_axi).resolve()
    home = Path(home_override) if home_override is not None else Path.home()
    local_bin = home / ".local" / "bin"
    local_bin.mkdir(parents=True, exist_ok=True)
    shim_path = local_bin / "axi"

    desired = SHIM_TEMPLATE.format(target=target_axi)

    previous_target: Path | None = None
    if shim_path.exists():
        existing = shim_path.read_text()
        previous_target = _parse_exec_target(existing)
        if existing == desired:
            # Perfectly idempotent — nothing to do.
            return ShimResult(
                path=shim_path,
                written=False,
                conflict=False,
                previous_target=previous_target,
            )
        if previous_target is not None and previous_target != target_axi and not force:
            return ShimResult(
                path=shim_path,
                written=False,
                conflict=True,
                previous_target=previous_target,
            )

    shim_path.write_text(desired)
    shim_path.chmod(0o755)
    return ShimResult(
        path=shim_path,
        written=True,
        conflict=False,
        previous_target=previous_target,
    )


def path_contains_local_bin(local_bin: Path, path_env: str | None = None) -> bool:
    """Return True if ``local_bin`` is present in the PATH environment string."""
    if path_env is None:
        path_env = os.environ.get("PATH", "")
    local_bin = Path(local_bin).resolve()
    for entry in path_env.split(os.pathsep):
        if not entry:
            continue
        try:
            if Path(entry).resolve() == local_bin:
                return True
        except OSError:
            continue
    return False
