"""Install attestation infrastructure in a repository."""

import os
from pathlib import Path

import click

from ..display.output import console, success, error, warning, info, panel
from ..hooks.agent_guidance import AGENT_FILE_MAP, detect_agents, write_agent_guidance
from ..hooks.installer import install_hooks, make_executable
from ..hooks.scripts import attestation_pre_commit_script, post_commit_upload_script, example_attestation
from ._shared import get_repo_root as _get_repo_root, load_local_config, migrate_gjalla_file_to_dir, ensure_gitignore

# Display labels for agent selection
_AGENT_LABELS: dict[str, str] = {
    "claude-code": "Claude Code",
    "gemini-cli": "Gemini CLI",
    "cursor": "Cursor",
    "codex": "Codex/OpenAI",
}


def _get_gjalla_config(repo_root: Path) -> dict | None:
    """Read .gjalla/config.yaml, handling old file-based and JSON formats."""
    migrate_gjalla_file_to_dir(repo_root)
    config = load_local_config(repo_root)
    return config or None


@click.command()
@click.option(
    "--hooks/--no-hooks",
    default=True,
    help="Install git hooks (default: yes).",
)
@click.option(
    "--yes", "-y",
    is_flag=True,
    help="Accept all defaults without prompting.",
)
def setup(hooks: bool, yes: bool) -> None:
    """Install attestation guardrails in this repository.

    Sets up the commit attestation gate:

    \b
    1. Verifies .gjalla project config exists
    2. Creates example attestation + hook scripts
    3. Updates .gitignore
    4. Optionally installs git hooks

    \b
    Examples:
        gjalla setup              # Full setup with hooks
        gjalla setup --no-hooks   # Scripts only, wire hooks yourself
    """
    repo_root = _get_repo_root()

    from ..display.output import bridge_banner
    bridge_banner()
    panel("gjalla Guardrails Setup", title="gjalla setup")
    console.print()

    # Step 1: Verify .gjalla config exists
    config = _get_gjalla_config(repo_root)
    if config is None:
        gjalla_dir = repo_root / ".gjalla"
        if not gjalla_dir.exists():
            error("No .gjalla config found. Run 'gjalla init' first.")
        else:
            error("Invalid .gjalla config. Run 'gjalla init' to recreate.")
        raise SystemExit(1)

    info(f"Project: {config.get('project_id', 'unknown')}")

    # Step 2: Write example attestation
    gjalla_dir = repo_root / ".gjalla"
    gjalla_dir.mkdir(parents=True, exist_ok=True)
    example_path = gjalla_dir / "example-attestation.yaml"
    example_path.write_text(example_attestation(), encoding="utf-8")
    success(f"Created {example_path.relative_to(repo_root)}")

    # Step 3: Write attestation scripts
    scripts_dir = repo_root / "scripts"
    scripts_dir.mkdir(exist_ok=True)

    pre_commit_path = scripts_dir / "gjalla-attestation-check.sh"
    pre_commit_path.write_text(attestation_pre_commit_script(), encoding="utf-8")
    make_executable(pre_commit_path)
    success(f"Created {pre_commit_path.relative_to(repo_root)}")

    post_commit_path = scripts_dir / "gjalla-post-commit-upload.sh"
    post_commit_path.write_text(post_commit_upload_script(), encoding="utf-8")
    make_executable(post_commit_path)
    success(f"Created {post_commit_path.relative_to(repo_root)}")

    # Step 4: Update .gitignore
    added = ensure_gitignore(repo_root, [".gjalla/.commit-attestation.yaml", ".gjalla/log.jsonl", ".gjalla/attestations/", ".gjalla/cache/"])
    if added:
        info(f"Added to .gitignore: {', '.join(added)}")

    # Step 5: Install hooks
    if hooks:
        result = install_hooks(
            repo_root,
            pre_commit_command="bash scripts/gjalla-attestation-check.sh",
            post_commit_command="bash scripts/gjalla-post-commit-upload.sh",
        )
        if result.pre_commit.status.value in ("installed", "added_to_existing", "updated"):
            success(f"Pre-commit hook: {result.pre_commit.message}")
        else:
            warning(f"Pre-commit hook: {result.pre_commit.message}")

        if result.post_commit.status.value in ("installed", "added_to_existing", "updated"):
            success(f"Post-commit hook: {result.post_commit.message}")
        else:
            warning(f"Post-commit hook: {result.post_commit.message}")
    else:
        info("Skipping hook installation (--no-hooks)")

    # Step 6: Agent guidance files
    project_id = str(config.get("project_id", "unknown"))
    _generate_agent_guidance(repo_root, project_id, yes)

    console.print()
    panel(
        "[green]Guardrails installed![/green]\n\n"
        "Agents must create .gjalla/.commit-attestation.yaml before committing.\n"
        "Example format: .gjalla/example-attestation.yaml\n"
        "Humans can skip with: SKIP_ATTESTATION=1 git commit ...\n\n"
        "[dim]If you use simple-git-hooks, husky, or pre-commit.org:[/dim]\n"
        "  pre-commit: bash scripts/gjalla-attestation-check.sh\n"
        "  post-commit: bash scripts/gjalla-post-commit-upload.sh",
        title="Setup Complete",
    )


def _generate_agent_guidance(repo_root: Path, project_id: str, yes: bool) -> None:
    """Generate agent instruction files with attestation guidance."""
    all_agents = list(AGENT_FILE_MAP.keys())
    detected = detect_agents(repo_root)

    if yes:
        # Auto mode: use detected agents, or all if none detected
        selected = detected if detected else all_agents
    else:
        # Interactive mode: prompt with detected agents pre-highlighted
        console.print()
        console.print("[bold]Agent instruction files[/bold]")
        console.print("Generate attestation guidance for your coding agents.")
        console.print()
        for i, agent in enumerate(all_agents, 1):
            label = _AGENT_LABELS.get(agent, agent)
            marker = " [dim](detected)[/dim]" if agent in detected else ""
            console.print(f"  {i}. {label}{marker}  →  {AGENT_FILE_MAP[agent]}")
        console.print()

        choices = click.prompt(
            "Which agents? (comma-separated numbers, or 'none' to skip)",
            default=",".join(str(i) for i, a in enumerate(all_agents, 1) if a in detected) if detected else "none",
        )

        if choices.strip().lower() == "none":
            info("Skipping agent guidance generation")
            return

        selected = []
        for part in choices.split(","):
            part = part.strip()
            if part.isdigit():
                idx = int(part) - 1
                if 0 <= idx < len(all_agents):
                    selected.append(all_agents[idx])

        if not selected:
            info("No valid agents selected — skipping")
            return

    for agent in selected:
        path = write_agent_guidance(repo_root, agent, project_id)
        success(f"Agent guidance: {path.relative_to(repo_root)}")
