#!/usr/bin/env python3
"""ACS menu bar app with local commit agent.

Manages a lightweight commit agent that discovers local repos, asks the
remote ACS daemon for LLM-generated commit messages, and commits+pushes.
Runs without the full auto_commit_service package — only needs httpx + rumps.

Usage:
    ./commits-tray --url http://apricot.local:8200 --cycle 300
    ./commits-tray --url http://apricot.local:8200 --commit-local --dry-run
    ./commits-tray --url http://apricot.local:8200 --commit-local  # for real
"""

import argparse
import json
import logging
import os
import sys
from pathlib import Path

# Add the tray module directory so we can import directly
_script_dir = os.path.dirname(os.path.abspath(__file__))
_tray_dir = os.path.join(_script_dir, "src", "auto_commit_service", "tray")
sys.path.insert(0, _tray_dir)


def _load_ignore_repos_from_config() -> list[str]:
    """Read ignore_repos from ~/.config/commits/startup-config.json.

    Mirrors the daemon's config loader (see auto_commit_service.__main__).
    Supports either a top-level `ignore_repos` array (shared) or a per-daemon
    entry whose `directory` matches the current working dir. Missing or
    unreadable files yield an empty list — never raises.
    """
    config_path = Path.home() / ".config" / "commits" / "startup-config.json"
    if not config_path.exists():
        return []
    try:
        data = json.loads(config_path.read_text())
    except (OSError, json.JSONDecodeError) as exc:
        logging.warning(f"commits-tray: failed to read {config_path}: {exc}")
        return []

    ignore: list[str] = []
    if isinstance(data.get("ignore_repos"), list):
        ignore.extend(str(p) for p in data["ignore_repos"] if p)

    cwd = str(Path.cwd())
    for daemon in data.get("daemons", []) or []:
        if isinstance(daemon, dict) and daemon.get("directory") == cwd:
            entries = daemon.get("ignore_repos")
            if isinstance(entries, list):
                ignore.extend(str(p) for p in entries if p)
            break

    # De-dup while preserving order
    seen: set[str] = set()
    deduped: list[str] = []
    for p in ignore:
        if p not in seen:
            seen.add(p)
            deduped.append(p)
    return deduped


def main():
    parser = argparse.ArgumentParser(description="ACS menu bar app + local commit agent")
    parser.add_argument(
        "--url", "-u",
        default="http://apricot.local:8200",
        help="Remote ACS daemon URL for LLM + recording (default: http://apricot.local:8200)",
    )
    parser.add_argument(
        "--repos", "-r",
        nargs="+",
        default=None,
        help="Base paths to scan for local git repos (default: ~/Code)",
    )
    parser.add_argument(
        "--cycle", "-c",
        type=int,
        default=300,
        help="Seconds between commit cycles (default: 300)",
    )
    parser.add_argument(
        "--commit-local",
        action="store_true",
        default=False,
        help="Enable local commit loop on this host (proxy mode). Default OFF.",
    )
    parser.add_argument(
        "--dry-run",
        action="store_true",
        default=False,
        help="Scan and generate messages but skip git commit/push. Useful for validation.",
    )
    parser.add_argument(
        "--max-diff-bytes",
        type=int,
        default=131072,
        help="Per-repo diff size cap in bytes before truncation (default: 131072)",
    )
    parser.add_argument(
        "--ignore-repo",
        action="append",
        default=[],
        dest="ignore_repos",
        help=(
            "Substring matched against absolute repo paths; matching repos "
            "are excluded from discovery. Repeat for multiple. Merged with "
            "ignore_repos from ~/.config/commits/startup-config.json."
        ),
    )
    args = parser.parse_args()

    ignore_repos = list(_load_ignore_repos_from_config()) + list(args.ignore_repos or [])

    # Import after argparse so --help exits cleanly before rumps is required
    from app import run_tray  # noqa: E402

    repos_paths = [Path(p).expanduser() for p in args.repos] if args.repos else None
    run_tray(
        daemon_url=args.url,
        repos_paths=repos_paths,
        commit_local=args.commit_local,
        dry_run=args.dry_run,
        max_diff_bytes=args.max_diff_bytes,
        cycle_seconds=args.cycle,
        ignore_repos=ignore_repos,
    )


if __name__ == "__main__":
    main()
