#!/usr/bin/env python3
"""
RalphLoop - "Tackle Until Solved" Autonomous Agent Loop

Integration of Ralph Orchestrator with Claude Code CLI.
This script runs an autonomous agent loop that continues until the task is complete.

Usage:
    ./ralphloop "Your task description here"
    ./ralphloop -i task.md
    ./ralphloop --agent claude --max-iterations 50

Environment Variables:
    ANTHROPIC_API_KEY    Required for Claude agent
    RALPH_AGENT          Override agent selection (claude, gemini, etc.)
    RALPH_MAX_ITERATIONS  Override max iterations (default: 100)
"""

import os
import sys
import subprocess
import argparse
import json
from pathlib import Path
from datetime import datetime

# Configuration
DEFAULT_AGENT = "claude"
DEFAULT_MAX_ITERATIONS = 100
DEFAULT_MAX_RUNTIME = 14400  # 4 hours

# Path to Ralph in venv
SCRIPT_DIR = Path(__file__).parent.parent
VENV_BIN = SCRIPT_DIR / ".venv" / "bin"
RALPH_CMD = str(VENV_BIN / "ralph")

def check_dependencies():
    """Check if Ralph Orchestrator is available."""
    try:
        result = subprocess.run(
            [RALPH_CMD, "run", "-h"],
            capture_output=True,
            text=True,
            timeout=5
        )
        if result.returncode == 0 or "usage:" in result.stdout:
            return True
    except (FileNotFoundError, subprocess.TimeoutExpired):
        pass

    # Fallback: check if pip package is installed
    try:
        import ralph_orchestrator
        return True
    except ImportError:
        return False

def create_ralph_project(task_description=None, task_file=None):
    """Create a Ralph project in the current directory."""
    ralph_dir = Path(".ralph")
    ralph_dir.mkdir(exist_ok=True)

    # Create prompt file
    prompt_file = Path("PROMPT.md")

    if task_file:
        # Read from file
        content = Path(task_file).read_text()
        prompt_file.write_text(content)
    elif task_description:
        # Use inline task
        prompt_file.write_text(f"# Task: {task_description}\n\n<!-- Ralph will continue iterating until task is complete -->\n\n## Success Criteria\n\nThe task is complete when:\n- All requirements are implemented\n- Tests pass\n- Code is documented\n\n<!-- When complete, add <!-- COMPLETE --> marker to this file -->")
    else:
        print("Error: Either provide task description or task file")
        sys.exit(1)

    # Create config file
    config_file = Path("ralph.yml")
    config = {
        "agent": os.getenv("RALPH_AGENT", DEFAULT_AGENT),
        "prompt_file": "PROMPT.md",
        "max_iterations": int(os.getenv("RALPH_MAX_ITERATIONS", DEFAULT_MAX_ITERATIONS)),
        "max_runtime": int(os.getenv("RALPH_MAX_RUNTIME", DEFAULT_MAX_RUNTIME)),
        "verbose": True,
        "adapters": {
            "claude": {
                "enabled": True,
                "timeout": 300
            }
        }
    }

    import yaml
    with open(config_file, "w") as f:
        yaml.dump(config, f, default_flow_style=False)

    print(f"✅ Ralph project initialized")
    print(f"   Prompt: {prompt_file}")
    print(f"   Config: {config_file}")

def run_ralph_loop(task=None, task_file=None, agent=None, max_iterations=None, max_runtime=None):
    """Run the Ralph autonomous loop."""
    print("🔄 RalphLoop: 'Tackle Until Solved' Autonomous Agent Loop")
    print("=" * 60)

    # Initialize project
    create_ralph_project(task, task_file)

    # Build command
    cmd = [RALPH_CMD, "run"]

    if agent:
        cmd.extend(["-a", agent])

    if max_iterations:
        cmd.extend(["-i", str(max_iterations)])

    if max_runtime:
        cmd.extend(["-t", str(max_runtime)])

    cmd.append("-v")  # Verbose output

    print(f"Command: {' '.join(cmd)}")
    print("=" * 60)

    # Run Ralph
    try:
        process = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            text=True,
            bufsize=1
        )

        # Stream output
        for line in process.stdout:
            print(line, end='', flush=True)

        process.wait()
        return process.returncode

    except KeyboardInterrupt:
        print("\n\n⚠️  Interrupted by user")
        return 130
    except Exception as e:
        print(f"❌ Error: {e}")
        return 1

def main():
    parser = argparse.ArgumentParser(
        description="RalphLoop - Autonomous agent loop for Claude Code CLI",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=__doc__
    )

    parser.add_argument(
        "task",
        nargs="?",
        help="Task description (inline)"
    )

    parser.add_argument(
        "-i", "--input",
        dest="task_file",
        help="Read task from file"
    )

    parser.add_argument(
        "-a", "--agent",
        choices=["claude", "kiro", "q", "gemini", "acp", "auto"],
        default=os.getenv("RALPH_AGENT", DEFAULT_AGENT),
        help="AI agent to use"
    )

    parser.add_argument(
        "--max-iterations",
        type=int,
        default=int(os.getenv("RALPH_MAX_ITERATIONS", DEFAULT_MAX_ITERATIONS)),
        help="Maximum iterations"
    )

    parser.add_argument(
        "--max-runtime",
        type=int,
        default=int(os.getenv("RALPH_MAX_RUNTIME", DEFAULT_MAX_RUNTIME)),
        help="Maximum runtime in seconds"
    )

    parser.add_argument(
        "--init-only",
        action="store_true",
        help="Only initialize project, don't run"
    )

    args = parser.parse_args()

    # Check dependencies
    if not check_dependencies():
        print("⚠️  Ralph Orchestrator not found at:", RALPH_CMD)
        print("\nTo install:")
        print(f"  .venv/bin/pip install ralph-orchestrator")
        print("\nFor now, creating project files only...")
        args.init_only = True

    # Initialize only mode
    if args.init_only:
        create_ralph_project(args.task, args.task_file)
        print("\n💡 To run the loop later:")
        print(f"   {RALPH_CMD} run")
        return 0

    # Run the loop
    return run_ralph_loop(
        task=args.task,
        task_file=args.task_file,
        agent=args.agent,
        max_iterations=args.max_iterations,
        max_runtime=args.max_runtime
    )

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