#!/usr/bin/env python3
"""
Multi-Agent Pipeline: Cleanup Worktree.

Usage:
    python3 cleanup.py <branch-name>      Remove specific worktree
    python3 cleanup.py --list             List all worktrees
    python3 cleanup.py --merged           Remove merged worktrees
    python3 cleanup.py --all              Remove all worktrees (with confirmation)

Options:
    -y, --yes                       Skip confirmation prompts
    --keep-branch                   Don't delete the git branch

This script:
1. Archives task directory to archive/{YYYY-MM}/
2. Removes agent from registry
3. Removes git worktree
4. Optionally deletes git branch
"""

from __future__ import annotations

import argparse
import shutil
import subprocess
import sys
from pathlib import Path

# Add parent directory to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))

from common.git_context import _run_git_command
from common.paths import get_repo_root
from common.registry import (
    registry_get_file,
    registry_get_task_dir,
    registry_remove_by_id,
    registry_remove_by_worktree,
    registry_search_agent,
)
from common.task_utils import (
    archive_task_complete,
    is_safe_task_path,
)

# =============================================================================
# Colors
# =============================================================================


class Colors:
    RED = "\033[0;31m"
    GREEN = "\033[0;32m"
    YELLOW = "\033[1;33m"
    BLUE = "\033[0;34m"
    NC = "\033[0m"


def log_info(msg: str) -> None:
    print(f"{Colors.BLUE}[INFO]{Colors.NC} {msg}")


def log_success(msg: str) -> None:
    print(f"{Colors.GREEN}[SUCCESS]{Colors.NC} {msg}")


def log_warn(msg: str) -> None:
    print(f"{Colors.YELLOW}[WARN]{Colors.NC} {msg}")


def log_error(msg: str) -> None:
    print(f"{Colors.RED}[ERROR]{Colors.NC} {msg}")


# =============================================================================
# Helper Functions
# =============================================================================


def confirm(prompt: str, skip_confirm: bool) -> bool:
    """Ask for confirmation."""
    if skip_confirm:
        return True

    if not sys.stdin.isatty():
        log_error("Non-interactive mode detected. Use -y to skip confirmation.")
        return False

    response = input(f"{prompt} [y/N] ")
    return response.lower() in ("y", "yes")


# =============================================================================
# Commands
# =============================================================================


def cmd_list(repo_root: Path) -> int:
    """List worktrees."""
    print(f"{Colors.BLUE}=== Git Worktrees ==={Colors.NC}")
    print()

    subprocess.run(["git", "worktree", "list"], cwd=repo_root)
    print()

    # Show registry info
    registry_file = registry_get_file(repo_root)
    if registry_file and registry_file.is_file():
        print(f"{Colors.BLUE}=== Registered Agents ==={Colors.NC}")
        print()

        import json

        data = json.loads(registry_file.read_text(encoding="utf-8"))
        agents = data.get("agents", [])

        if agents:
            for agent in agents:
                print(
                    f"  {agent.get('id', '?')}: PID={agent.get('pid', '?')} [{agent.get('worktree_path', '?')}]"
                )
        else:
            print("  (none)")
        print()

    return 0


def archive_task(worktree_path: str, repo_root: Path) -> None:
    """Archive task directory."""
    task_dir = registry_get_task_dir(worktree_path, repo_root)

    if not task_dir or not is_safe_task_path(task_dir, repo_root):
        return

    task_dir_abs = repo_root / task_dir
    if not task_dir_abs.is_dir():
        return

    result = archive_task_complete(task_dir_abs, repo_root)
    if "archived_to" in result:
        dest = Path(result["archived_to"])
        log_success(f"Archived task: {dest.name} -> archive/{dest.parent.name}/")


