#!/usr/bin/env python3
"""odysseus — one entrypoint for every odysseus-* CLI.

Discovers `scripts/odysseus-<name>` siblings and dispatches to them, the
same way `git` finds `git-foo`. Pure passthrough: any flags after the
subcommand name are forwarded as-is, so `odysseus mail list --pretty`
behaves exactly like `odysseus-mail list --pretty`.

    odysseus                       # list every subcommand + short help
    odysseus <name>                # run odysseus-<name>
    odysseus <name> <args...>      # run odysseus-<name> <args...>
    odysseus help                  # alias for `odysseus` (the listing)
    odysseus help <name>           # show the subcommand's own --help
    odysseus --version             # print version

Designed to live in `scripts/`. Symlink it onto `$PATH` (`ln -s
$PWD/scripts/odysseus ~/.local/bin/odysseus`) to use it without typing
the full path.
"""
from __future__ import annotations

import os
import re
import subprocess
import sys
from pathlib import Path

VERSION = "0.1.0"

SCRIPTS_DIR = Path(__file__).resolve().parent


def _list_subcommands() -> list[Path]:
    """Find every executable `odysseus-*` next to this file (excluding
    the dispatcher itself + any .bak / .pre-* migration leftovers)."""
    out = []
    for p in sorted(SCRIPTS_DIR.iterdir()):
        if not p.is_file():
            continue
        if p.name == "odysseus":
            continue
        if not p.name.startswith("odysseus-"):
            continue
        if any(p.name.endswith(suf) for suf in (".bak", ".pre-cli-refactor", ".pyc")):
            continue
        if not os.access(p, os.X_OK):
            continue
        out.append(p)
    return out


def _short_help(path: Path) -> str:
    """Pull the first non-blank line of the docstring (after the shebang)
    as a 1-line description. Falls back to '(no description)'."""
    try:
        text = path.read_text()
    except Exception:
        return "(unreadable)"
    m = re.search(r'"""(.*?)"""', text, re.DOTALL)
    if not m:
        return ""
    body = m.group(1).strip()
    if not body:
        return ""
    # First non-blank line, strip the leading "name — " noise.
    first = next((ln for ln in body.splitlines() if ln.strip()), "")
    first = re.sub(r"^odysseus-\w+\s*—\s*", "", first).strip()
    return first


def _print_listing() -> None:
    """`odysseus` with no args (or `odysseus help`) — print the table."""
    sys.stdout.write(f"odysseus {VERSION} — every feature, on the shell.\n\n")
    sys.stdout.write("Usage:  odysseus <subcommand> [args...]\n\n")
    sys.stdout.write("Available subcommands:\n")
    subs = _list_subcommands()
    width = max((len(p.name[len("odysseus-"):]) for p in subs), default=10)
    for p in subs:
        name = p.name[len("odysseus-"):]
        desc = _short_help(p)
        sys.stdout.write(f"  {name:<{width + 2}}{desc}\n")
    sys.stdout.write(
        "\nRun `odysseus help <subcommand>` for that tool's own --help.\n"
    )


def main(argv: list[str] | None = None) -> int:
    argv = list(sys.argv[1:] if argv is None else argv)

    if not argv or argv[0] in ("-h", "--help", "help") and len(argv) == 1:
        _print_listing()
        return 0

    if argv[0] in ("-v", "--version"):
        sys.stdout.write(f"odysseus {VERSION}\n")
        return 0

    if argv[0] == "help":
        # `odysseus help foo` → `odysseus-foo --help`
        if len(argv) < 2:
            _print_listing()
            return 0
        sub = SCRIPTS_DIR / f"odysseus-{argv[1]}"
        if not sub.exists():
            sys.stderr.write(f"odysseus: unknown subcommand {argv[1]!r}\n")
            return 1
        return subprocess.call([str(sub), "--help"])

    # `odysseus foo ...` → exec `odysseus-foo ...` under the project venv.
    name = argv[0]
    sub = SCRIPTS_DIR / f"odysseus-{name}"
    if not sub.exists():
        sys.stderr.write(
            f"odysseus: unknown subcommand {name!r}. "
            f"Try `odysseus help` to see available ones.\n"
        )
        return 1
    # Run the subcommand with the project's venv Python so dependencies
    # (bcrypt, sqlalchemy, fastapi, ...) resolve. Fall back to whatever
    # `python` is on PATH if no venv is found — useful in container
    # installs that wire the deps system-wide.
    repo_root = SCRIPTS_DIR.parent
    venv_python = repo_root / "venv" / "bin" / "python"
    py = str(venv_python) if venv_python.exists() else sys.executable
    os.execv(py, [py, str(sub)] + argv[1:])
    return 0  # unreachable


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