#!/usr/bin/env python3
"""chuck-aider-init — generate .aider.conf.yml for the current Chuck project.

Writes an Aider config file that pre-loads Chuck's patch or snap_context as
read-only context, disables auto-commits, and opts out of gitignore
management (Chuck projects may not use git).

Also appends .aider* and .chuck/ to .gitignore when the project IS a git repo.

Usage:
    chuck-aider-init          # run in or below the Chuck root
    chuck-aider-init /path    # explicit path (must contain .chuck/)

Re-running overwrites .aider.conf.yml with current values (idempotent).

Note: If snap_context.md is selected, generate it first with:
    chuck snap > .chuck/snap_context.md
"""

from __future__ import annotations

import sys
from pathlib import Path


# ─── Helpers ──────────────────────────────────────────────────────────────────

def find_chuck_root(start: Path) -> Path | None:
    """Walk up from *start* looking for a .chuck/ directory."""
    for p in [start, *start.parents]:
        if (p / ".chuck").exists():
            return p
    return None


def select_read_file(chuck_root: Path) -> str:
    """Return the Chuck context file path to put in .aider.conf.yml.

    Prefers patch.md when it exists and is non-empty; falls back to
    snap_context.md (full snapshot with file contents, generated by
    `chuck snap > .chuck/snap_context.md`).

    Note: manifest.json is NOT used — it contains only metadata (paths,
    hashes, token counts) and provides no useful context to Aider.
    """
    patch_path = chuck_root / ".chuck" / "patch.md"
    if patch_path.exists():
        try:
            if patch_path.read_text(encoding="utf-8").strip():
                return ".chuck/patch.md"
        except OSError:
            pass
    return ".chuck/snap_context.md"


def write_aider_conf(chuck_root: Path) -> Path:
    """Write (or overwrite) .aider.conf.yml at the Chuck root.

    Returns the path that was written.
    """
    read_file = select_read_file(chuck_root)
    conf = (
        "# .aider.conf.yml — generated by chuck-aider-init\n"
        "# Re-run chuck-aider-init to refresh.\n"
        "read:\n"
        f"  - {read_file}\n"
        "auto-commits: false\n"
        "gitignore: false\n"
    )
    conf_path = chuck_root / ".aider.conf.yml"
    conf_path.write_text(conf, encoding="utf-8")
    return conf_path


def update_gitignore(chuck_root: Path) -> None:
    """Append .aider* and .chuck/ to .gitignore if this is a git repo.

    Silently skips when .git/ is absent.  Does not add lines that are
    already present (idempotent).
    """
    if not (chuck_root / ".git").exists():
        return

    gitignore_path = chuck_root / ".gitignore"
    existing = ""
    if gitignore_path.exists():
        try:
            existing = gitignore_path.read_text(encoding="utf-8")
        except OSError:
            return

    existing_lines = set(existing.splitlines())
    patterns = [".aider*", ".chuck/"]
    to_add = [p for p in patterns if p not in existing_lines]

    if not to_add:
        return

    with open(gitignore_path, "a", encoding="utf-8") as f:
        if existing and not existing.endswith("\n"):
            f.write("\n")
        f.write("\n# Chuck/Aider (added by chuck-aider-init)\n")
        for line in to_add:
            f.write(line + "\n")


# ─── Entry point ──────────────────────────────────────────────────────────────

def main() -> None:
    # Optional positional argument for an explicit path
    start = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else Path.cwd()

    chuck_root = find_chuck_root(start)
    if chuck_root is None:
        print(
            "chuck-aider-init: error: no .chuck/ directory found. Run: chuck init",
            file=sys.stderr,
        )
        sys.exit(1)

    conf_path = write_aider_conf(chuck_root)
    print(f"Written: {conf_path}")

    snap_context = chuck_root / ".chuck" / "snap_context.md"
    patch = chuck_root / ".chuck" / "patch.md"
    if not patch.exists() and not snap_context.exists():
        print(
            "chuck-aider-init: warning: .chuck/snap_context.md not found.\n"
            "  Generate it with: chuck snap > .chuck/snap_context.md",
            file=sys.stderr,
        )

    update_gitignore(chuck_root)


if __name__ == "__main__":
    main()