def cleanup_registry_only(search: str, repo_root: Path, skip_confirm: bool) -> int:
    """Cleanup from registry only (no worktree)."""
    agent_info = registry_search_agent(search, repo_root)

    if not agent_info:
        log_error(f"No agent found in registry matching: {search}")
        return 1

    agent_id = agent_info.get("id", "?")
    task_dir = agent_info.get("task_dir", "?")

    print()
    print(f"{Colors.BLUE}=== Cleanup Agent (no worktree) ==={Colors.NC}")
    print(f"  Agent ID:  {agent_id}")
    print(f"  Task Dir:  {task_dir}")
    print()

    if not confirm("Archive task and remove from registry?", skip_confirm):
        log_info("Aborted")
        return 0

    # Archive task directory if exists
    if task_dir and is_safe_task_path(task_dir, repo_root):
        task_dir_abs = repo_root / task_dir
        if task_dir_abs.is_dir():
            result = archive_task_complete(task_dir_abs, repo_root)
            if "archived_to" in result:
                dest = Path(result["archived_to"])
                log_success(
                    f"Archived task: {dest.name} -> archive/{dest.parent.name}/"
                )
    else:
        log_warn("Invalid task_dir in registry, skipping archive")

    # Remove from registry
    registry_remove_by_id(agent_id, repo_root)
    log_success(f"Removed from registry: {agent_id}")

    log_success("Cleanup complete")
    return 0


def cleanup_worktree(
    branch: str, repo_root: Path, skip_confirm: bool, keep_branch: bool
) -> int:
    """Cleanup single worktree."""
    # Find worktree path for branch
    _, worktree_list, _ = _run_git_command(
        ["worktree", "list", "--porcelain"], cwd=repo_root
    )

    worktree_path = None
    current_worktree = None

    for line in worktree_list.splitlines():
        if line.startswith("worktree "):
            current_worktree = line[9:]  # Remove "worktree " prefix
        elif line.startswith("branch refs/heads/"):
            current_branch = line[18:]  # Remove "branch refs/heads/" prefix
            if current_branch == branch:
                worktree_path = current_worktree
                break

    if not worktree_path:
        # No worktree found, try to cleanup from registry only
        log_warn(f"No worktree found for: {branch}")
        log_info("Trying to cleanup from registry...")
        return cleanup_registry_only(branch, repo_root, skip_confirm)

    print()
    print(f"{Colors.BLUE}=== Cleanup Worktree ==={Colors.NC}")
    print(f"  Branch:   {branch}")
    print(f"  Worktree: {worktree_path}")
    print()

    if not confirm("Remove this worktree?", skip_confirm):
        log_info("Aborted")
        return 0

    # 1. Archive task
    archive_task(worktree_path, repo_root)

    # 2. Remove from registry
    registry_remove_by_worktree(worktree_path, repo_root)
    log_info("Removed from registry")

    # 3. Remove worktree
    log_info("Removing worktree...")
    ret, _, _ = _run_git_command(
        ["worktree", "remove", worktree_path, "--force"], cwd=repo_root
    )
    if ret != 0:
        # Try removing directory manually
        try:
            shutil.rmtree(worktree_path)
        except Exception as e:
            log_error(f"Failed to remove worktree: {e}")

    log_success("Worktree removed")

    # 4. Delete branch (optional)
    if not keep_branch:
        log_info("Deleting branch...")
        ret, _, _ = _run_git_command(["branch", "-D", branch], cwd=repo_root)
        if ret != 0:
            log_warn("Could not delete branch (may be checked out elsewhere)")

    log_success(f"Cleanup complete for: {branch}")
    return 0


def cmd_merged(repo_root: Path, skip_confirm: bool, keep_branch: bool) -> int:
    """Cleanup merged worktrees."""
    # Get main branch
    _, head_out, _ = _run_git_command(
        ["symbolic-ref", "refs/remotes/origin/HEAD"], cwd=repo_root
    )
    main_branch = head_out.strip().replace("refs/remotes/origin/", "") or "main"

    print(f"{Colors.BLUE}=== Finding Merged Worktrees ==={Colors.NC}")
    print()

    # Get merged branches
    _, merged_out, _ = _run_git_command(
        ["branch", "--merged", main_branch], cwd=repo_root
    )
    merged_branches = []
    for line in merged_out.splitlines():
        branch = line.strip().lstrip("* ")
        if branch and branch != main_branch:
            merged_branches.append(branch)

    if not merged_branches:
        log_info("No merged branches found")
        return 0

    # Get worktree list
    _, worktree_list, _ = _run_git_command(["worktree", "list"], cwd=repo_root)

    worktree_branches = []
    for branch in merged_branches:
        if f"[{branch}]" in worktree_list:
            worktree_branches.append(branch)
            print(f"  - {branch}")

    if not worktree_branches:
        log_info("No merged worktrees found")
        return 0

    print()
    if not confirm("Remove these merged worktrees?", skip_confirm):
        log_info("Aborted")
        return 0

    for branch in worktree_branches:
        cleanup_worktree(branch, repo_root, True, keep_branch)

    return 0


def cmd_all(repo_root: Path, skip_confirm: bool, keep_branch: bool) -> int:
    """Cleanup all worktrees."""
    print(f"{Colors.BLUE}=== All Worktrees ==={Colors.NC}")
    print()

    # Get worktree list
    _, worktree_list, _ = _run_git_command(
        ["worktree", "list", "--porcelain"], cwd=repo_root
    )

    worktrees = []
    main_worktree = str(repo_root.resolve())

    for line in worktree_list.splitlines():
        if line.startswith("worktree "):
            wt = line[9:]
            if wt != main_worktree:
                worktrees.append(wt)

    if not worktrees:
        log_info("No worktrees to remove")
        return 0

    for wt in worktrees:
        print(f"  - {wt}")

    print()
    print(f"{Colors.RED}WARNING: This will remove ALL worktrees!{Colors.NC}")

    if not confirm("Are you sure?", skip_confirm):
        log_info("Aborted")
        return 0

    # Get branch for each worktree
    for wt in worktrees:
        # Find branch name from worktree list
        _, wt_list, _ = _run_git_command(["worktree", "list"], cwd=repo_root)
        for line in wt_list.splitlines():
            if wt in line:
                # Extract branch from [branch] format
                import re

                match = re.search(r"\[([^\]]+)\]", line)
                if match:
                    branch = match.group(1)
                    cleanup_worktree(branch, repo_root, True, keep_branch)
                break

    return 0


# =============================================================================
# Main
# =============================================================================


def main() -> int:
    """Main entry point."""
    parser = argparse.ArgumentParser(
        description="Multi-Agent Pipeline: Cleanup Worktree"
    )
    parser.add_argument("branch", nargs="?", help="Branch name to cleanup")
    parser.add_argument("-y", "--yes", action="store_true", help="Skip confirmation")
    parser.add_argument(
        "--keep-branch", action="store_true", help="Don't delete git branch"
    )
    parser.add_argument("--list", action="store_true", help="List all worktrees")
    parser.add_argument("--merged", action="store_true", help="Remove merged worktrees")
    parser.add_argument("--all", action="store_true", help="Remove all worktrees")

    args = parser.parse_args()
    repo_root = get_repo_root()

    if args.list:
        return cmd_list(repo_root)
    elif args.merged:
        return cmd_merged(repo_root, args.yes, args.keep_branch)
    elif args.all:
        return cmd_all(repo_root, args.yes, args.keep_branch)
    elif args.branch:
        return cleanup_worktree(args.branch, repo_root, args.yes, args.keep_branch)
    else:
        print("""Usage:
  python3 cleanup.py <branch-name>      Remove specific worktree
  python3 cleanup.py --list             List all worktrees
  python3 cleanup.py --merged           Remove merged worktrees
  python3 cleanup.py --all              Remove all worktrees

Options:
  -y, --yes             Skip confirmation
  --keep-branch         Don't delete git branch
""")
        return 1


if __name__ == "__main__":
    sys.exit(main())
